SpringCloud入门实战之十二:断路器聚合监控(Hystrix Turbine)

上一篇文章讲述了如何利用Hystrix Dashboard去监控断路器的Hystrix command,当我们有很多个服务的时候,就需要
聚合Hystrix Dashboard的数据,这就需要用到Spring Cloud的另一个组件 ------ Hystrix Turbine。

看单个的Hystrix Dashboard的数据并没有什么多大的价值,要想看这个系统的Hystrix Dashboard数据就需要用到
Hystrix Turbine,Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合。Hystrix Turbine的使用非常简单,
只需要引入相应的依赖和加上注解和配置就可以了。

本文使用的工程为上一篇文章的工程,在此基础上进行改造。因为我们需要多个服务的Dashboard,所以需要再建一个
服务,取名为service-lucy,它的基本配置同service-hi一样。

第一部分:创建service-lucy工程

勾选 Hystrix                    生成依赖 spring-cloud-starter-netflix-hystrix
勾选 Hystrix Dashboard 生成依赖 spring-cloud-starter-netflix-hystrix-dashboard
勾选 Eureka Discovery  生成依赖 spring-cloud-starter-netflix-eureka-client
勾选 Actuator                 生成依赖 spring-boot-starter-actuator
勾选 Web                       生成依赖 spring-boot-starter-web

在程序的入口ServiceHiApplication类,加上@EnableHystrix注解开启断路器,这个是必须的,并且需要在程序中声
明断路点HystrixCommand;加上@EnableHystrixDashboard注解,开启HystrixDashboard

package com.contoso;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@RestController
@EnableHystrix
@EnableHystrixDashboard
@EnableCircuitBreaker
public class ServiceLucyApplication {

