一、断路器
1.1 断路器介绍
在微服务架构中,不同业务被拆分成一个一个的服务里面,服务与服务之间是通过RPC进行调用。为了保证服务的高可用性,单个服务可能会在多台服务器中集群部署。但是,有时候会由于网络或自身原因操作服务通讯失败。由于服务与服务之间具有依赖性,比如说A服务调用B服务,B服务调用C服务,C服务调用D服务,那么万一其中一个服务停止,就会导致其他依赖的服务出现阻塞。如果系统中同时出现多个服务发生故障的情况,那么对整个微服务系统就会造成灾难性的严重后果。
使用断路器可以防止上面的问题。如果在该服务上注册了断路器,那么服务发生故障的时候,断路器就会自动向该服务的调用者发送一个默认的数据,从而防止调用者阻塞等待该服务。
Netflix开源了Hystrix组件,该组件实现了断路器模式。目前该组件已经被整合到了Spring Cloud中,因此Spring Cloud用户可以非常方便在指定服务中使用断路器。
1.2 在Robbin中使用Hystrix
Netflix Hystrix是微服务架构中提供服务隔离、熔断、 降级机制的框架。Netflix Hystrix是断路器的一种实现,用于高微服务架构的可用性,防止服务出现崩塌。
在Robbin中使用Hystrix的步骤:
第一步:引入Hystrix依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
第二步:在主类中使用@EnableHystrix注解。
第三步:改造DemoService,在demoService方法上使用@HystrixCommand注解。该注解指定fallbackMethod方法,用于服务故障发生时候熔断器调用该方法返回默认数据。
第四步:关闭service-demo服务,然后启动Robbin项目,并且在浏览器上访问服务。
从上面输出的内容可以看到,当服务调用失败时候,断路器被自动运行了。
1.3 在Feign中使用Hystrix
由于Feign自带了断路器功能,但是在一些Spring Cloud版本中默认没有被打开,所以需要在配置文件中手动打开断路器功能。
在Feign中使用Hystrix的步骤:
第一步:在application.yml文件中开启hystrix功能。
feign:
hystrix:
enabled: true
第二步:定义一个断路器类,该类实现提供服务的接口,并实现接口的方法。
@Component
public class DemoServiceHystrix implements DemoService {
@Override
public String sayHello(String name) {
return "hello " + name + ", 调用sayHello服务失败!";
}
}
第三步:在服务接口的@FeignClient注解上指定fallback属性, 该属性指定断路器类。
第四步:关闭service-demo服务,然后启动Feign项目,并且在浏览器上访问服务。
从上面输出的内容可以看到,当服务调用失败时候,断路器被自动运行了。
1.4 Hystrix Dashboard断路器仪表盘
Hystrix Dashboard作为断路器的一个组件,它主要用来实时监控Hystrix的各项指标信息。它提供了友好的图形化界面,通过Hystrix Dashboard反馈的实时信息,可以帮助我们快速发现系统存在的问题,从而及时地采取应对措施。
使用仪表盘的步骤:
第一步:在Robbin工程中引入相关依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
第二步:在主类中使用@EnableHystrixDashboard注解。
第三步:因为springboot的默认路径不是 “/hystrix.stream”,所以如果springboot是2.0版本,则在主类中需要配置ServletRegistrationBean 。
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
配置完成后启动Robbin服务,然后在浏览器上输入localhost:8264/hystrix,然后在浏览器上看到Hystrix主界面。
第四步:在页面上输入以下信息后,点击Monitor Stream开始监控服务。
我们也可以在浏览器上输入localhost:8264/hystrix.stream查看实时捕获到的JSON数据。这时候后台Hystrix
每个指定毫秒数后,仪表盘的数据可能发生了变化。因此,建议使用一些抓包功能查看捕获到的数据。
二、路由网关
在Spring Cloud微服务系统中,一种常见的负载均衡方式是:客户端的请求先经过负载均衡(zuul、nginx),再到达服务网关(zuul集群),然后再到具体的服务。服务统一注册到高可用的服务注册中心集群,服务的所有配置文件由配置服务管理。配置服务的配置文件放在git仓库中,方便开发人员随时修改配置。
Zuul组件的主要功能是路由转发和过滤器。路由功能是微服务的一部分。Zuul默认与Ribbon结合实现了负载均衡的功能。
2.1 路由转发
第一步:在CloudSample父工程下新建一个子模块,并命名为ServiceZuul。
第二步:在pom中加入zuul依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
完整pom文件如下:
<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>
<parent>
<groupId>com.xjy</groupId>
<artifactId>CloudSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ServiceZuul</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</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>
第三步:创建主类,并在主类上使用@EnableZuulProxy注解。
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
第四步:在application.yml中配置路由信息。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8260/eureka/
server:
port: 8269
spring:
application:
name: service-zuul
zuul:
routes:
api-a:
path: /api-a/**
serviceId: service-ribbon
api-b:
path: /api-b/**
serviceId: service-feign
上面配置了api-a和api-b两个路由。zull.routes.xxx.path指定请求路径规则,zull.routes.xxx.serviceId指定处理请求的服务名。
第五步:运行主类,然后在浏览器上分别访问http://localhost:8269/api-a/demo?name=aa和http://localhost:8269/api-b/demo?name=bb。可以看到如下效果:
2.2 过滤器
Zuul不仅仅只有路由功能,它还可以作为请求过滤器使用。下面我们对ServiceZuul子模块进行改造。
第一步:定义一个类,继承ZuulFilter,并重写它的方法。
@Component
public class TestZuulFilter extends ZuulFilter {
@Override
public Object run() {
}
@Override
public boolean shouldFilter() {
}
@Override
public int filterOrder() {
}
@Override
public String filterType() {
}
}
方法说明:
- run:过滤器方法,相当于Servlet Filter中的doFilter方法。
- shouldFilter:是否启动过滤器,如果返回true代表过滤,返回false代表不过滤。
- filterOrder:过滤器执行优先级,它的值从0开始,值越大,优先级就越低。
- filterType:过滤类型。pre代表路由前过滤,routing代表路由时过滤,post代表路由后过滤,error代表错误发生时候调用。
第二步:实现这些方法。
package com.xjy.servicezuul;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@Component
public class TestZuulFilter extends ZuulFilter {
@Override
public Object run() {
// 获取HttpServletRequest对象
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 获取参数token
String token = request.getParameter("token");
// 判断token是否为空,如果为空就阻止请求执行
// 如果token不为空,那么不需要做任何事情,直接返回null即可。
if (token == null) {
// 阻止请求的发送
ctx.setSendZuulResponse(false);
// 发送响应状态码给客户端
ctx.setResponseStatusCode(401);
try {
// 向客户端发送内容
ctx.getResponse().getWriter().write("token is empty!");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
return null;
}
@Override
public boolean shouldFilter() {
// 开启过滤功能
return true;
}
@Override
public int filterOrder() {
// 设置过滤器优先级最高
return 0;
}
@Override
public String filterType() {
// 在路由前过滤
return "pre";
}
}
在run方法中请求发送过来的请求参数token。如果token为空就阻止请求执行,下面方法就是用于阻止请求的执行。
ctx.setSendZuulResponse(false)
第三步:重启Zuul服务,然后按照之前方式访问,效果如下图所示:
三、分布式配置中心组件
在分布式系统中,由于服务器数量庞大,为了方便对服务的配置信息进行统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中有分布式配置中心组件Spring Cloud Config,它支持配置服务的配置信息放在本地的内存中,也支持放在远程Git仓库中。
Spring Cloud Config组件分为两个角色:Config Server 和 Config Client。Config Server代表服务配置的提供者,Config Client代表服务配置的使用者。
下面介绍如何使用Spring Cloud Config访问远程Git仓库中的配置文件。
3.1 配置Config Server
第一步:在CloudSample父工程下新建一个子模块,并命名为ServiceConfig。
第二步:在pom中添加相关依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
完整pom文件内容如下:
<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>
<parent>
<groupId>com.xjy</groupId>
<artifactId>CloudSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ServiceConfig</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</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>
第三步:配置仓库信息。
# 服务名
spring.application.name=service-config
# 服务端口号
server.port=8888
# 注册中心地址
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
# 配置文件所在仓库的地址
spring.cloud.config.server.git.uri=https://github.com/joe1981/respo
# 仓库路径
spring.cloud.config.server.git.searchPaths=respo
# 分支
spring.cloud.config.label=master
# github登录帐号
spring.cloud.config.server.git.username=
# github登录密码
spring.cloud.config.server.git.password=
第四步:在Github中创建一个工程,然后在主分支上添加一个资源文件。
配置文件内容如下:
第五步:创建主类,并在主类上使用@EnableConfigServer注解。
@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
第六步:运行主类,然后在浏览器上输入localhost:8888/config-client/dev查看资源文件的信息。
请求路径与资源文件的映射关系:
请求路径 | 资源文件 |
---|---|
/{application}/{profile}[/{label}] | /{application}-{profile}.yml |
/{label}/{application}-{profile}.yml | |
/{application}-{profile}.properties | |
/{label}/{application}-{profile}.properties |
3.2 配置Config Client
第一步:在CloudSample父工程下新建一个子模块,并命名为ServiceConfigClient。
第二步:在pom中添加相关依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
完整pom文件内容如下:
<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>
<parent>
<groupId>com.xjy</groupId>
<artifactId>CloudSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ServiceConfigClient</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</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>
第三步:定义bootstrap.properties配置文件。
# 配置服务注册中心
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
# 服务端口号
server.port=8881
# ServiceConfig的服务地址
spring.cloud.config.url=http://localhost:8888/
# 远程仓库分支
spring.cloud.config.label=master
# 和git仓库中资源文件名字对应
spring.application.name=config-client
# {application}-{profile}.properties中profile的名字
spring.cloud.config.profile=dev
这里之所以不在application配置文件中配置上面信息,是因为需要在ApplicationContext初始化之前把配置文件的信息广播出来。假如在构建某些Bean的时候使用@Value注解注入配置文件属性的时候,那么这些属性必须要先存在才可以进行注入。因此在构建ApplicationContext之前就需要先得到这些配置信息。而bootstrap配置文件的加载优先级比application配置文件要高,它会在ApplicationContext初始化之前执行。因此,这里需要把上面的配置信息定义在bootstrap配置文件中比较合适。
第四步:创建主类。
@SpringBootApplication
@RestController
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Value("${cname}")
String cname;
@RequestMapping(value = "/demo")
public String demo() {
return cname;
}
}
上面${cname}是从远程Git仓库中获取该参数。
第五步:运行主类,然后在浏览器上输入localhost:8881/demo,运行效果如下图所示:
3.3 配置Config Server集群
当存在多个服务实例都需要从配置中心读取资源文件的时候,可以考虑将Config Server集群化,从而达到高可用性。
第一步:改造Service模块,在pom文件中加入spring-cloud-starter-eureka依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
第二步:在配置文件中指定服务注册中心的地址。
spring.application.name=service-config
server.port=8888
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
第三步:在主类上加入@EnableEurekaClient注解,用于访问服务注册中心。
步骤二和步骤三前面已经配置过的话可以省略。
第四步:改造ServiceConfigClient模块,在pom中加入spring-cloud-starter-eureka依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
第五步:修改配置文件。
# 指定从注册中心发现配置服务
spring.cloud.config.discovery.enabled=true
# 指定配置服务名
spring.cloud.config.discovery.serviceId=service-config
第六步:依次启动EurekaServer、ServiceConfig、ServiceConfigClient服务,启动完成后可以在注册中心管理页面看到启动的服务。
3.4 消息总线(Spring Cloud Bus)
配置消息总线的好处:当配置仓库中资源文件发送改变的时候,配置服务会主动广播给配置服务的客户端。Spring Cloud Bus需要依赖MQ组件进行消息的发送和接收。因此需要安装并启动以下两个组件的服务:
- ErLang
- RabbitMQ
链接:https://pan.baidu.com/s/1MNj9xnrGHpvvUGVgUCF_9A
提取码:zgp0
下载完成后,按照以下步骤改造ServiceConfigClient模块。
第一步:添加spring-cloud-starter-bus-amqp依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
第二步:在bootstrap配置文件中指定management.security.enabled参数。
management.security.enabled=false
如果在springcloud1.5以后的版本上支持配置动态刷新请求访问,那么就需要指定management.security.enabled参数值为false。
第三步:在application配置文件中设置mq参数。
# mq服务器地址
spring.rabbitmq.host=localhost
# mq服务器端口号
spring.rabbitmq.port=5672
# mq服务的用户名,默认不需要设置
# spring.rabbitmq.username=
# mq服务的密码,默认不需要设置
# spring.rabbitmq.password=
第四步:在主类上加入@RefreshScope注解,指定可以更新配置。
第五步:依次启动EurekaServer、ServiceConfig、ServiceConfigClient服务,然后访问localhost:8881/demo服务。
然后在github上修改资源文件。
这里我们把cname参数值修改为mickey。
修改完成后向localhost:8881/bus/refresh发送一个post请求,这时候模块就会重新读取github仓库中的资源文件。所以,当我们重新刷新localhost:8881/demo页面的时候,可以看到cname参数的值为mickey。
四、服务链路跟踪
4.1 服务链介绍
微服务架构通过业务来划分服务,服务与服务之间通过REST进行服务调用。在实际业务中,一个业务可以需要由多个服务共同完成,例如:服务A -> 服务B -> 服务C -> 服务D,从而形成一条链,我们称之为服务链。如果链路上任何一个服务出现问题,都会导致服务调用失败。当服务调用失败的时候,我们需要对服务调用过程进行跟踪,找出发生问题的服务,这样才能够有效解决服务调用的问题。
Spring Cloud Sleuth组件为分布式系统提供了服务追踪的解决方案,并且兼容zipkin(关于zipkin的这里不作深入研究)。
4.2 服务链演示
(1)构建服务跟踪模块
第一步:创建ServiceZipKin模块,并加入zipkin依赖。
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
完整的pom文件内容如下:
<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>
<parent>
<groupId>com.xjy</groupId>
<artifactId>SleuthSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ServiceZipkin</artifactId>
<dependencies>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</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>
第二步:在application配置文件中配置服务。
spring:
application:
name: service-zipkin
server:
port: 9411
第三步:在主类上使用@EnableZipkinServer注解。
@SpringBootApplication
@EnableZipkinServer
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
(2)创建服务跟踪节点
第一步:创建子模块,并命名为servicehi,并加入sleuth zipkin相关依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
完整的pom文件内容如下:
<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>
<parent>
<groupId>com.xjy</groupId>
<artifactId>SleuthSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ServiceHi</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</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>
第二步:在application配置文件中配置服务节点。
server:
port: 8987
spring:
zipkin:
base-url: http://localhost:9411
application:
name: service-hi
sleuth:
sampler:
percentage: 1.0
spring.zipkin.base-url代表zipkin服务器地址。sleuth.sampler.percentage代表跟踪采集器的频率,默认为0.1,即每10次请求采集数据一次。1.0代表每次请求都被采集。
第三步:在主类上加入@EnableDiscoveryClient注解。
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
第四步:按照上面步骤1~3创建另外两个服务节点,分别命名为servicemiya和servicezhong,并分别修改配置文件server.port为8988和8989。
servicemiya服务节点的配置文件:
server:
port: 8988
spring:
zipkin:
base-url: http://localhost:9411
application:
name: service-miya
sleuth:
sampler:
percentage: 1.0
servicezhong服务节点的配置文件:
server:
port: 8989
spring:
zipkin:
base-url: http://localhost:9411
application:
name: service-zhong
sleuth:
sampler:
percentage: 1.0
第五步:在三个服务节点的主类中定义服务方法,服务方法的调用关系如下:
servicehi节点:
@RequestMapping("/hi")
public String callHome() {
return restTemplate.getForObject("http://localhost:8988/miya", String.class);
}
servicemiya节点:
@RequestMapping("/miya")
public String info(){
return restTemplate.getForObject("http://localhost:8989/zhong",String.class);
}
servicezhong节点:
@RequestMapping("/zhong")
public String home(){
return "i'm zhong!";
}
第六步:依次启动所有服务节点,然后通过localhost:9411访问ZipKin管理后台界面。
然后访问localhost:8987/hi,访问完后刷新管理后台界面可以看到服务跟踪链的信息。
在SpringCloud的Finchley版本开始,ZipKin成为了一个自服务项目,已经不需要自己构建ZipKin Server了。只需要下载一个jar文件并运行该文件即可。
下载地址:https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server
下载完成后jar文件所在目录下执行命令:
命令格式:
java -jar 压缩文件名
例如:
java -jar zipkin-server-2.9.4-exec.jar
五、搭建高可用的服务中心集群
第一步:改造EurekaServer工程,创建新的配置文件application-es1.yml和application-es2.yml。
application-es1.yml:
server:
port: 8260
spring:
profiles: es1
eureka:
instance:
hostname: es1
client:
serviceUrl:
defaultZone: http://es2:8259/eureka/
application-es2.yml:
server:
port: 8259
spring:
profiles: es2
eureka:
instance:
hostname: es2
client:
serviceUrl:
defaultZone: http://es1:8260/eureka/
第二步:在主机hosts文件中配置es1和es2.
127.0.0.1 es1
127.0.0.1 es2
第三步:修改EurekaService工程的配置文件。
修改eureka.client.serviceUrl.defaultZone:
第三步:启动服务。
先启动两个注册中心服务,然后再启动EurekaService服务。启动完成后,可以在Eureka管理后台看出注册的所有服务。
在上面示例中,两个EurekaServer服务都是对等的,他们都存在相同的信息。即使其中一个服务注册中心停止服务,其他注册中心还可以继续提供服务。