分布式【凤凰架构】

服务注册与发现

服务注册:(如调用 API、产生事件消息、在 ZooKeeper/Etcd 的指定位置记录、存入数据库,等等)将自己的坐标信息通知到服务注册中心,这个过程可能由应用程序本身来完成,称为自注册模式,譬如 Spring Cloud 的@EnableEurekaClient 注解;也可能由容器编排框架或第三方注册工具来完成,称为第三方注册模式,譬如 Kubernetes 和 Registrator。

  • 服务的维护(Service Maintaining):尽管服务发现框架通常都有提供下线机制,但并没有什么办法保证每次服务都能优雅地下线(Graceful Shutdown)而不是由于宕机、断网等原因突然失联。所以服务发现框架必须要自己去保证所维护的服务列表的正确性,以避免告知消费者服务的坐标后,得到的服务却不能使用的尴尬情况。现在的服务发现框架,往往都能支持多种协议(HTTP、TCP 等)、多种方式(长连接、心跳、探针、进程状态等)去监控服务是否健康存活,将不健康的服务自动从服务注册表中剔除。
  • 服务的发现(Service Discovery):这里的发现是特指狭义上消费者从服务发现框架中,把一个符号(譬如 Eureka 中的 ServiceID、Nacos 中的服务名、或者通用的 FQDN)转换为服务实际坐标的过程,这个过程现在一般是通过 HTTP API 请求或者通过 DNS Lookup 操作来完成,也还有一些相对少用的方式,譬如 Kubernetes 也支持注入环境变量来做服务发现。

服务注册中心都是以集群的方式进行部署的,通常使用三个或者五个节点(通常最多七个,一般也不会更多了,否则日志复制的开销太高)来保证高可用。注册中心这有CAP矛盾,副本间的CP和AP

服务注册中心Eureka

Eureka 的选择是优先保证高可用性,相对牺牲系统中服务状态的一致性。Eureka 的各个节点间采用异步复制来交换服务注册信息,当有新服务注册进来时,并不需要等待信息在其他节点复制完成,而是马上在该服务发现节点宣告服务可见,只是不保证在其他节点上多长时间后才会可见。同时,当有旧的服务发生变动,譬如下线或者断网,只会由超时机制来控制何时从哪一个服务注册表中移除,变动信息不会实时的同步给所有服务端与客户端。这样的设计使得不论是 Eureka 的服务端还是客户端,都能够持有自己的服务注册表缓存,并以 TTL(Time to Live)机制来进行更新,哪怕服务注册中心完全崩溃,客户端在仍然可以维持最低限度的可用。Eureka 的服务发现模型对节点关系相对固定,服务一般不会频繁上下线的系统是很合适的,以较小的同步代价换取了最高的可用性;Eureka 能够选择这种模型的底气在于万一客户端拿到了已经发生变动的错误地址,也能够通过 Ribbon 和 Hystrix 模块配合来兜底,实现故障转移(Failover)或者快速失败(Failfast)。

Consul

Consul 的选择是优先保证高可靠性,相对牺牲系统服务发现的可用性。Consul 采用Raft 算法,要求多数派节点写入成功后服务的注册或变动才算完成,严格地保证了在集群外部读取到的服务发现结果必定是一致的;同时采用 Gossip 协议,支持多数据中心之间更大规模的服务同步。 没有 Netflix OSS 那样有着全家桶式的微服务组件兜底

CP还是AP 取决于 更不能容忍 分区不一致还是不可用

如果是基于 Etcd/zookeeper 实现的,那自然是 CP 的,如果是基于内存异步复制的方案实现的,那就是 AP 的(仅针对 DNS 服务器本身,不考虑本地 DNS 缓存的 TTL 刷新) Redis AP的

专门用于服务发现的框架和工具,这类的代表是 Eureka、Consul 和 Nacos。这一类框架中,你可以自己决定是 CP 还是 AP 的问题,譬如 CP 的 Consul、AP 的 Eureka,还有同时支持 CP 和 AP 的 Nacos

网络IO

每一次网络访问,从远程主机返回的数据会先存放到操作系统内核的缓冲区中,然后内核的缓冲区复制到应用程序的地址空间,所以当发生一次网络请求发生后,将会按顺序经历“等待数据从远程主机到达缓冲区”和“将数据从内核缓冲区拷贝到应用程序地址空间”两个阶段,根据实现这两个阶段的不同方法,人们把网络 I/O 模型总结为两类、五种模型

异步 I/O 中数据到达缓冲区后,不需要由调用进程主动进行从缓冲区复制数据的操作,而是复制完成后由操作系统向线程发送信号,所以它一定是非阻塞的。

同步 I/O(Synchronous I/O):

  1. 阻塞 I/O(Blocking I/O):你去到饭堂,发现饭还没做好,你也干不了别的,只能打个瞌睡(线程休眠),直到饭做好。阻塞 I/O 是最直观的 I/O 模型,逻辑清晰,也比较节省 CPU 资源,但缺点就是线程休眠所带来的上下文切换,这是一种需要切换到内核态的重负载操作,不应当频繁进行。

