SpringCloud基础(4)

来源:互联网 发布:淘宝新店写给顾客的话 编辑:程序博客网 时间:2024/06/05 06:13

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=localhostspring.cloud.consul.port=8500

服务接口修改为:

@RestControllerpublic 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-consumerserver.port=2101spring.cloud.consul.host=localhostspring.cloud.consul.port=8500

服务消费者主类:

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

消费接口类:

@RestControllerpublic 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=consumer3server.port=2103eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

控制器为:

@RestControllerpublic 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@EnableCircuitBreakerpublic 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-dashboardserver.port=1301

主类:

@SpringCloudApplication@EnableHystrixDashboardpublic 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@EnableDiscoveryClientpublic class TurbineApplication {    public static void main(String[] args) {        SpringApplication.run(TurbineApplication.class, args);    }}

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

spring.application.name=turbineserver.port=8989management.port=8990eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/turbine.app-config=consumer3turbine.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@EnableTurbineStreampublic class TurbinemqApplication {    public static void main(String[] args) {        SpringApplication.run(TurbinemqApplication.class,args);    }}

配置application.properties文件:

spring.application.name=turbine-amqpserver.port=8989management.port=8990eureka.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

原创粉丝点击