SpringCloud基础(4)

6 服务注册中心Consul

前文中介绍了Spring Cloud的核心组件,包括服务注册与发现组件Eureka,熔断器Hystrix,配置中心Spring Cloud Config和服务网关Zuul。

在前文的基础上进行工作。先将Spring Cloud的版本进行升级:将pom.xml中的parent模块版本升级为1.5.4.RELEASE,同时将spring-cloud-dependencies组件升级为Dalston.SR1版本。

Spring Cloud Consul是一个服务发现框架,与Eureka作用类似。当然常用的服务发现框架或者说服务注册中心还有Zookeeper,etcd等。对比图如下:
这里写图片描述

各个框架的具体差异就不讨论了,这里用Consul替换掉前文中的Eureka。

从官网https://www.consul.io/downloads.html下载consul服务注册中心。以开发模式启动consul:
consul agent –dev

打开http://localhost:8500,可以看到consul的ui界面。
将服务提供者的依赖模块替换:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

然后修改配置文件为:

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

服务接口修改为:

@RestController
public class ComputeController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    DiscoveryClient discoveryClient;

    @GetMapping("/dc")
    public String dc() {
        String services = "Services: " + discoveryClient.getServices();
        System.out.println(services);
        return services;
    }
}

服务消费者依赖:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

配置文件:

spring.application.name=consul-consumer
server.port=2101
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

服务消费者主类:

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        new SpringApplicationBuilder(ConsumerApplication.class).web(true).run(args);
    }
}

消费接口类:

@RestController
public class ConsumerController {

    @Resource
    LoadBalancerClient loadBalancerClient;

    @Resource
    RestTemplate restTemplate;

   @GetMapping("/consumer")
    public String dc() {
       ServiceInstance serviceInstance = loadBalancerClient.choose("consul-provider1");
       String url = "http://" + serviceInstance.getHost()+ ":" + serviceInstance.getPort() + "/dc";
       System.out.println(url);
       return restTemplate.getForObject(url, String.class);
   }
}

分别启动服务提供者和服务消费者,访问http://localhost:2101/consumer。返回Services: [consul, consul-consumer, consul-provider1]。
以上是以consul作为注册中心,如果采用eureka作为注册中心的话,除了eureka注册中心需要自己构建外,其他基本一样。

7 Hystrix监控

在前面介绍过,断路器根据快照时间窗口内的请求情况来判断是否需要进行熔断,而这些请求情况的指标信息都是HystrixCommand和HystrixObservableCommand实例在执行过程中记录的重要度量信息,它们除了Hystrix断路器实现中使用以外,对于系统运维也有非常大的帮助。这些指标信息会以“滚动时间窗”与“桶”结合的方式进行汇总,并在内存中驻留一段时间,以供内部或外部进行查询使用,Hystrix Dashboard就是这些指标内容的消费者。

创建一个服务实例my-consumer3。这里仍然以eureka为注册中心,添加依赖:

<parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
    </dependencies>

配置文件为:

spring.application.name=consumer3
server.port=2103
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

控制器为:

@RestController
public class ConsumerController {
    @Resource
    ConsumerService consumerService;
    @GetMapping("/consumer")
    public String dc() {
        return consumerService.consumer();
    }
    @Service
    class ConsumerService {
        @Resource
        RestTemplate restTemplate;
        @HystrixCommand(fallbackMethod = "fallback")
        public String consumer() {
            return restTemplate.getForObject("http://compute-service/add?a=1&b=2", String.class);
        }
        public String fallback() {
            return "fallbck";
        }
    }
}

主类需要开启@EnableCircuitBreaker注解:

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ConsumerApplication3 {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication3.class,args);
    }
}

启动服务注册中心和compute-service服务实例及本实例之后,可以通过调用本实例提供的consumer接口进而调用compute-service服务。

接着创建mysc-hystrixdashboard实例。依赖:

<parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
</dependencies>

配置文件:

spring.application.name=hystrix-dashboard
server.port=1301

主类:

@SpringCloudApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {

    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class,args);
    }
}

实际上,官方也提供了监控包:hystrix-dashboard-#.#.#.war,下载后放到服务器上,一样地使用。不过这里为了方便就使用自己创建的监控实例。

启动hystrix监控实例,访问http://localhost:1301后可以看到Hystrix Dashboard首页。从首页描述可以得知,Hystrix Dashboard支持三种不同的监控方式,分别是:

默认的集群监控:通过URLhttp://turbine-hostname:port/turbine.stream开启,实现对默认集群的监控。
指定的集群监控:通过URLhttp://turbine-hostname:port/turbine.stream?cluster=[clusterName]开启,实现对clusterName集群的监控。
单体应用的监控:通过URLhttp://hystrix-app:port/hystrix.stream开启,实现对具体某个服务实例的监控。

对集群的监控需要整合turbine才能实现。这里先看对单个服务实例的监控。再consumer3实例中引入了actuator和hystrix依赖包,因此可以实现对该实例的hystrix监控。

7.1 单实例监控

