面试:如何设计一个注册中心?

大家好,我是田哥

上周,一位群里的朋友反馈面试情况:

bcc61b8899b69e4b48660916b06ff321.png

今天,给大家分享如何设计一个注册中心。其实这个问题,我之前在知识星球里分享过,可能是因为时间比较久了,加上这位朋友加入不久,还没看到那里。

d56e75c37f1c79fadadab0ebca55ea90.png

不管是出于面试,还是深入学习注册中心,关于如何设计一个注册中心都是一个很好的话题。

假设现在我们系统有两个小系统(这里只是个假设,可能很多人并没有做过类似的业务,注意只是一个业务场景而已):

  • 订单系统

  • 商品系统

单个系统分别部署在不同服务器上,如果我们订单系统需要调用商品系统的某个服务(聊简单点,别扯什么缓存之类的):

fd4a7b0337cdfca65f0fa2db2ca3bf4f.png


怎么调用?

方法1:商品系统开发的朋友告诉你对应的地址。

852a966c4e56f1ab7c0ef1bd01be8569.png


方法2:商品系统开发的朋友把对应API地址存放到某个地方。

7fed865123a8d6db512da1e89e03a830.png


方法3:直接通过Nginx,使用域名进行转发到某个实例上。

cd54ea2c14df2e01b80abf473e2955f3.png


这时候,订单系统就可以通过上述方法调用商品系统的API了。

问题来了

实际线上环境中,很少是单体机构的,很多都是做了集群的,也就是说每个服务会有N个实例,少则几个几十个,多则几百上千上万。如果此时我们还用上面三种方法,当我们的商品系统某个服务下线(宕机了),或者新增实例,此时是非常的头疼。

所以,注册中心就来了。

注册中心来了

我们能不能搞一个第三方的节点,这个节点就用来存放我们商品系统的服务信息,这样一来,其他系统需要服务信息,直接去第三方节点上去获取即可。此时,其他系统只要知道这个第三方的节点地址就可以了。这个第三方的节点,我们也称之为注册中心

下面我们用服务提供方(商品系统)称之为provider,服务调用方(订单系统)我们称之为consumer。

如何设计一个注册中心

我们需要解决如下几个问题:

  • 服务如何注册

  • consumer如何知道provider

  • 服务注册中心如何高可用

  • 服务上下线,消费端如何动态感知

服务注册

733f2a08ee600cd840c470768b6ddc64.png


当我们把服务信息注册上去后,就应该是:

ac85a70b5fd85fdc07d8744835e0ff43.png


服务列表保存通常有三种方式:本地内存、数据库、第三方缓存系统

注册上去后,consumer需要服务地址的时候,就可以用相应key去注册中心获取对应的服务列表。

c791bc85317bf2a959e794912ed99703.png


同一个服务注册中心,我们可以注册多个服务,比如用户服务、商品服务、订单服务...

服务消费

cfd44e17f8c2e6026906eba9d0c6e8e6.png


consumer端通过key获取指定的服务地址列表。

以上的还是蛮简单的吧,简单来说,我们就是引用了一个第三方的服务来存放我们的服务提供者列表。并且以key-value的形式存储,key我们可以理解为服务名称,value就是服务实例列表。

d159b4446a6acbf108de933b73ad1cda.png


注册中心高可用

高可用无非就是做集群,我们可以对注册中心部署多个节点。在消费端consumer只需要知道一个服务注册中心集群地址cluster-url即可。

31cd7f01a3a6a7015f2033cb107dcbe2.png


动态感知服务上下线

consumer拿到服务列表后,会把服务列表保存起来,保存到本地缓存里。

0369742ce3d5cf0d1bc9cd2f66c91975.png


consumer通过一定的负载均衡算法,选择出一个地址,最后发起远程的调用。

b7986fa82b988ca539d89400f54fd263.png


如果我们的服务节点挂掉一个了,怎么办?

2f468ec01237c6cb527458baf5d4e386.png


此时,服务注册中心的服务列表还是之前的列表,如果consumer调用到过掉的节点上,那岂不是会出问题呀。

所以,我们的服务注册中心需要知道哪个服务节点挂了,然后从对应服务列表里删除。

有种办法叫做心跳检测heartBeat,即就是服务注册中心,每隔一定时间去监测一下provider,如果监测到某个服务挂了,那就把对应服务地址从服务列表中删除。

根据心跳检测,来提出无效服务。

4f2ac0864fbd19355eac6333818b9721.png


可是不对呀,此时consumer端本地列表里还有过掉的服务地址,怎么办呢?

或者是,在增加一个新的服务节点

8fc7b910ca9ceda199ad08d564677e71.png


对于服务注册中心来说,就是服务列表里增加一个服务地址。

