通过zipkin实现dubbo下的链路追踪
通过zipkin对dubbo进行链路追踪
目标
在dubbo的服务之间穿插调用时
可以通过zipkin查看调用关系 方便定位错误
环境
- jdk- 1.8
- dubbo- 2.6.5
- spring boot- 2.1.4
- zipkin- 2.12.8 采用内存保存数据
- nacos- 0.9 采用嵌入式数据库
流程描述
dubbo将服务注册到nacos中
前端用springboot接收请求 调用dubbo服务处理
调用关系为 web-hello依次调用provider1-hello11,provider1-hello12
provider1-hello12则会调用provider2-hello2
然后通过zipkin的管理界面查看调用情况
代码篇
项目采用maven聚合方式构建
dubbo-265-zipkin为父工程
- dubbo-consumer
- dubbo-interfaces
- dubbo-provider
- dubbo-provider2
项目结构整合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
<!-- 父工程pom.xml -->
<?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>fluffy.mo</groupId>
<artifactId>dubbo-265-zipkin</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<encoding>UTF-8</encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jdk.version>1.8</jdk.version>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<brave.version>5.6.3</brave.version>
<zipkin-reporter.version>2.8.2</zipkin-reporter.version>
</properties>
<modules>
<module>dubbo-interfaces</module>
<module>dubbo-provider</module>
<module>dubbo-provider2</module>
<module>dubbo-consumer</module>
</modules>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<!--nacos注册中心-->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>0.0.2</version>
</dependency>
<!-- zipkin与dubbo集成 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-dubbo-rpc</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-spring-beans</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-context-slf4j</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 引入 zipkin brave 的 BOM 文件 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>${brave.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 引入 zipkin repoter 的 BOM 文件 -->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-bom</artifactId>
<version>${zipkin-reporter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
|
其实zipkin的坐标应该在子工程中引用
dubbo-interfaces
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!-- dubbo-interfaces/pom.xml -->
<?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">
<parent>
<groupId>fluffy.mo</groupId>
<artifactId>dubbo-265-zipkin</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-interfaces</artifactId>
</project>
|
provider1与provider2的配置相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<!-- dubbo-provider1与dubbo-provider2的pom.xml -->
<?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">
<parent>
<groupId>fluffy.mo</groupId>
<artifactId>dubbo-265-zipkin</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-provider2</artifactId>
<dependencies>
<dependency>
<groupId>fluffy.mo</groupId>
<artifactId>dubbo-interfaces</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
|
1
2
3
4
5
6
7
8
|
#application.properties
spring.application.name=app-provider2
demo.service.version=1.1.0
dubbo.scan.basePackages=fluffy.mo
dubbo.protocol.port=10085
dubbo.registry.address = nacos://192.168.88.3:8848
dubbo.provider.filter=tracing
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
//#zipkin配置类
import brave.Tracing;
import brave.context.slf4j.MDCScopeDecorator;
import brave.propagation.CurrentTraceContext;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.sampler.Sampler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import zipkin2.Span;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.okhttp3.OkHttpSender;
@Configuration
public class ConfigZpk {
@Bean
AsyncReporter<Span> spanReporter() {
String url = "http://192.168.88.3:9411/api/v2/spans";
OkHttpSender.create(url);
return AsyncReporter.create(OkHttpSender.create(url));
}
@Bean
Tracing tracing(@Autowired AsyncReporter<Span> reporter
, @Value("${spring.application.name}") String serviceName) {
CurrentTraceContext currentTraceContext = ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(MDCScopeDecorator.create()).build();
return Tracing.newBuilder()
.localServiceName(serviceName)
.currentTraceContext(currentTraceContext)
.spanReporter(reporter)
.sampler(Sampler.ALWAYS_SAMPLE)
.build();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
//#启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class App_Main_pro1 {
public static void main(String[] args) {
SpringApplication.run(App_Main_pro1.class, args);
}
}
|
web与调用方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<!-- dubbo-consumer/pom.xml -->
<?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">
<parent>
<groupId>fluffy.mo</groupId>
<artifactId>dubbo-265-zipkin</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-consumer</artifactId>
<dependencies>
<dependency>
<groupId>fluffy.mo</groupId>
<artifactId>dubbo-interfaces</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--加载配置中心-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.1</version>
</dependency>
<!-- http的监控 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-web</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
</dependencies>
</project>
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#application.properties
spring.application.name=dubbo-consumer
server.servlet.context-path=/
server.port=18080
nacos.config.server-addr=192.168.88.3:8848
demo.service.version=1.1.0
dubbo.protocol.port=20086
dubbo.scan.basePackages=fluffy.mo.consumer
dubbo.registry.address = nacos://192.168.88.3:8848
dubbo.provider.filter=tracing
|
1
2
3
4
5
6
7
8
9
|
//#启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App_Main_client {
public static void main(String[] args) {
SpringApplication.run(App_Main_client.class, args);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
//#zipkin配置类
import brave.Tracing;
import brave.context.slf4j.MDCScopeDecorator;
import brave.http.HttpTracing;
import brave.propagation.B3Propagation;
import brave.propagation.CurrentTraceContext;
import brave.propagation.ExtraFieldPropagation;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.sampler.Sampler;
import brave.servlet.TracingFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.okhttp3.OkHttpSender;
import javax.servlet.Filter;
@Configuration
public class TraceAutoConfiguration{
@Value("${spring.application.name}")
private String serviceName;
@Bean
public Tracing tracing(){
String zipkin = "http://192.168.88.3:9411/api/v2/spans";
CurrentTraceContext currentTraceContext = ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(MDCScopeDecorator.create()).build();
return Tracing.newBuilder()
.localServiceName(serviceName)
.propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
.currentTraceContext(currentTraceContext)
.spanReporter(AsyncReporter.create(OkHttpSender.create(zipkin)))
.sampler(Sampler.ALWAYS_SAMPLE)
.build();
}
@Bean(name = "httpTracing")
HttpTracing httpTracing(Tracing tracing){
return HttpTracing.create(tracing);
}
@Bean
public Filter filter(HttpTracing httpTracing){
return TracingFilter.create(httpTracing);
}
}
|
web端处理要监控rpc的链路外
还要监控http请求的链路 所以比生产者要多配个httpTracing与filter
服务调用
dubbo-interfaces中定义两个接口
1
2
3
4
5
6
7
|
public interface Hello1Service {
String sayHello11(String name);
String sayHello12(String name);
}
public interface Hello2Service {
String sayHello2(String name);
}
|
dubbo-provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import fluffy.mo.interfaces.Hello2Service;
import fluffy.mo.interfaces.Hello1Service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
@Service(version = "${demo.service.version}" ,filter = "tracing")
public class Hello1ServiceImpl implements Hello1Service {
@Reference(version = "${demo.service.version}",timeout = 60000 ,filter = "tracing")
Hello2Service svc2;
public String sayHello11(String name) {
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
return "Hello, " + name;
}
public String sayHello12(String name) {
svc2.sayHello2(name);
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
return "Hello, " + name;
}
}
|
dubbo-provider2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import com.alibaba.dubbo.config.annotation.Service;
import fluffy.mo.interfaces.Hello2Service;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
@Service(version = "${demo.service.version}", filter = "tracing")
public class Hello2ServiceImpl implements Hello2Service {
static int COUNT = 0;
public String sayHello2(String name) {
if ((COUNT++) % 2 == 0) {
throw new RuntimeException("手动异常");
}
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
return "Hello, " + name;
}
}
|
开始测试
启动nacos与zipkin
1
2
3
4
5
6
7
8
9
|
#nacos
curl -L https://github.com/nacos-group/nacos-docker/archive/0.9.0.tar.gz \
| tar zxf
cd nacos-docker-0.9.0/
mkdir example/standalone-logs
docker-compose -d -f example/standalone-derby.yaml up
#zipkin
docker run -d -p 9411:9411 openzipkin/zipkin
|
依次启动项目
dubbo-provider2
dubbo-provider
dubbo-consumer
多次访问 http://127.0.0.1:18080/sayHello/test
成功返回 与 报错 次数是1比1
访问zipkin查看调用链路
http://192.168.88.3:9411/zipkin/?serviceName=all&spanName=all&sortOrder=timestamp-desc&limit=5
可以看到调用链为 http请求到provider1与provider2 关系为树形结构
文章作者
duansheli
上次更新
2019-12-25
(325c7b3)