Skip to content

Commit f333cba

Browse files
committed
feature: zipkin
1 parent 4e92404 commit f333cba

File tree

3 files changed

+235
-1
lines changed

3 files changed

+235
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# CAP原则
2+
3+
## Overview
4+
5+
`CAP` 原则又称 `CAP` 定理,指的是在一个分布式系统中, `Consistency`(一致性)、`Availability`(可用性)、`Partition tolerance`(分区容错性),三者不可得兼,最多只能同时满足其中的 `2` 个。
6+
7+
8+
9+
- 一致性(`Consistency`
10+
11+
在分布式系统中的所有数据备份,在同一时刻是否同样的值。(严格的一致性,所有节点访问同一份最新的数据副本)
12+
13+
- 可用性(`Availability`
14+
15+
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性,不保证获取的数据为最新数据,但是保证最终一致性)
16+
17+
- 分区容错性(`Partition tolerance`
18+
19+
分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 `C``A` 之间做出选择。
20+
21+
## CAP原则论证
22+
23+
## 取舍策略
24+
25+
- CA without P
26+
27+
如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但放弃P的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。传统的关系型数据库RDBMS:Oracle、MySQL就是CA。
28+
29+
- CP without A
30+
31+
如果不要求A(可用),相当于每个请求都需要在服务器之间保持强一致,而P(分区)会导致同步时间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统。设计成CP的系统其实不少,最典型的就是分布式数据库,如Redis、HBase等。对于这些分布式数据库来说,数据的一致性是最基本的要求,因为如果连这个标准都达不到,那么直接采用关系型数据库就好,没必要再浪费资源来部署分布式数据库。
32+
33+
- AP wihtout C
34+
35+
要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。典型的应用就如某米的抢购手机场景,可能前几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。这其实就是先在 A(可用性)方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲,虽然多少会影响一些用户体验,但也不至于造成用户购物流程的严重阻塞。
36+
37+
## 主流分布式系统是如何选择的
38+

研发相关/Kafka/分布式环境下保持数据一致性.md renamed to 研发相关/分布式/分布式环境下保持数据一致性.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
https://blog.csdn.net/sundacheng1989/article/details/93613270
88

9-
https://blog.csdn.net/floor2011/article/details/100907102
9+
https://blog.csdn.net/floor2011/article/details/100907102
10+
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# 从0开始服务化-0-调用链-Zipkin
2+
3+
## Zipkin
4+
5+
`Zipkin` 是一个分布式跟踪系统,用于收集、管理和查找跟踪数据。它可以把分布式链路调用的顺序串起来,并计算链路中每个 `RPC` 调用的耗时,可以很直观的看出在整个调用链路中延迟问题。 `Zipkin` 的设计基于 `GoogleDapper` 论文实现的。
6+
7+
`ZipkinServer` 提供了 `UI` 操作,可以非常方便地查看和搜索跟踪数据,直观的查看到链调用依赖关系。
8+
9+
该项目包括一个无依赖库和一个 `spring-boot` 服务器。存储支持包括内存, `JDBC(mysql)``Cassandra``Elasticsearch`
10+
11+
在没有使用外部存储时,则默认使用内存存储数据,内存数据是有限且不可持久化的,所以建议使用外部存储,因日志数据通常很大,为了搜索日志的效率,所以建议使用 `Elasticsearch`
12+
13+
Zipkin 的基础架构由 4 个核心组件构成:
14+
15+
- `Collector`:收集器组件,处理从外部系统发过来的跟踪信息,将这些信息转换为 Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
16+
- `Stroage`:存储组件,主要处理收集器收到的跟踪信息,默认存储在内存中,也可通过 ES 或 JDBC 来存储。
17+
- `Restful API`:API 组件,提供外部访问接口。
18+
- `Web UI`:UI组件,基于 API 组件实现的 Web 控制台,用户可以很方便直观地查询、搜索和分析跟踪信息。
19+
20+
## 部署测试服务
21+
22+
使用 `docker` 部署本地 `zipkin``server`
23+
24+
```
25+
docker run -d -p 9411:9411 \
26+
--name zipkin \
27+
docker.io/openzipkin/zipkin
28+
```
29+
30+
![20191211171340](http://cdn.heroxu.com/20191211171340.png)
31+
32+
访问:`http://localhost:9411/zipkin/`
33+
34+
![20191211171424](http://cdn.heroxu.com/20191211171424.png)
35+
36+
## 构建测试项目
37+
38+
- Service A
39+
40+
```
41+
server:
42+
port: 8081
43+
44+
spring:
45+
application:
46+
name: server-a
47+
sleuth:
48+
web:
49+
client:
50+
enabled: true
51+
sampler:
52+
probability: 1.0 # 采用比例,默认 0.1 全部采样 1.0
53+
zipkin:
54+
base-url: http://localhost:9411/ # 指定了Zipkin服务器的地址
55+
```
56+
57+
```
58+
@Slf4j
59+
@RestController
60+
public class ServiceAController {
61+
62+
@Resource
63+
private RestTemplate restTemplate;
64+
65+
@GetMapping(value = "/servicea")
66+
public String servicea() {
67+
try {
68+
Thread.sleep(3000);
69+
} catch (InterruptedException e) {
70+
e.printStackTrace();
71+
}
72+
log.info("This is service a!");
73+
return restTemplate.getForObject("http://localhost:8082/serviceb", String.class);
74+
}
75+
}
76+
```
77+
78+
- Service B
79+
80+
```
81+
server:
82+
port: 8082
83+
84+
spring:
85+
application:
86+
name: server-b
87+
sleuth:
88+
web:
89+
client:
90+
enabled: true
91+
sampler:
92+
probability: 1.0 # 采用比例,默认 0.1 全部采样 1.0
93+
zipkin:
94+
base-url: http://localhost:9411/ # 指定了Zipkin服务器的地址
95+
```
96+
97+
```
98+
@Slf4j
99+
@RestController
100+
public class ServiceBController {
101+
102+
@Autowired
103+
private RestTemplate restTemplate;
104+
105+
@GetMapping(value = "/serviceb")
106+
public String serviceb() {
107+
try {
108+
Thread.sleep(3000);
109+
} catch (InterruptedException e) {
110+
e.printStackTrace();
111+
}
112+
log.info("This is service b!");
113+
return restTemplate.getForObject("http://localhost:8083/servicec", String.class);
114+
}
115+
}
116+
```
117+
118+
- Service C
119+
120+
```
121+
server:
122+
port: 8083
123+
124+
spring:
125+
application:
126+
name: server-c
127+
sleuth:
128+
web:
129+
client:
130+
enabled: true
131+
sampler:
132+
probability: 1.0 # 采用比例,默认 0.1 全部采样 1.0
133+
zipkin:
134+
base-url: http://localhost:9411/ # 指定了Zipkin服务器的地址
135+
```
136+
137+
```
138+
@Slf4j
139+
@RestController
140+
public class ServiceCController {
141+
142+
@Resource
143+
private RestTemplate restTemplate;
144+
145+
@GetMapping(value = "/servicec")
146+
public String servicec() {
147+
try {
148+
Thread.sleep(3000);
149+
} catch (InterruptedException e) {
150+
e.printStackTrace();
151+
}
152+
log.info("This is service c!");
153+
return "hello,this is server c!";
154+
}
155+
}
156+
```
157+
158+
## 测试服务调用链-Sleuth
159+
160+
`Zipkin` 的依赖中包含了 `Sleuth`,`Sleuth` 功能:
161+
162+
- 将 `SpanID` 和 `TraceID` 添加到 `Slf4JMDC` 中,这样可以在日志聚合器中根据 `SpanID` 和 `TraceID` 提取日志。
163+
- 提供对常见分布式跟踪数据模型的抽象:`traces(跟踪)`, `spans(形成DAG(有向无环图))`,注释, `key-value` 注释。松散地基于 `HTrace` ,但兼容 `Zipkin(Dapper)`。
164+
- `Sleuth` 常见的入口和出口点来自 `Spring` 应用(`Servlet` 过滤器、`Rest Template`、`Scheduled Actions`、消息通道、`Zuul Filter、`Feign Client`)。
165+
- 如果 `spring-cloud-sleuth-zipkin` 可用,`Sleuth` 将通过 `HTTP` 生成并收集与 `Zipkin` 兼容的跟踪。默认情况下,将跟踪数据发送到 `localhost`(端口:9411)上的 `Zipkin` 收集服务应用,可使用 `spring.zipkin.baseUrl` 修改服务器地址。
166+
167+
启动3个服务,访问:`http://localhost:8081/servicea`,可以看到3个服务的日志输出如下:
168+
169+
![20191211173729](http://cdn.heroxu.com/20191211173729.png)
170+
171+
![20191211173754](http://cdn.heroxu.com/20191211173754.png)
172+
173+
![20191211173809](http://cdn.heroxu.com/20191211173809.png)
174+
175+
在输出的日志中,多了些内容,这些内容就是由 `sleuth` 为服务调用提供的链路信息
176+
可以看到内容组成:`[appname,traceId,spanId,exportable]`,具体含义如下:
177+
178+
- `appname`:服务的名称,即 spring.application.name 的值。
179+
- `traceId`:整个请求链路的唯一ID。
180+
- `spanId`:基本的工作单元,一个 RPC 调用就是一个新的 span。启动跟踪的初始 span 称为 root span ,此 spanId 的值与 traceId 的值相同。见上面示例消费者服务日志输出。
181+
- `exportable`:是否将数据导入到 Zipkin 中,true 表示导入成功,false 表示导入失败。
182+
183+
## Zipkin Server
184+
185+
再次访问:`http://localhost:9411/zipkin/`,点击查询,可以看到刚才执行的服务调用链:
186+
187+
![20191211174929](http://cdn.heroxu.com/20191211174929.png)
188+
189+
点击可以看到具体的调用时间与链路:
190+
191+
![20191211175049](http://cdn.heroxu.com/20191211175049.png)
192+
193+
点击具体的服务,可以看到服务调用的详情以及父级子级 `trace`
194+
195+
![20191211175127](http://cdn.heroxu.com/20191211175127.png)

0 commit comments

Comments
 (0)