但是在消费端存在同样的问题,就是服务注册中心的服务列表和consumer端的服务列表不一样了。

如何让consumer端也动态感知呢?

其实很简单,此时,我们得思维换一下,因为consumer的服务列表是来自于服务注册中心,我们就可以把consumer理解为消费端,服务注册中心理解为服务端。此时,consumer端就可以去服务端(服务注册中心)拉取provider服务列表。

通常有两种方案:push和pull

  • push:服务注册中心主动推送服务列表给consumer。

  • pull:consumer主动从注册中心拉取服务列表。

90ebdca5a7cb2bb39b469f261e66a973.png


不管是push还是pull,都会存在consumer和服务注册中心的通信管道。如果他们之间断开了,那就无法获取服务列表了。

还有就是服务注册中心知道consumer的地址,比如

我得知道你的微信好友,不然我怎么把我手里的资源发给你

我们的网络通信,必然会存在监听的动作。

如果服务注册中心要push到consumer,此时他们之间需要建立一个会话,所以,在服务注册中心会维护一个会话管理的模块。还有一种方式就是consumer提供一个API,这个API给服务注册中心进行回调。

本质是我们是使用HTTP协议还是使用Socket监听

push有个不好点,那就是服务注册中心需要维护大量的会话,而且还需要对每个会话维持一个心跳,一遍知晓这些会话状态,得确保这些consumer能收到数据,

另外就是pull,pull其实就相对push就简单多了。pull和我们前面说的心跳机制是类似的,consumer端启动定时任务,每个多久拉取服务注册中心的服务列表。pull也不需要去维护大量的会话,我只需要每隔多久调用接口拉取服务列表即可。但是这里还是会存在一个问题,因为是定时去拉取,所以会存在一定的数据延迟,比如consumer刚刚拉取服务列表,但就在拉取结束的后,某个服务provider挂了,consumer就要等下次拉取才知道对应服务provider挂了。

如果定时任务是每隔30秒拉去一次,那就是说,延迟最长时间是30秒。

还有一种方式long-pull,也叫长轮询,是上面两种方案的优化方案,consumer发起拉取请求时,先把这个请求hold住,当服务注册中心有发生变化后,consumer端能立马感知。

关于长轮询:

与简单轮询相似,只是在服务端在没有新的返回数据情况下不会立即响应,而会挂起,直到有数据或即将超时

优点:实现也不复杂,同时相对轮询,节约带宽

缺点:还是存在占用服务端资源的问题,虽然及时性比轮询要高,但是会在没有数据的时候在服务端挂起,所以会一直占用服务端资源,处理能力变少

应用:一些早期的对及时性有一些要求的应用:web IM 聊天

这样,我们就搞定了所谓的服务上下线动态感知。

通过上面的服务注册、服务消费、注册中心高可用以及动态感知服务的上下线,这就是我们去实现一个服务注册中心的通用模型。

总结

关于如何设计一个注册中心,无非重点关以下几点:

  • 服务是如何注册

  • 消费端如何获取服务

  • 如何保证注册中心的高可用

  • 动态感知服务的上下线

好了,今天就跟大家分享这么多,希望能给你带来点点帮助。

如果有点点帮助,那就顺手来个三连呗:点赞、转发、再看,谢谢啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/306541.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣HOT100 - 160. 相交链表

解题思路: /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if…

雨云:不一样的服务器体验

引言 在当今数字化时代,服务器已经成为了许多企业和个人不可或缺的一部分。无论是建立网站、存储数据还是运行应用程序,都需要一个稳定可靠的服务器来支持。然而,在众多的服务器提供商中,选择一个适合自己需求的并不容易。今天我要…

spispi

数据手册里面有这么一段解释,就是说如果我们开启了看门狗,那么LSI就会跟随强制打开,等待LSI稳定之后就可以自动为独立看门狗提供时钟了。所以这里的第一步开启时钟不需要我们写代码来执行 2.写入预分频器和重装寄存器 在写入这两个寄存器之前…

git知识

如何将develop分支合并到master分支 #简单版 git checkout master git pull origin master git merge origin/develop # 解决可能的冲突并提交 git push origin master#复杂版 git checkout master # 拉取远程 master 分支的最新代码并合并到本地 git pull origin master # 拉…

Linux:软件包管理器 - yum

Linux:软件包管理器 - yum Linux的软件安装方式源代码安装rpm包安装yum安装 yum三板斧yum listyum installyum remove yum生态yum源 Linux的软件安装方式 源代码安装 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序 源代码安…

若依ts版本(vue3+element plus+ts)

1、项目简介 本项目参考若依前后端分离版,前端由[若依vue3]改写为ts版本[ruoyi-web-vue3-ts],后端对[若依V3.8.7]进行了修改[后端版本分支vue3.ts.3.8.7],具体文档参见[若依官方文档]。本项目对部分代码做了优化,增加了activiti7…