2. 非阻塞 I/O(Non-Blocking I/O):每隔 3 分钟轮询直到饭做好。白白浪费了 CPU 资源,所以目前并不常用

3. 多路复用 I/O(Multiplexing I/O):多路复用 I/O 本质上是阻塞 I/O 的一种,但是它的好处是可以在同一条阻塞线程上处理多个不同端口的监听类比的情景是你名字叫雷锋,代表整个宿舍去饭堂打饭,去到饭堂,发现饭还没做好,还是继续打瞌睡,但哪个舍友的饭好了,你就马上把那份饭送回去,然后继续打着瞌睡哼着歌等待其他的饭做好。多路复用 I/O 是目前的高并发网络应用的主流,它下面还可以细分 select、epoll、kqueue 等不同实现。

4.信号驱动 I/O(Signal-Driven I/O):你去到饭堂,发现饭还没做好,但你跟厨师熟,跟他说饭做好了叫你,然后回去该干嘛干嘛,等收到厨师通知后,你把饭从饭堂拿回宿舍。这里厨师的通知就是那个“信号”,信号驱动 I/O 与异步 I/O 的区别是“从缓冲区获取数据”这个步骤的处理,前者收到的通知是可以开始进行复制操作了,即要你自己从饭堂拿回宿舍,在复制完成之前线程处于阻塞状态,所以它仍属于同步 I/O 操作,而后者收到的通知是复制操作已经完成,即外卖小哥已经把饭送到了。

服务容错

故障转移(Failover):高可用的服务集群中,多数的服务——尤其是那些经常被其他服务所依赖的关键路径上的服务,均会部署有多个副本。这些副本可能部署在不同的节点(避免节点宕机)、不同的网络交换机(避免网络分区)甚至是不同的可用区(避免整个地区发生灾害或电力、骨干网故障)中。故障转移是指如果调用的服务器出现故障,系统不会立即向调用者返回失败结果,而是自动切换到其他服务副本,尝试其他副本能否返回成功调用的结果,从而保证了整体的高可用性。故障转移的容错策略应该有一定的调用次数限制,譬如允许最多重试三个服务,如果都发生报错,那还是会返回调用失败。原因不仅是因为重试是有执行成本的,更是因为过度的重试反而可能让系统处于更加不利的状况。

快速失败(Failfast):还有另外一些业务场景是不允许做故障转移的,故障转移策略能够实施的前提是要求服务具备幂等性,对于非幂等的服务,重复调用就可能产生脏数据,引起的麻烦远大于单纯的某次服务调用失败,此时就应该以快速失败作为首选的容错策略。譬如,在支付场景中,为了避免重复扣款,此时最恰当可行的方案就是尽快让服务报错,坚决避免重试,尽快抛出异常,由调用者自行处理。

广播调用(Broadcast):广播调用与并行调用是相对应的,都是同时发起多个调用,但并行调用是任何一个调用结果返回成功便宣告成功,广播调用则是要求所有的请求全部都成功,这次调用才算是成功,任何一个服务提供者出现异常都算调用失败,广播调用通常会被用于实现“刷新分布式缓存”这类的操作。

断路器

断路器的基本思路是很简单的,就是通过代理(断路器对象)来一对一地(一个远程服务对应一个断路器对象)接管服务调用者的远程请求。断路器会持续监控并统计服务返回的成功、失败、超时、拒绝等各种结果,当出现故障(失败、超时、拒绝)的次数达到断路器的阈值时,它状态就自动变为“OPEN”,后续此断路器代理的远程访问都将直接返回调用失败,而不会发出真正的远程服务请求。避免服务雪崩

服务熔断和服务降级之间的联系与差别。断路器做的事情是自动进行服务熔断,这是一种快速失败的容错策略的实现方法。在快速失败策略明确反馈了故障信息给上游服务以后,上游服务必须能够主动处理调用失败的后果,而不是坐视故障扩散,这里的“处理”指的就是一种典型的服务降级逻辑,降级逻辑可以包括,但不应该仅仅限于是把异常信息抛到用户界面去,而应该尽力想办法通过其他路径解决问题,譬如把原本要处理的业务记录下来,留待以后重新处理是最低限度的通用降级逻辑。

全部评论

相关推荐

