SpringCloud 是微服务中的翘楚,最佳的落地方案。
在一个完整的微服务架构项目中,服务之间的调用是很复杂的,当其中某一个服务出现了问题或者访问超时,很
难直接确定是由哪个服务引起的,所以就有了 Spring Cloud Sleuth 链路跟踪。通过它,我们就可以很清楚直观
的了解每一个服务请求经过了哪些服务,用时多久,谁依赖谁或者被谁依赖。
GitHub地址:https://github.com/intomylife/SpringCloud
4.0.0
com.zwc
springcloud-sleuth-commons
1.0
springcloud-sleuth-commons
公用工程
jar
UTF-8
1.8
Cairo-SR3
Finchley.RELEASE
io.spring.platform
platform-bom
${platform-bom.version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud-dependencies.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
① 此工程下有五个模块:一个注册中心,一个网关、一个 Zipkin 服务以及两个提供者
② 在 SpringBoot 2.x 版本后就不推荐自定义 zipkin server 了,但是下面有使用官网下载的 jar 包方式,
也有自定义的方式
③ Zipkin 也分为两部分,server 端和 client 端
④ server 端:收集数据,并展示
⑤ client 端:把调用信息发送给 server 端(本博客使用的 HTTP 报文的方式发送的信息)
⑥ 其中使用注册中心把服务连接起来,通过访问网关调用服务工程 A,服务工程 A 中使用的 Feign 调用服务
工程 B,最后使用 Zipkin 把所有请求数据记录下来,并展示
4.0.0
com.zwc
springcloud-sleuth-service
1.0
com.zwc
springcloud-sleuth-registry-service
1.0
springcloud-sleuth-registry-service
注册中心
jar
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-maven-plugin
# 端口
server:
port: 8761
# 应用名称
spring:
application:
name: eureka-server
eureka:
instance:
# 使用 ip 代替实例名
prefer-ip-address: true
# 实例的主机名
hostname: ${spring.cloud.client.ip-address}
# 实例的 ID 规则
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
# 是否向注册中心注册自己
registerWithEureka: false
# 是否向注册中心获取注册信息
fetchRegistry: false
serviceUrl:
# 注册中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
package com.zwc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class SpringcloudSleuthRegistryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudSleuthRegistryServiceApplication.class, args);
}
}
1. 项目启动成功后访问 http://localhost:8761/ 即可看到 eureka-server 主页面
1. 在浏览器中访问 https://zipkin.io/quickstart.sh
2. 选择路径下载保存到本地(我保存到了桌面)
3. 在桌面双击打开 quickstart.sh(刚刚下载保存的文件),会自动下载一个 jar 包
4. 等待下载结束后,打开 cmd
5. 输入命令 cd desktop -> 进入到桌面
6. 输入命令 java -jar zipkin.jar -> 执行 jar 包,zipkin.jar 就是上面自动下载的 jar 包
7. 启动成功后访问:http://localhost:9411 即可看到 Zipkin Server 主页面
4.0.0
com.zwc
springcloud-sleuth-service
1.0
com.zwc
springcloud-sleuth-master-service
1.0
springcloud-sleuth-master-service
链路跟踪
jar
2.11.8
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
io.zipkin.java
zipkin-server
org.springframework.boot
spring-boot-starter-log4j2
${zipkin.version}
io.zipkin.java
zipkin-autoconfigure-ui
${zipkin.version}
org.springframework.boot
spring-boot-maven-plugin
# 端口
server:
port: 9411
spring:
application:
# 应用名称
name: sleuth-zipkin-server
eureka:
instance:
# 使用 ip 代替实例名
prefer-ip-address: true
# 实例的主机名
hostname: ${spring.cloud.client.ip-address}
# 实例的 ID 规则
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注册中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
# 关闭自动配置启用所有请求得检测
management:
metrics:
web:
server:
# 避免访问 zipkin 页面报 java.lang.IllegalArgumentException
auto-time-requests: false
package com.zwc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import zipkin2.server.internal.EnableZipkinServer;
@SpringBootApplication
@EnableEurekaClient
@EnableZipkinServer
public class SpringcloudSleuthMasterServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudSleuthMasterServiceApplication.class, args);
}
}
1. 启动成功后访问:http://localhost:9411 即可看到 Zipkin Server 主页面
2. 两种方式任选其一即可
4.0.0
com.zwc
springcloud-sleuth-service
1.0
com.zwc
springcloud-sleuth-gateway-service
1.0
springcloud-sleuth-gateway-service
服务网关
jar
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.cloud
spring-cloud-starter-zipkin
org.springframework.boot
spring-boot-maven-plugin
# 端口
server:
port: 8000
spring:
application:
# 应用名称
name: sleuth-gateway
cloud:
gateway:
discovery:
locator:
# 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
enabled: true
# 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
routes:
# 路由标识(id:标识,具有唯一性)
- id: route_simple
# 目标服务地址(uri:地址,请求转发后的地址)
uri: http://localhost:8090/aUseB
# 路由条件(predicates:断言,匹配 HTTP 请求内容)
predicates:
## 匹配 GET 请求
- Method=GET
zipkin:
# 指定了 zipkin 服务器的地址
base-url: http://${spring.cloud.client.ip-address}:9411
sleuth:
sampler:
# 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
probability: 1.0
eureka:
instance:
# 使用 ip 代替实例名
prefer-ip-address: true
# 实例的主机名
hostname: ${spring.cloud.client.ip-address}
# 实例的 ID 规则
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注册中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 级别
org.springframework.cloud.gateway: debug
package com.zwc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class SpringcloudSleuthGatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudSleuthGatewayServiceApplication.class, args);
}
}
1. 暂不启动
4.0.0
com.zwc
springcloud-sleuth-a-service
1.0
com.zwc
springcloud-sleuth-a-service-core
1.0
springcloud-sleuth-a-service-core
服务工程 - A 核心
jar
com.zwc
springcloud-sleuth-commons
1.0
com.zwc
springcloud-sleuth-a-service-api
1.0
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-zipkin
org.springframework.boot
spring-boot-maven-plugin
# 端口
server:
port: 8090
spring:
application:
# 应用名称
name: sleuth-a
zipkin:
# 指定了 zipkin 服务器的地址
base-url: http://${spring.cloud.client.ip-address}:9411
sleuth:
sampler:
# 将采样比例设置为 1.0,也就是全部都需要。默认是 0.1
probability: 1.0
eureka:
instance:
# 使用 ip 代替实例名
prefer-ip-address: true
# 实例的主机名
hostname: ${spring.cloud.client.ip-address}
# 实例的 ID 规则
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注册中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
feign:
hystrix:
# 开启断路器
enabled: true
package com.zwc.a.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*
* @ClassName ASayHelloController
* @Desc TODO Say Hello
* @Date 2019/5/20 23:24
* @Version 1.0
*/
@RestController
public class ASayHelloController {
/*
* @ClassName ASayHelloController
* @Desc TODO 读取配置文件中的端口
* @Date 2019/5/20 23:24
* @Version 1.0
*/
@Value("${server.port}")
private String port;
/*
* @ClassName ASayHelloController
* @Desc TODO Say Hello
* @Date 2019/5/20 23:24
* @Version 1.0
*/
@RequestMapping("/a")
public String a(){
return "Hello!I'm a. port:" + port;
}
}
package com.zwc.a.api.feign;
import com.zwc.a.api.impl.FeignApiFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/*
* @ClassName FeignApi
* @Desc TODO 使用 Feign 调用 b - 接口
* @Date 2019/5/20 23:21
* @Version 1.0
*/
@FeignClient(value = "sleuth-b" , fallback = FeignApiFallBack.class)
public interface FeignApi {
/*
* @ClassName FeignApi
* @Desc TODO 通过 sleuth-b 服务名调用 b() 方法
* @Date 2019/5/20 23:21
* @Version 1.0
*/
@RequestMapping("/b")
String b();
}
package com.zwc.a.api.impl;
import com.zwc.a.api.feign.FeignApi;
import org.springframework.stereotype.Component;
/*
* @ClassName FeignApi
* @Desc TODO fallback
* @Date 2019/5/20 23:21
* @Version 1.0
*/
@Component
public class FeignApiFallBack implements FeignApi {
/*
* @ClassName FeignApiFallBack
* @Desc TODO 调用 sleuth-b 服务中的 b() 方法失败时执行
* @Date 2019/5/20 23:31
* @Version 1.0
*/
@Override
public String b() {
return "Hello!aUseB fail";
}
}
package com.zwc.a.controller;
import com.zwc.a.api.feign.FeignApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*
* @ClassName AUseBFeignController
* @Desc TODO 使用 Feign 调用 b - 前端控制器
* @Date 2019/5/20 23:23
* @Version 1.0
*/
@RestController
public class AUseBFeignController {
@Autowired(required = false)
private FeignApi feignApi;
/*
* @ClassName FeignController
* @Desc TODO 通过 sleuth-b 服务名调用 b() 方法
* @Date 2019/5/20 23:13
* @Version 1.0
*/
@RequestMapping("/aUseB")
public String aUseB(){
return feignApi.b();
}
}
package com.zwc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringcloudSleuthAServiceCoreApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudSleuthAServiceCoreApplication.class, args);
}
}
1. 暂不启动
① 此工程与服务工程 A 类似
② application.yml 配置文件中端口与应用名称与服务工程 A 不一致
③ 服务工程 B 只提供服务,所以不引入 feign
1. 暂不启动
1. 启动注册中心工程(registry-service)
2. 项目启动成功后访问:http://localhost:8761/ 即可看到 eureka-server 主页面
3. 启动 Zipkin Server 工程(master-service)或者启动官网 zipkin.jar 包
4. 启动成功后访问:http://localhost:9411 即可看到 Zipkin Server 主页面
5. 启动网关工程(gateway-service)、服务工程 A(a-service)以及服务工程 B(b-service)
6. 项目都启动成功后,首先访问:http://localhost:8090/a(调用自己的服务)
7. 输出内容:'Hello!I'm a. port:8090'
8. 回到 Zipkin Server 主页面,点击 Find Traces 蓝色按钮
9. 可以看到有一条服务调用信息
10. 点击上面的 Dependencies,查看依赖关系
11. 发现没有任何依赖关系,是因为服务工程 A 自己调用了自己的服务
12. 这时再访问:http://localhost:8090/aUseB(调用服务工程 B 的服务)
13. 输出内容:'Hello!I'm b. port:8091'
14. 回到 Zipkin Server 主页面,点击 Find Traces 蓝色按钮
15. 发现多了一条服务调用信息
16. 点击上面的 Dependencies,再次查看依赖关系
17. 发现刚刚通过服务工程 A 调用的服务工程 B 的关系图就出来了
18. 访问网关:http://localhost:8000/
19. 输出内容:'Hello!I'm b. port:8091'
20. 再次回到 Zipkin Server 主页面,点击 Find Traces 蓝色按钮
21. 发现又多了一条服务调用信息
22. 点击上面的 Dependencies,再次查看依赖关系
23. 访问网关通过路由转发到服务工程 A,服务工程 A 又通过 Feign 调用服务工程 B
希望能够帮助到你
over