LeetCode-5. 最长回文子串【字符串 动态规划】

LeetCode-5. 最长回文子串【字符串 动态规划】 题目描述:解题思路一:动态规划五部曲解题思路二:动态规划[版本二]解题思路三:0 题目描述: 给你一个字符串 s,找到 s 中最长的回文 子串 。 如果字符串的反序…

【MYSQL】索引机制概述

由于MySQL是作为存储层部署在业务系统的最后端,所有的业务数据最终都要入库落盘,但随着一个项目在线上运行的时间越来越久,数据库中的数据量自然会越来越多,而数据体积出现增长后,当需要从表查询一些数据时&#xff0c…

网络安全入门教程(非常详细)从零基础入门到精通

网络安全是一个庞大而不断发展的领域,它包含多个专业领域,如网络防御、网络攻击、数据加密等。介绍网络安全的基本概念、技术和工具,逐步深入,帮助您成为一名合格的网络安全从业人员。 一、网络安全基础知识 1.计算机基础知识 …

蓝桥杯省赛冲刺(3)广度优先搜索

广度优先搜索(Breadth-First Search, BFS)是一种在图或树等非线性数据结构中遍历节点的算法,它从起始节点开始,按层级逐步向外扩展,即先访问离起始节点最近的节点,再访问这些节点的邻居,然后是邻…

DCI-BOX 数据中心互联扩容设备

2U DCI-BOX是针对DCI数据互联开发的一款高性能、大容量DCI平台 恒通未来2U DCI-BOX 优势: 随着5G网络的演进,人们对大数据需求越来越旺盛,2U DCI-BOX是针对DCI数据互联开发的一款高性能、大容量DCI平台。 1. 单机箱最大容量6.4T,单100G功耗…

设计模式——简单工厂模式

设计模式——简单工厂模式 什么是简单工厂模式简单工厂模式的优点 我们今天接着来看设计模式的简单工厂模式,如果还没看过上一篇的单列模式的小伙伴可以点击这里: https://blog.csdn.net/qq_67693066/article/details/136603292 什么是简单工厂模式 简单…

【c语言】结构体的访问

🎈个人主页:豌豆射手^ 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:C语言 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步&…

宏景eHR customreport/tree SQL注入漏洞复现

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合,满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景eHR customreport/tree 接口处存在SQL注入漏洞,未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令,从而窃取数据库…

【cocos creator】【TS】贝塞尔曲线,地图之间显示曲线,顺着曲线移动

参考: https://blog.csdn.net/Ctrls_/article/details/108731313 https://blog.csdn.net/qq_28299311/article/details/104009804 const { ccclass, property } cc._decorator;ccclass export default class mapPanel extends cc.Component {property(cc.Node)pla…

力扣HOT100 - 41. 缺失的第一个正数

解题思路: 原地哈希 就相当于,让每个数字n都回到下标为n-1的家里。 而那些没有回到家里的就成了孤魂野鬼流浪在外,他们要么是根本就没有自己的家(数字小于等于0或者大于nums.size()),要么是自己的家被别…

试题 C: 质因数个数

萎了&#xff0c;整个人都萎了 快三天都没刷题了&#xff0c;想着明天就蓝桥杯了&#xff0c;就找了个真题做了下 可以看得出来这题很简单 但是没有测试点给我用&#xff0c;所以我的代码不保证正确性 代码如下&#xff1a; #include<cstdio> #include<cmath> …

014:vue3 van-list van-pull-refresh实现上拉加载,下拉刷新

文章目录 1. 实现上拉加载&#xff0c;下拉刷新效果2. van-list&#xff0c;van-pull-refresh组件详解2.1 van-list组件2.2 van-pull-refresh组件 3. 完整案例4. 坑点&#xff1a;加载页面会一直调用加载接口 1. 实现上拉加载&#xff0c;下拉刷新效果 通过下拉刷新加载下一页…

20240405,数据类型,运算符,程序流程结构

是我深夜爆炸&#xff0c;不能再去补救C了&#xff0c;真的来不及了&#xff0c;不能再三天打鱼两天晒网了&#xff0c;真的来不及了呜呜呜呜 我实在是不知道看什么课&#xff0c;那黑马吧……MOOC的北邮的C正在进行呜呜 #include <iostream> using namespace std; int…

力扣 | 54. 螺旋矩阵

注意按照顺时针方向进行访问元素&#xff0c;以及每次触发的条件只会满足一个&#xff01; public List<Integer> spiralOrder(int [][] matrix){List<Integer> result new ArrayList<>();int m matrix.length;int n matrix[0].length;int row0,col 0;//…