本篇继续简述Netflix版SpringCloud之ribbon+hystrix & zipkin。
一些基本组件概念理解:
ribbon: 可以实现负载均衡,feign默认集成了ribbon。
hystrix: 断路器,feign自带断路器,但需要配置开启。
hystrix dashboard: 断路器仪表盘。
zipkin: spring clound sleuth集成了服务链路追踪组件zipkin.
sleuth进行数据埋点采集,zipkin进行数据存储展示
下面简单演示下以上组件的用法。
准备工作:启动eureka服务注册中心(参见 Netflix SpringCloud-Eureka)
"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0modelVersion> <groupId>com.demogroupId> <artifactId>routing-ribbonartifactId> <version>0.0.1-SNAPSHOTversion> <packaging>jarpackaging> <name>routing-ribbonname> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>1.5.12.RELEASEversion> <relativePath/> parent> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding> <java.version>1.8java.version> <spring-cloud.version>Edgware.SR3spring-cloud.version> properties> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-ribbonartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-hystrixartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-actuatorartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-hystrix-dashboardartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency> dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-dependenciesartifactId> <version>${spring-cloud.version}version> <type>pomtype> <scope>importscope> dependency> dependencies> dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> plugins> build> <repositories> <repository> <id>spring-milestonesid> <name>Spring Milestonesname> <url>https://repo.spring.io/milestoneurl> <snapshots> <enabled>falseenabled> snapshots> repository> repositories>project>
1.2 yml
spring: application: name: routing-ribbon eureka: client: serviceUrl: defaultZone: http://peer1:8888/eureka/,http://peer2:8889/eureka/server: port: 9000
1.3 application
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.hystrix.EnableHystrix;import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;/** * ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为。 * Feign默认集成了ribbon */@SpringBootApplication@EnableDiscoveryClient // 向服务注册中心eureka注册ribbon服务组件@EnableHystrix // 开启断路器@EnableHystrixDashboard // 开启断路器仪表盘public class RoutingRibbonApplication { public static void main(String[] args) { SpringApplication.run(RoutingRibbonApplication.class, args); } @Bean // 向spring IOC容器注入一个bean: restTemplate @LoadBalanced // RestTemplate开启负载均衡功能 RestTemplate restTemplate() { return new RestTemplate(); }}
1.4 演示ribbon负载均衡
(1)服务注册中心eureka-server集群,端口为8888,8889(相当于zookeeper)
eureka-client 工程同Netflix SpringCloud-Eureka 第3部分eureka client ,eureka-client工程启动两个实例,端口分别为8887,8886,分别向服务注册中心注册。