昨天 20:36
已编辑
字节跳动_llm开发(实习员工)
bg:双非本 985硕士 五段实习(四段大厂,都是后端) + 开源经历(300+star)+ 大模型经验 + 懂前端(前端转的后端),主要考虑杭州的base。不是标题党哈,本人是真有点劝退后端了。究其原因就是后端这边实在是太卷了,从我自己亲身体会可以看出来。1、暑期:本人投递暑期前已有三段实习(其中2段大厂实习)。其中字节和腾讯明确要求我3月份就要到岗(有截图作证),而且字节2月份的时候就打电话给我约面了,最终我字节也是于3月中旬入职暑期(字节base南京,能边上课边实习)。因为我本身还有课在身上,在腾讯面试的时候说了只能五月份到岗,明确感受到面试官对我的热情降下来了,后续泡了1-2周也挂了。暑期暑期,变成了不在暑期的实习,暑期实习总结可以看之前的帖子。2、秋招:本人秋招虽然投递稍微晚一点,基本上是7月底开始大范围投递,这时候提前批基本都在尾声了(提前批没有任何约面),9月份的时候基本上手里就没啥面试了(说好的金9银10呢)。然后在这个时候我是5段实习(四段大厂实习),以为秋招能乱杀,时至今日,也就3个意向在手(BAT一个没有)。挂:① 字节:tt直播二面挂 抖音电商hr面挂 开发者服务二面挂(通过,但后续不推进)。字节我是从基本上8月份开始面试一直面到上周,都挂了,可能运气也差点。抖音电商尤其是面试的时候问了一些例如洗牌算法、尾递归等我不太了解,可能是导致横向被挂的主要原因。字节说白了每一轮都在横向,运气也很重要。抖音电商尤其如此,泡了一个月很是难绷(当初说两天出结果嘻嘻)。② 百度、滴滴、pdd等:笔试挂百度提前批我当时不知道在哪投递,发现原来填了内推码就是提前批,没填就是普通批。普通批有笔试,提前批没笔试,但是我记得三道题我做了1.5还是1.8将近两道题,一直没约面,到目前还在共享中。滴滴笔试没太认真做,因为我投的很早但是一直泡着,后续发笔试的时候手里也有其他意向了,遂放弃。pdd感觉我那次比较难,而且pdd那个我用java过不了,但是用c++同样的思路能过。。③ 腾讯:七次一面挂腾讯由于暑期实习生太多,感觉人均一段腾讯实习一样,听说后续都坐不下了,搬到会议室当工位了(本人同学)。秋招也没啥正经后端部门约我,都是一些机器人部门、ieg游戏后端、wxg搜广推之类的。反正答对了也挂,答不对就更不用说了。问的问题也千奇白怪,有喜欢问思维题的例如倒水问题,有喜欢出一些奇怪的coding题的单例高性能配置刷新、hash算法等等。如果大家想去腾讯,感觉还是转正比较好,秋招机会太少(但是转正率也不高嘻嘻)。意向:① 快手:快手电商杭州转正,早早转正,组里也保温,目前top1。当然强度很大,懂得抖动。② 美团(9月初oc):早早1-2周内速通,也有人过来保温,c端业务感觉很香,目前没开奖。③ 京东(大概9月底-10月初阶段oc):oc了京东一个不知名的部门,一开始是京东零售一面问了一些点没答上来,然后泡两周挂了。重新一个部门1-2周速通,线下去的南京hr面,hr面的时候基于前人的经验表示自己投递比较晚,手里没有其他offer,遂oc(京东hr面的时候得表达自己对京东的忠心)。hr面:④ xhs:8.29投递,10.14 才四面完,目前没泡出来,商业技术。xhs流程是真的慢,感觉自己要泡死了。总结:我大约在9月份的时候手里就没啥面试了,所以后续也投递了一些例如b站、蚂蚁啥的,反正都没有啥约面的。基本只要有hr约我,我都会去面,手里也就oc了这3个意向,陆陆续续忙碌几个月,最终大概率还是去快手转正了。字节又重新开始一面了(难绷)。基于我个人的BG,我觉得首先学历越来越成为后端的一项门槛(重要考虑因素),我双非本985硕尚且如此,更何况很多双非本的同学呢。说起来,最近我有个学妹前端实习转正失败,后突然保研上岸一所211,我给她的建议是你到时候毕业不要做前端了,我说现在已经很卷了,2年后、3年后我不敢想是什么场景。身边985本硕的同学秋招也很失败,没有想象中那么好拿,暑期和秋招区别也确实很大,运气也是很重要的一环。然后也是建议后来人秋招早做准备(投递早很重要),自己卷那么多实习其实也是因为本科学历不好,想开大包,现在看来也不用这么卷,实习段数不重要,大概1-2段即可,投递的早机会大一点。然后最好是暑期转正就去自己想去的部门,这样秋招不至于太焦虑。然后现在没有oc的也没关系,很多人早早投递拿了意向所以暂时hc不多,待开奖后释放,还是有不少机会的,肯定是能上岸的,就是周期会长一点。跟🐖佬、timeErrors、壹宇各位大佬都经常聊天感觉大家都是很好的人,也感谢有这么一个牛客的平台供大家交流(薅了2000牛币),所有的私信我都会回。秋招也就告一段落,愿大家都上岸自己想去的公司,共勉。最后附上我的哈吉米~最近躺平,瓦(找妈妈游戏)也打到神话了,这下是真大结局了
后端转测开第一人:建议后端人均10段大厂实习+92
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务