	/**
	 * 访问地址 http://localhost:8762/actuator/hystrix.stream
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		SpringApplication.run(ServiceLucyApplication.class, args);
	}

	@Value("${server.port}")
	String port;

	@RequestMapping("/hi")
	@HystrixCommand(fallbackMethod = "hiError")
	public String message(@RequestParam(value = "name", defaultValue = "World") String name) {
		return "Hello " + name + " ,this message is from port:" + port;
	}

	public String hiError(String name) {
		return "Hello " + name + " ,sorry,error!";
	}
}

定义application.yml配置文件内容如下:

server:
  port: 8763

spring:
  application:
    name: service-lucy

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
management:
  endpoints:
    web:
      exposure:
        include: "*"
      cors:
        allowed-origins: "*"
        allowed-methods: "*"

第二部分:创建service-turbine工程

勾选 Hystrix                    生成依赖 spring-cloud-starter-netflix-hystrix
勾选 Hystrix Dashboard 生成依赖 spring-cloud-starter-netflix-hystrix-dashboard
勾选 Eureka Discovery   生成依赖 spring-cloud-starter-netflix-eureka-client
勾选 Actuator                  生成依赖 spring-boot-starter-actuator
勾选 Web                       生成依赖 spring-boot-starter-web
勾选 Turbine                   生成依赖 spring-cloud-starter-netflix-turbine

在其入口类ServiceTurbineApplication加上注解@EnableTurbine,开启turbine,@EnableTurbine注解包含了@EnableDiscoveryClient注解,即开启了注册服务。

package com.contoso;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@RestController
@EnableHystrix
@EnableHystrixDashboard
@EnableCircuitBreaker
@EnableTurbine
public class ServiceTurbineApplication {

    /**
     * http://localhost:8764/turbine.stream
     */

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

配置文件application.yml内容如下:

server:
  port: 8764

spring:
  application:
    name: service-turbine

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
management:
  endpoints:
    web:
      exposure:
        include: "*"
      cors:
        allowed-origins: "*"
        allowed-methods: "*"

turbine:
  app-config: service-hi,service-lucy
  aggregator:
    clusterConfig: default
  clusterNameExpression: new String("default")
  combine-host: true
  instanceUrlSuffix:
    default: actuator/hystrix.stream

依次启动eureka-server、service-hi、service-lucy、service-turbine工程

[root@contoso ~]# curl -i -X GET http://localhost:8764/turbine.stream
HTTP/1.1 200 
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Content-Type: text/event-stream;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 23 Jul 2018 05:28:52 GMT

: ping
: ping
data: {"reportingHostsLast10Seconds":0,"name":"meta","type":"meta","timestamp":1532323735587}

: ping
data: {"reportingHostsLast10Seconds":0,"name":"meta","type":"meta","timestamp":1532323738589}

: ping
data: {"reportingHostsLast10Seconds":0,"name":"meta","type":"meta","timestamp":1532323741592}

: ping
data: {"reportingHostsLast10Seconds":0,"name":"meta","type":"meta","timestamp":1532323744593}

: ping
data: {"reportingHostsLast10Seconds":0,"name":"meta","type":"meta","timestamp":1532323747597}

...     ...
...     ...

在浏览器中依次请求如下地址:

http://localhost:8762/hi?name=Cathy
http://localhost:8763/hi?name=Cathy

依次显示:
Hello Cathy ,this message is from port:8762
Hello Cathy ,this message is from port:8763

[root@contoso ~]# curl -i -X GET http://localhost:8764/turbine.stream
HTTP/1.1 200 
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Content-Type: text/event-stream;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 23 Jul 2018 05:36:53 GMT

: ping
data: {"currentCorePoolSize":10,"currentLargestPoolSize":1,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"currentActiveCount":0,"currentMaximumPoolSize":10,"currentQueueSize":0,"type":"HystrixThreadPool","currentTaskCount":1,"currentCompletedTaskCount":1,"rollingMaxActiveThreads":0,"rollingCountCommandRejections":0,"name":"ServiceLucyApplication$$EnhancerBySpringCGLIB$$4fce8b0b","reportingHosts":1,"currentPoolSize":1,"propertyValue_queueSizeRejectionThreshold":5,"rollingCountThreadsExecuted":0}

data: {"rollingCountFallbackSuccess":0,"rollingCountFallbackFailure":0,"propertyValue_circuitBreakerRequestVolumeThreshold":40,"propertyValue_circuitBreakerForceOpen":false,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":20000,"latencyTotal_mean":0,"rollingMaxConcurrentExecutionCount":0,"type":"HystrixCommand","rollingCountResponsesFromCache":0,"rollingCountBadRequests":0,"rollingCountTimeout":0,"propertyValue_executionIsolationStrategy":"THREAD","rollingCountFailure":0,"rollingCountExceptionsThrown":0,"rollingCountFallbackMissing":0,"threadPool":"{\"ServiceLucyApplication$$EnhancerBySpringCGLIB$$4fce8b0b\":1,\"ServiceHiApplication$$EnhancerBySpringCGLIB$$57305cf1\":1}","latencyExecute_mean":0,"isCircuitBreakerOpen":false,"errorCount":0,"rollingCountSemaphoreRejected":0,"group":"{\"ServiceLucyApplication$$EnhancerBySpringCGLIB$$4fce8b0b\":1,\"ServiceHiApplication$$EnhancerBySpringCGLIB$$57305cf1\":1}","latencyTotal":{"0":0,"99":0,"100":0,"25":0,"90":0,"50":0,"95":0,"99.5":0,"75":0},"requestCount":0,"rollingCountCollapsedRequests":0,"rollingCountShortCircuited":0,"propertyValue_circuitBreakerSleepWindowInMilliseconds":10000,"latencyExecute":{"0":0,"99":0,"100":0,"25":0,"90":0,"50":0,"95":0,"99.5":0,"75":0},"rollingCountEmit":0,"currentConcurrentExecutionCount":0,"propertyValue_executionIsolationSemaphoreMaxConcurrentRequests":20,"errorPercentage":0,"rollingCountThreadPoolRejected":0,"propertyValue_circuitBreakerEnabled":true,"propertyValue_executionIsolationThreadInterruptOnTimeout":true,"propertyValue_requestCacheEnabled":true,"rollingCountFallbackRejection":0,"propertyValue_requestLogEnabled":true,"rollingCountFallbackEmit":0,"rollingCountSuccess":0,"propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests":20,"propertyValue_circuitBreakerErrorThresholdPercentage":100,"propertyValue_circuitBreakerForceClosed":false,"name":"message","reportingHosts":2,"propertyValue_executionIsolationThreadPoolKeyOverride":"null","propertyValue_executionIsolationThreadTimeoutInMilliseconds":2000,"propertyValue_executionTimeoutInMilliseconds":2000}

data: {"currentCorePoolSize":10,"currentLargestPoolSize":1,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"currentActiveCount":0,"currentMaximumPoolSize":10,"currentQueueSize":0,"type":"HystrixThreadPool","currentTaskCount":1,"currentCompletedTaskCount":1,"rollingMaxActiveThreads":0,"rollingCountCommandRejections":0,"name":"ServiceHiApplication$$EnhancerBySpringCGLIB$$57305cf1","reportingHosts":1,"currentPoolSize":1,"propertyValue_queueSizeRejectionThreshold":5,"rollingCountThreadsExecuted":0}

data: {"reportingHostsLast10Seconds":1,"name":"meta","type":"meta","timestamp":1532324214067}

: ping
data: {"reportingHostsLast10Seconds":1,"name":"meta","type":"meta","timestamp":1532324217071}

: ping
data: {"reportingHostsLast10Seconds":1,"name":"meta","type":"meta","timestamp":1532324220073}

: ping
data: {"reportingHostsLast10Seconds":1,"name":"meta","type":"meta","timestamp":1532324223076}

: ping
data: {"reportingHostsLast10Seconds":1,"name":"meta","type":"meta","timestamp":1532324226080}

打开Google浏览器(FireFox可能无法显示输出内容)输入 http://localhost:8764/turbine.stream 显示如下:

在浏览器中打开 http://localhost:8763/hystrix 输入监控流http://localhost:8764/turbine.stream

可以看到这个页面聚合了2个service的hystrix dashbord数据

本篇blog源码 spring-cloud-example12.zip

猜你喜欢

转载自blog.csdn.net/zhengzizhi/article/details/81164382
今日推荐