(2)eureka-client中定义一个简单的HelloController:
@RestControllerpublic class HelloController { @Value("${server.port}") private String port; /** * http://localhost:8887/hello?name=bruce * @param name * @return */ @RequestMapping("/hello") public String hello(@RequestParam String name) { return "hello " + name + ",I am from port:" + port; }}
(3)routing-ribbon端口为9000(功能类似Nginx),向服务注册中心注册。
routing-ribbon中定义一个简单的HelloController:
@RestControllerpublic class HelloController { @Autowired HelloService helloService; /** * http://localhost:9000/hello?name=bruce * @param name * @return */ @RequestMapping(value = "/hello") public String hello(@RequestParam String name){ return helloService.helloService(name); } /** * http://localhost:9000/hi?name=bruce * @param name * @return */ @RequestMapping(value = "/hi") public String hi(@RequestParam String name){ return helloService.hiService(name); }}
routing-ribbon中定义的HelloService:
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;@Servicepublic class HelloService { @Autowired RestTemplate restTemplate; /** * url 中的 eureka-client 即为eureka-client工程中配置的spring-application-name * 在浏览器上多次访问http://eureka-client/hello?name=bruce,浏览器交替显示: * hello bruce,I am from port:8887 * hello bruce,I am from port:8886 * * 这说明当我们通过调用restTemplate.getForObject("http://eureka-client/hello?name=" + name, String.class)方法时, * 已经做了负载均衡,访问了不同的端口的服务实例。 * * @param name * @return */ public String helloService(String name) { return restTemplate.getForObject("http://eureka-client/hello?name=" + name, String.class); } /** * 启动:routing-ribbon 工程,当我们访问http://localhost:9000/hi?name=bruce,浏览器显示: * hi bruce,i am from port:8887 / hi bruce,i am from port:8886, 当任意关闭一个客户端,仍可以访问; * 此时全部关闭 eureka-client 工程,当我们再访问http://localhost:9000/hi?name=bruce,浏览器会显示: * hi,bruce! sorry,error! * @param name * @return */ @HystrixCommand(fallbackMethod = "hiError") // 指定下面定义的断路处理方法名 public String hiService(String name) { return restTemplate.getForObject("http://eureka-client/hello?name=" + name, String.class); } /** * 这就说明当 eureka-client 工程不可用的时候, * routing-ribbon调用 eureka-client的API接口时,会执行快速失败,直接返回一组字符串, * 而不是等待响应超时,这很好的控制了容器的线程阻塞 * @param name * @return */ public String hiError(String name) { return "hi," + name + "! sorry,error!"; }}
(4)当routing-ribbon通过restTemplate调用eureka-client的hello接口时, 因为用ribbon进行了负载均衡,会轮流的调用8887和8886 两个端口的hello接口。
当eureka-client两个节点服务都可用时,反复刷新请求,可见通过ribbon实现了负载均衡;当其中一个client服务节点挂掉后,会一直调用仅存的一个节点服务。


1.5 演示hystrix断路处理
(1)当eureka-client两个节点服务都不可用时,即无可用服务时,这时会触发我们定义好的断路机制,调取 fallbackMethod = "hiError"

(2)如果没有指定断路防护机制,将直接返回springboot定义的默认错误页面

(3)访问hystrix dashboard


在图表中,左上角的圆圈代表了该方法的流量和状态:
圆圈越大代表方法流量越大
圆圈为绿色代表断路器健康、黄色代表断路器偶发故障、红色代表断路器故障
右上角的计数器(三列数字):
第一列从上到下
绿色代表当前成功调用的数量
蓝色代表短路请求的数量
蓝绿色代表错误请求的数量
第二列从上到下
黄色代表超时请求的数量
紫色代表线程池拒绝的数量
红色代表失败请求的数量
第三列
过去10s的错误请求百分比
<dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>dependency><dependency> <groupId>io.zipkin.javagroupId> <artifactId>zipkin-serverartifactId>dependency><dependency> <groupId>io.zipkin.javagroupId> <artifactId>zipkin-autoconfigure-uiartifactId>dependency>
spring: application: name: server-zipkinserver: port: 9100 eureka: client: serviceUrl: defaultZone: http://peer1:8888/eureka/,http://peer2:8889/eureka/
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import zipkin.server.EnableZipkinServer;/** * Spring Cloud Sleuth集成了服务追踪组件zipkin * 依次启动server-zipkin,eureka-client1,eureka-client2, * 访问server-zipkin http://localhost:9100*/@SpringBootApplication@EnableZipkinServer@EnableEurekaClientpublic class ServerZipkinApplication { public static void main(String[] args) { SpringApplication.run(ServerZipkinApplication.class, args); }}
eureka-client 工程加入zipkin服务追踪
eureka-client pom.xml
<dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>dependency><dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-zipkinartifactId>dependency>
eureka-client yml
eureka: client: serviceUrl: defaultZone: http://peer1:8888/eureka/,http://peer2:8889/eureka/
server: port: 8887
spring: application: name: eureka-client zipkin: base-url: http://localhost:9100
访问zipkin监控面板 http://localhost:9100 ,查看服务调用路径

点击查看具体的服务调用:

以上简单演示了下ribbon的负载均衡功能,hystrix的断路处理机制,以及使用zipkin监控追踪服务调用链路。
下章节将简述下feign及zuul相关的组件功能。