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