本篇继续简述Netflix版SpringCloud之ribbon+hystrix & zipkin。
一些基本组件概念理解:
ribbon: 可以实现负载均衡,feign默认集成了ribbon。
hystrix: 断路器,feign自带断路器,但需要配置开启。
hystrix dashboard: 断路器仪表盘。
zipkin: spring clound sleuth集成了服务链路追踪组件zipkin.
sleuth进行数据埋点采集,zipkin进行数据存储展示
下面简单演示下以上组件的用法。
准备工作:启动eureka服务注册中心(参见 Netflix SpringCloud-Eureka)
1. ribbon负载均衡+hystrix断路机制
1.1 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>routing-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>routing-ribbon</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
</properties>
<dependencies>
<!--注册ribbon服务到注册中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!--hystrix断路器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<!--Hystrix Dashboard (断路器仪表盘)-->
<!--访问http://localhost:9000/hystrix
在请求地址栏输入:http://localhost:9000/hystrix.stream,
点击Monitor Stream可以监控service层的方法-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</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:
@RestController
public 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:
@RestController
public 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;
@Service
public 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的错误请求百分比
2. zipkin链路追踪
2.1 zipkin相关依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
2.2 zipkin yml
spring:
application:
name: server-zipkin
server:
port: 9100
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8888/eureka/,http://peer2:8889/eureka/
2.3 zipkin application
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
@EnableEurekaClient
public class ServerZipkinApplication {
public static void main(String[] args) {
SpringApplication.run(ServerZipkinApplication.class, args);
}
}
eureka-client 工程加入zipkin服务追踪
eureka-client pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</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相关的组件功能。