Skip to content

Commit fc711bd

Browse files
committed
注册中心怎么设计?
1 parent 9ba7fab commit fc711bd

File tree

4 files changed

+271
-3
lines changed

4 files changed

+271
-3
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
今天,给大家分享如何设计一个**注册中心**
2+
3+
不管是出于面试,还是深入学习注册中心,关于如何设计一个注册中心都是一个很好的话题。
4+
5+
假设现在我们系统有两个小系统:
6+
7+
- 订单系统
8+
- 商品系统
9+
10+
单个系统分别部署在不同服务器上,如果我们订单系统需要调用商品系统的某个服务:
11+
12+
![](http://img.topjavaer.cn/img/注册中心1.png)
13+
14+
15+
16+
#### 怎么调用?
17+
18+
方法1:商品系统开发的朋友告诉你对应的地址。
19+
20+
![](http://img.topjavaer.cn/img/注册中心2.png)
21+
22+
23+
24+
方法2:商品系统开发的朋友把对应`API`地址存放到某个地方。
25+
26+
![](http://img.topjavaer.cn/img/注册中心3.png)
27+
28+
29+
30+
方法3:直接通过Nginx,使用域名进行转发到某个实例上。
31+
32+
![](http://img.topjavaer.cn/img/注册中心4.png)
33+
34+
这时候,订单系统就可以通过上述方法调用商品系统的`API`了。
35+
36+
#### 问题来了
37+
38+
实际线上环境中,很少是单体机构的,很多都是做了集群的,也就是说每个服务会有N个实例,少则几个几十个,多则几百上千上万。如果此时我们还用上面三种方法,当我们的商品系统某个服务下线(宕机了),或者新增实例,此时是非常的头疼。
39+
40+
> 所以,注册中心就来了。
41+
42+
#### 注册中心来了
43+
44+
我们能不能搞一个第三方的节点,这个节点就用来存放我们商品系统的服务信息,这样一来,其他系统需要服务信息,直接去第三方节点上去获取即可。此时,其他系统只要知道这个第三方的节点地址就可以了。这个第三方的节点,我们也称之为`注册中心`
45+
46+
> 下面我们用服务提供方(商品系统)称之为provider,服务调用方(订单系统)我们称之为consumer。
47+
48+
#### 如何设计一个注册中心
49+
50+
我们需要解决如下几个问题:
51+
52+
- 服务如何注册
53+
- consumer如何知道provider
54+
- 服务注册中心如何高可用
55+
- 服务上下线,消费端如何动态感知
56+
57+
##### 服务注册
58+
59+
![](http://img.topjavaer.cn/img/注册中心5.png)
60+
61+
当我们把服务信息注册上去后,就应该是:
62+
63+
![](http://img.topjavaer.cn/img/注册中心6.png)
64+
65+
> 服务列表保存通常有三种方式:本地内存、数据库、第三方缓存系统
66+
67+
注册上去后,consumer需要服务地址的时候,就可以用相应key去注册中心获取对应的服务列表。
68+
69+
![](http://img.topjavaer.cn/img/注册中心7.png)
70+
71+
> 同一个服务注册中心,我们可以注册多个服务,比如用户服务、商品服务、订单服务...
72+
73+
##### 服务消费
74+
75+
![](http://img.topjavaer.cn/img/注册中心8.png)
76+
77+
consumer端通过key获取指定的服务地址列表。
78+
79+
以上的还是蛮简单的吧,简单来说,我们就是引用了一个第三方的服务来存放我们的服务提供者列表。并且以key-value的形式存储,key我们可以理解为服务名称,value就是服务实例列表。
80+
81+
![](http://img.topjavaer.cn/img/注册中心9.png)
82+
83+
84+
85+
##### 注册中心高可用
86+
87+
高可用无非就是做集群,我们可以对注册中心部署多个节点。在消费端consumer只需要知道一个服务注册中心集群地址`cluster-url`即可。
88+
89+
![](http://img.topjavaer.cn/img/注册中心10.png)
90+
91+
92+
93+
##### 动态感知服务上下线
94+
95+
consumer拿到服务列表后,会把服务列表保存起来,保存到本地缓存里。
96+
97+
![](http://img.topjavaer.cn/img/注册中心10.png)
98+
99+
100+
101+
consumer通过一定的负载均衡算法,选择出一个地址,最后发起远程的调用。
102+
103+
![](http://img.topjavaer.cn/img/注册中心12.png)
104+
105+
106+
107+
如果我们的服务节点挂掉一个了,怎么办?
108+
109+
![](http://img.topjavaer.cn/img/注册中心13.png)
110+
111+
112+
113+
此时,服务注册中心的服务列表还是之前的列表,如果consumer调用到过掉的节点上,那岂不是会出问题呀。
114+
115+
所以,我们的服务注册中心需要知道哪个服务节点挂了,然后从对应服务列表里删除。
116+
117+
有种办法叫做心跳检测`heartBeat`,即就是服务注册中心,每隔一定时间去监测一下provider,如果监测到某个服务挂了,那就把对应服务地址从服务列表中删除。
118+
119+
> 根据心跳检测,来提出无效服务。
120+
121+
![](http://img.topjavaer.cn/img/注册中心13.png)
122+
123+
124+
125+
可是不对呀,此时consumer端本地列表里还有过掉的服务地址,怎么办呢?
126+
127+
或者是,在增加一个新的服务节点
128+
129+
![](http://img.topjavaer.cn/img/注册中心15.png)
130+
131+
132+
133+
对于服务注册中心来说,就是服务列表里增加一个服务地址。
134+
135+
但是在消费端存在同样的问题,就是服务注册中心的服务列表和consumer端的服务列表不一样了。
136+
137+
如何让consumer端也动态感知呢?
138+
139+
其实很简单,此时,我们得思维换一下,因为consumer的服务列表是来自于服务注册中心,我们就可以把consumer理解为消费端,服务注册中心理解为服务端。此时,consumer端就可以去服务端(服务注册中心)拉取provider服务列表。
140+
141+
通常有两种方案:push和pull
142+
143+
- push:服务注册中心主动推送服务列表给consumer。
144+
- pull:consumer主动从注册中心拉取服务列表。
145+
146+
![](http://img.topjavaer.cn/img/注册中心15.png)
147+
148+
149+
150+
不管是push还是pull,都会存在consumer和服务注册中心的通信管道。如果他们之间断开了,那就无法获取服务列表了。
151+
152+
还有就是服务注册中心知道consumer的地址,比如
153+
154+
> 我得知道你的微信好友,不然我怎么把我手里的资源发给你
155+
156+
我们的网络通信,必然会存在监听的动作。
157+
158+
如果服务注册中心要push到consumer,此时他们之间需要建立一个会话,所以,在服务注册中心会维护一个会话管理的模块。还有一种方式就是consumer提供一个`API`,这个`API`给服务注册中心进行回调。
159+
160+
> 本质是我们是使用HTTP协议还是使用Socket监听
161+
162+
push有个不好点,那就是服务注册中心需要维护大量的会话,而且还需要对每个会话维持一个心跳,一遍知晓这些会话状态,得确保这些consumer能收到数据,
163+
164+
另外就是pull,pull其实就相对push就简单多了。pull和我们前面说的心跳机制是类似的,consumer端启动定时任务,每个多久拉取服务注册中心的服务列表。pull也不需要去维护大量的会话,我只需要每隔多久调用接口拉取服务列表即可。但是这里还是会存在一个问题,因为是定时去拉取,所以会存在一定的数据延迟,比如consumer刚刚拉取服务列表,但就在拉取结束的后,某个服务provider挂了,consumer就要等下次拉取才知道对应服务provider挂了。
165+
166+
> 如果定时任务是每隔30秒拉去一次,那就是说,延迟最长时间是30秒。
167+
168+
还有一种方式long-pull,也叫长轮询,是上面两种方案的优化方案,consumer发起拉取请求时,先把这个请求hold住,当服务注册中心有发生变化后,consumer端能立马感知。
169+
170+
关于长轮询:
171+
172+
> 与简单轮询相似,只是在服务端在没有新的返回数据情况下不会立即响应,而会挂起,直到有数据或即将超时
173+
>
174+
> `优点`:实现也不复杂,同时相对轮询,节约带宽
175+
>
176+
> `缺点`:还是存在占用服务端资源的问题,虽然及时性比轮询要高,但是会在没有数据的时候在服务端挂起,所以会一直占用服务端资源,处理能力变少
177+
>
178+
> `应用`:一些早期的对及时性有一些要求的应用:web IM 聊天
179+
180+
这样,我们就搞定了所谓的服务上下线动态感知。
181+
182+
通过上面的服务注册、服务消费、注册中心高可用以及动态感知服务的上下线,这就是我们去实现一个服务注册中心的通用模型。
183+
184+
##### 小总结
185+
186+
关于如何设计一个注册中心,无非重点关以下几点:
187+
188+
- 服务是如何注册
189+
- 消费端如何获取服务
190+
- 如何保证注册中心的高可用
191+
- 动态感知服务的上下线

docs/advance/system-design/2-order-timeout-auto-cancel.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@ sidebar: heading
44

55
# 订单30分钟未支付自动取消怎么实现?
66

7+
推荐大家加入我的[**学习圈**](https://mp.weixin.qq.com/s?__biz=Mzg2OTY1NzY0MQ==&mid=2247491988&idx=1&sn=a7d50c0994cbfdede312715b393daa8a&scene=21#wechat_redirect),目前已经有100多位小伙伴加入了,下面有50元的**优惠券****扫描二维码**领取优惠券加入(**即将恢复原价**)。
8+
9+
学习圈提供以下这些**服务**
10+
11+
1、学习圈内部**知识图谱**,汇总了**优质资源、面试高频问题、大厂面经、踩坑分享**,让你少走一些弯路
12+
13+
2、四个**优质专栏**、Java**面试手册完整版**(包含**场景设计、系统设计、分布式、微服务**等),持续更新
14+
15+
![](http://img.topjavaer.cn/img/image-20230120085023054.png)
16+
17+
3、**一对一答疑**,我会尽自己最大努力为你答疑解惑
18+
19+
4、**免费的简历修改、面试指导服务**,绝对赚回门票
20+
21+
5、各个阶段的优质**学习资源**(新手到架构师),超值
22+
23+
6、打卡学习,**大学自习室的氛围**,一起蜕变成长
24+
25+
![](http://img.topjavaer.cn/img/星球优惠券-学习网站.png)
26+
27+
--分割线--
28+
729
**目录**
830

931
- 了解需求
@@ -613,4 +635,14 @@ lRabbitMQ 的 Queue 可以配置 x-dead-letter-exchange 和 x-dead-letter-routin
613635

614636
### 缺点
615637

616-
本身的易用度要依赖于 rabbitMq 的运维.因为要引用 rabbitMq,所以复杂度和成本变高。
638+
本身的易用度要依赖于 rabbitMq 的运维.因为要引用 rabbitMq,所以复杂度和成本变高。
639+
640+
--end--
641+
642+
最后给大家分享一个Github仓库,上面有大彬整理的**300多本经典的计算机书籍PDF**,包括**C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生**等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~
643+
644+
![](http://img.dabin-coder.cn/image/Image.png)
645+
646+
![](http://img.dabin-coder.cn/image/image-20221030094126118.png)
647+
648+
**Github地址**https://github.com/Tyson0314/java-books

docs/java/java-basic.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ sidebar: heading
33

44
---
55

6+
67
> 欢迎加入[大彬的学习圈](https://topjavaer.cn/zsxq/introduce.html),学习圈整理了最新的**Java面试手册完整版**(本网站的面试题补充版,更全面),还有很多其他**优质资料**,比如包括Java项目、进阶知识、实战经验总结、优质书籍、笔试面试资源等等。
78
>
89
> ![](http://img.topjavaer.cn/img/image-20230102194032026.png)
@@ -1575,4 +1576,48 @@ server {
15751576

15761577
> 参考链接:https://mp.weixin.qq.com/s/O_jCxZWtTTkFZ9FlaZgOCg
15771578
1579+
## 8招让接口性能提升100倍
1580+
1581+
**池化思想**
1582+
1583+
如果你每次需要用到线程,都去创建,就会有增加一定的耗时,而线程池可以重复利用线程,避免不必要的耗时。
1584+
1585+
比如`TCP`三次握手,它为了减少性能损耗,引入了`Keep-Alive长连接`,避免频繁的创建和销毁连接。
1586+
1587+
**拒绝阻塞等待**
1588+
1589+
如果你调用一个系统`B`的接口,但是它处理业务逻辑,耗时需要`10s`甚至更多。然后你是一直**阻塞等待,直到系统B的下游接口返回**,再继续你的下一步操作吗?这样**显然不合理**
1590+
1591+
参考**IO多路复用模型**。即我们不用阻塞等待系统`B`的接口,而是先去做别的操作。等系统`B`的接口处理完,通过**事件回调**通知,我们接口收到通知再进行对应的业务操作即可。
1592+
1593+
**远程调用由串行改为并行**
1594+
1595+
比如设计一个商城首页接口,需要查商品信息、营销信息、用户信息等等。如果是串行一个一个查,那耗时就比较大了。这种场景是可以改为并行调用的,降低接口耗时。
1596+
1597+
**锁粒度避免过粗**
1598+
1599+
在高并发场景,为了防止**超卖等情况**,我们经常需要**加锁来保护共享资源**。但是,如果加锁的粒度过粗,是很影响接口性能的。
1600+
1601+
不管你是`synchronized`加锁还是`redis`分布式锁,只需要在共享临界资源加锁即可,不涉及共享资源的,就不必要加锁。
1602+
1603+
**耗时操作,考虑放到异步执行**
1604+
1605+
耗时操作,考虑用**异步处理**,这样可以降低接口耗时。比如用户注册成功后,短信邮件通知,是可以异步处理的。
1606+
1607+
**使用缓存**
1608+
1609+
把要查的数据,提前放好到缓存里面,需要时,**直接查缓存,而避免去查数据库或者计算的过程**
1610+
1611+
**提前初始化到缓存**
1612+
1613+
预取思想很容易理解,就是**提前把要计算查询的数据,初始化到缓存**。如果你在未来某个时间需要用到某个经过复杂计算的数据,**才实时去计算的话,可能耗时比较大**。这时候,我们可以采取预取思想,**提前把将来可能需要的数据计算好,放到缓存中**,等需要的时候,去缓存取就行。这将大幅度提高接口性能。
1614+
1615+
**压缩传输内容**
1616+
1617+
压缩传输内容,传输报文变得更小,因此传输会更快。
1618+
1619+
> 参考:https://juejin.cn/post/7167153109158854687
1620+
1621+
1622+
15781623
![](http://img.topjavaer.cn/img/20220612101342.png)

docs/zsxq/introduce.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ APP端页面如下(建议大家**使用APP**,因为APP布局更加美观,
5151

5252
如果你加入了,希望你也能跟像球友们一样**每天坚持打卡学习,为未来奋斗**~
5353

54-
![](http://img.topjavaer.cn/img/星球优惠券-私聊.png)
54+
![](http://img.topjavaer.cn/img/星球优惠券-学习网站.png)
5555

5656
## 学习圈能提供什么?
5757

@@ -173,4 +173,4 @@ APP端页面如下(建议大家**使用APP**,因为APP布局更加美观,
173173

174174
PS:如果加入学习圈之后觉得不合适,**支持3天内全额退款**~
175175

176-
![](http://img.topjavaer.cn/img/星球优惠券-私聊.png)
176+
![](http://img.topjavaer.cn/img/星球优惠券-学习网站.png)

0 commit comments

Comments
 (0)