启动consumer3,调用一次consumer3提供的consumer接口(如果一次都没调用,监控页面就一直在loading中)。接着访问http://localhost:1301/hystrix,在输入框中输入要监控的实例地址:http://localhost:2103/hystrix.stream,可以看到该实例的hystrix监控信息。

监控台首页中有两个参数,分别是Delay和Title。其中Delay是用来控制服务器上轮询监控信息的延迟时间,默认为2000毫秒,可以通过配置该属性降低客户端的网络和cpu消耗。Title对应了监控地址的内容,默认使用具体监控实例的url,可以通过配置该信息来展示更合适的标题。

具体实例的监控页面可以看到一个实心圆和一条曲线。

实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,其健康度从绿色,黄色,橙色。红色依次递减。同时,实心圆的大小随着请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的大小和颜色,可以在大量实例中快速发现故障实例和高压力实例。

曲线:用来记录两分钟内流量的相对变化,可以通过它来观察流量的上升和下降趋势。

其他:竖线隔开的两列数字,左边的依次代表请求成功数,短路和熔断数。右边的依次代表请求超时数,线程池拒绝数和失败/异常数。右边百分数代表最近10秒的错误比例。Host和Cluster数值表示该主机和集群上的请求频率,Circuit表示断路器状态。最下面左侧的是集群下的主机报告,右侧的是百分比延迟统计。

7.2 监控数据聚合

在实际的生产环境中有多个实例,对多实例需要将度量指标数据进行聚合,因此需要整合turbine。
在前文的hystrix监控例子中,实现的架构如下图所示:
这里写图片描述
在上述架构基础上,引入Turbine来对服务的Hystrix数据进行聚合展示。聚合方式有两种。
通过HTTP收集聚合
创建turbine工程,依赖为:

<parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-turbine</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
</dependencies>

创建应用主类TurbineApplication,并使用@EnableTurbine注解开启Turbine:

@Configuration
@EnableAutoConfiguration
@EnableTurbine
@EnableDiscoveryClient
public class TurbineApplication {
    public static void main(String[] args) {
        SpringApplication.run(TurbineApplication.class, args);
    }
}

在application.properties加入eureka和turbine的相关配置,具体如下:

spring.application.name=turbine
server.port=8989
management.port=8990
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
turbine.app-config=consumer3
turbine.cluster-name-expression="default"
turbine.combine-host-port=true

参数说明:
turbine.app-config指定了需要收集监控信息的服务名。
turbine.cluster-name-expression指定了集群名称为default,当服务数量非常多时,可以启动多个turbine服务来构建不同的聚合集群,而该参数可以用来区分这些不同的聚合集群,同时该参数可以在Hystrix仪表盘中定位不同的聚合集群,只需要在Hystrix Stream的URL中通过cluster参数来指定。
turbine.combine-host-port设置为true,可以让同一主机上的服务通过主机名与端口号的组合来进行区分,默认情况下以host来区分不同的服务,这会使得在本地调试时本机上的不同服务聚合成一个服务来统计。

启动服务注册中心server1和server2,服务提供者provider2,服务消费者consumer3,Hystrix监控以及turbine聚合实例,在http://localhost:1301/hystrix监控首页中输入http://localhost:8989/turbine.stream后进行监控,将会看到针对服务consumer3的聚合数据监控。架构为:
这里写图片描述

通过消息代理收集聚合
Spring Cloud在封装turbine的时候,还实现了基于消息代理的收集实现。因此可以将所有需要收集的监控信息都输出到消息代理中,然后turbine服务再从消息代理中异步的获取这些监控信息,最后将这些监控信息聚合并输出到Hystrix Dashboard中。通过引入消息代理,Turbine和Hystrix Dashboard实现的监控架构可以改成如下:
这里写图片描述

创建一个maven工程,名为mysc-turbinemq。在pom.xml中添加依赖:

<parent>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-parent</artifactId>
       <version>Dalston.SR1</version>
</parent>

<dependencies>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-turbine-amqp</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>
</dependencies>

这里的spring-cloud-starter-turbine-amqp实际上包装了spring-cloud-starter-turbine-stream和pring-cloud-starter-stream-rabbit。
在主类中开启@EnableTurbineStream注解:

@SpringBootApplication
@EnableAutoConfiguration
@EnableTurbineStream
public class TurbinemqApplication {

    public static void main(String[] args) {
        SpringApplication.run(TurbinemqApplication.class,args);
    }
}

配置application.properties文件:

spring.application.name=turbine-amqp
server.port=8989
management.port=8990
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

然后在消费者consumer3中的pom.xml文件修改一下,添加对amqp的依赖,使监控信息能输出到消息队列里:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-hystrix-amqp</artifactId>
</dependency>

然后停止前文的turbine聚合实例,启动turbinemq实例,访问监控页面,可以实现同样的监控效果,但这里的监控信息收集是通过消息代理异步实现的。
代码地址:https://github.com/howetong/mysc/tree/branch1

猜你喜欢

转载自blog.csdn.net/xiaoyi52/article/details/78055568
今日推荐