当前位置: 首页 > 科技观察

13张图吃透分布式系统服务注册与发现原理

时间:2023-03-13 18:33:12 科技观察

本文转载自微信公众号“笑嘻嘻的架构师”,可通过以下二维码关注。转载本文,请联系LoveSmile的架构师公众号。在微服务架构或分布式环境中,服务注册和发现技术是必不可少的。这也是程序员在进阶之路上必须掌握的核心技术之一。本文通过图表的方式,引导大家轻松掌握。引入服务注册和发现组件的原因我们先来看一个问题。如果我们现在要做一个商城项目,作为架构师应该如何设计系统架构呢?你心里一定在想:直接照抄淘宝的架构不好不就行了。但在真正的创业环境中,一个项目可能会濒临死亡。如果一开始就投入大量的人力和财力,一旦项目失败,就会损失惨重。作为一个经验丰富的架构师,根据公司的财力和人力投入预算选择最合适的架构才是王道。大网站是从小网站发展起来的,架构也是如此。任何大型网站的架构都不是从一开始就一成不变的,而是随着用户数量和数据量不断增加而不断迭代演化的结果。我们在架构不断迭代演进的过程中会遇到很多问题。技术发展的本质就是不断发现问题然后解决问题,解决问题再发现问题。单体架构在系统建立之初可能没有很多用户。所有服务都打包成一个应用程序包,运行在tomcat容器中,与数据库共享一台服务器。这种架构通常被称为单体架构。.单体架构——应用和数据库共部署,前期非常高效,可以根据用户反馈快速迭代上线。但是随着用户数量的增加,一个服务的内存和CPU吃紧,很容易造成瓶颈。如何解决新问题?应用与数据分离随着用户请求数量的增加,服务器的内存和CPU不断飙升,用户请求响应时间变慢。这时候可以考虑把应用和数据库分开,各用一台服务器。你看,问题又解决了。单体架构——应用与数据库分离有一天扫地阿姨不小心碰到了电线,其中一台服务器断电,所有用户请求都报错,随之而来的是一连串的投诉电话。在集群中部署单实例很容易出现单点问题,比如服务器故障或者服务容量瓶颈,怎么办?聪明的你一定想到过用集群。应用集群部署集群部署是指在多台服务器或虚拟机上部署应用程序。用户通过服务均衡随机访问其中一个实例,使多个实例的流量均衡。如果一个实例失败,它可以脱机。实例不受影响,仍然可以对外提供服务。随着用户数量的激增,老板决定加大投入扩大团队规模。开发团队壮大后,开发团队的效率并没有明显提升。以前一个小团队一周可以迭代上线一次,现在至少需要两到三周。业务逻辑越来越复杂,代码之间的耦合非常严重。修改一行代码可能会引入几个在线问题。架构师认识到架构重构的必要性。当微服务架构演进到一定阶段,开发和测试的复杂度会增加,团队规模的扩大也会让他们工作的耦合度更加严重。这是牵动全身的情景。当单体架构遇到瓶颈时,微服务架构应运而生。微服务就是将之前的单体服务按照业务维度进行拆分。拆分粒度可大可小,拆分时机可根据节奏进行。最佳实践是先将一些独立的功能从单体中分离出来,抽取成一个或多个微服务,这样可以保证业务的连续性和稳定性。微服务架构将一个商业应用拆分成六个独立的微服务,如上图所示。使用Docker容器化,可以使用多个实例部署六个微服务。架构的演进在这里遇到了问题。如果要查询用户的所有订单,用户服务可能依赖于订单服务。用户服务如何与订单服务交互?当订单服务有多个实例时应该访问哪一个?通常有几种解决方法:(1)服务地址硬编码将服务的地址硬编码在数据库或配置文件中,通过访问DNS域名进行地址路由。服务元数据是硬编码的。服务B的地址硬编码在数据库或配置文件中。服务A首先需要获取服务B的地址,然后通过DNS服务器解析获取其中一个实例的真实地址,最后向服务B发起请求。如果某个服务实例在大促的时候需要扩容,并且大促后服务实例需要下线,运维人员需要做大量的手工操作,非常容易误操作。(2)服务动态注册和发现服务地址硬编码还有一个很致命的问题。如果某个实例宕机,运维人员可能无法及时发现,导致部分用户的请求出现异常。服务注册和发现组件的引入,可以解决上面遇到的问题,避免过多的手动操作。架构演进总结在单体架构中,一个应用就是一个服务包,包中的模块通过函数和方法相互调用。该模型足够简单,没有服务注册和发现之类的东西。在微服务架构中,一个应用被拆分成多个微服务,微服务会部署在不同的服务器、不同的容器,甚至多个数据中心。微服务需要相互调用,服务注册和发现成为一个单一的过程。不可或缺的组成部分。服务注册和发现的基本原理服务注册和发现分为两个关键步骤:注册和发现。服务注册:服务进程在注册中心注册自己的元数据信息。通常包括主机号和端口号,有时还包括身份验证信息、协议、版本号和有关操作环境的信息。服务发现:客户端服务进程向注册中心发起查询,获取服务信息。服务发现的一个重要作用是为客户端提供可用服务的列表。服务注册服务注册有两种形式:客户端注册和代理注册。客户端注册客户端注册是服务本身负责注册和注销的工作。当服务启动时,注册线程向注册中心注册,当服务下线时,它自己注销。这种客户端注册方式的缺点是注册和注销逻辑与服务的业务逻辑耦合在一起。如果服务是用不同语言开发的,需要适配多套服务注册逻辑。代理注册代理注册由用于注册和注销的单独代理服务处理。服务提供者在启动时,通过一定的方式通知代理服务,然后由代理服务负责向注册中心发起注册工作。这种代理注册方式的缺点是多了一个代理服务的引用,而且代理服务必须保持高可用状态。服务发现服务发现也分为客户端发现和代理发现。客户端发现客户端发现是指客户端负责向注册中心查询可用的服务地址,在得到所有可用实例地址的列表后,客户端根据负载均衡算法选择一个实例发起请求调用。客户端觉得这个方法很直接,客户端可以控制负载均衡算法。但缺点也很明显。获取实例地址和负载均衡的逻辑与服务的业务逻辑耦合在一起。如果服务发现或负载平衡发生变化,则必须修改并重新启动所有服务。ProxydiscoveryProxydiscovery是指增加一个路由服务,负责服务发现,获取可用实例列表。如果服务消费者需要调用服务A的实例,可以直接向路由服务发送请求。路由服务从配置的负载均衡算法开始。只需从可用实例列表中选择一个实例并将请求转发到那里。如果发现实例不可用,路由服务可以自行重试,服务消费者完全不需要感知。代理路由服务注册心跳机制如果服务有多个实例,其中一个实例宕机,注册中心可以实时感知,将实例信息从列表中移除,也称为摘机。如何实现摘机?业界比较常见的方式是通过心跳检测。心跳检测有两种方式:主动和被动。被动检测是指服务主动向注册中心发送心跳消息。时间间隔可以自定义。比如配置为每5秒发送一次。该实例已从列表中删除。心跳机制-被动检测上图中服务A的实例2已经宕机,无法主动向注册中心发送心跳消息。注册将在15秒后删除实例2。主动检测由注册中心发起。每隔几秒,就会向列表中的所有服务实例发送一条心跳检测消息。若消息发送不成功或多次循环未收到回复,则该实例将被主动移除。心跳机制——业内常用服务注册与发现组件的主动检测对比了解了服务注册与发现的基本原理后,如果想在项目中使用服务注册与发现组件,面对众多的服务注册与发现组件如何选择技术开源组件?在互联网公司中,具有研发能力的大公司一般会选择基于开源组件的自研或二次开发,但对于中小型公司来说,直接选择一个开源软件是一个不错的选择。常用的注册和发现组件有eureka、zookeeper、consul、etcd等,由于eureka已经宣布2018年放弃维护,这里不再推荐。业界开源组件下面是各个组件结合各个维度的对比。组件优点缺点接口类型一致性算法zookeeper1.功能强大,不仅仅是服务发现;2、提供watcher机制,实时获取服务商状态;3、应用广泛,dubbo等微服务框架已经支持;1.没有体检;2.服务中需要引入sdk,集成复杂度高;3.不支持多数据中心;sdkPaxosconsul1.开箱即用,易于集成;2.有健康检查;3.支持多数据中心;4.提供网页管理界面;无法实时获取服务变更通知restful/dnsRaftetcd1.开箱即用,易于集成;二、可配置性强1、无健康检查;2.需要配合三方工具完成服务发现功能;3.不支持多数据中心;restfulRaft整体来说,consul的功能更加完善和均衡。下面以consul为例详细介绍一下。Consul——推荐用于服务注册和发现的开源组件Consul简介Consul是HashiCorp推出的一款开源工具,使用Go语言开发,具有开箱即用的易部署特点。Consul是一个分布式的、高可用的、可水平扩展的分布式系统服务发现和配置。领事的优势是什么?服务注册和发现:Consul提供了一种通过DNS或restful接口注册和发现服务的方法。可根据实际情况选择服务。健康检查:Consul的客户端可以提供任意数量的健康检查,与给定服务或本地节点相关联。多数据中心:Consul支持多数据中心,这意味着用户无需担心Consul本身的高可用以及多数据中心带来的扩展访问。Consul架构图Consul架构Consul依赖于gossip协议实现了多个数据中心。这是做什么的:无需使用服务器地址配置客户端;服务发现是自动完成的。健康检查失败的工作不放在服务器上,而是分布式的。Consul的使用场景Consul的应用场景包括服务注册发现、服务隔离、服务配置。在服务注册发现场景中,使用consul作为注册中心。在consul中注册好服务地址后,就可以使用consul提供的dns和http接口进行查询了。consul支持健康检查。在服务隔离场景下,consul支持按服务设置访问策略,同时支持经典平台和新兴平台,支持tls证书分发,服务到服务加密。在服务配置场景中,consul提供了key-value数据存储功能,可以快速通知变化。借助Consul,可以实现配置共享。需要读取配置的服务可以从Consul读取准确的配置信息。