- 实现微服务的服务注册中心,支持服务服务注册、接收心跳等。
- 客户端实现基于注册中心的服务发现机制
微服务
微服务是一些协同工作的小而自治的服务
微服务主要分为六个部分组成
服务描述:类似服务的文档说明,简单但不可或缺。
比如:服务调用首先要解决的问题是服务如何对外描述。服务名叫什么?调用服务需提供那些信息?调用服务返回结果是什么格式?如何解析?注册中心:解决服务的发布和订阅
提供了一个服务(Provider)后,如何让外部(Consumer)想调用它的人知道。此时就需要一个类似注册中心(Registry)的角色,服务提供者将自己提供的服务以及地址登记到注册中心,服务消费者从注册中心查询所需调用的服务地址,然后发起请求。服务框架
通过注册中心,服务消费者可以获取到服务提供者的地址,有了地址后可以发起调用。但发起调用前需要解决:服务通信采用什么协议?数据传输采用什么方式?数据压缩采用什么格式?这些通常都会集成到服务框架中。服务监控
一旦服务消费者和服务提供者之间能够正常发起服务调用,就需要对调用情况进行监控以了解服务是否正常。通常来说,服务监控主要分为三个流程:指标收集、数据处理、数据展示。监控是为了发现问题和异常,进一步跟踪和定位问题,则需进一步了解服务追踪。服务追踪
除了需要对服务调用情况进行监控外,还需记录服务调用经过的每一层链路,以便进行问题追踪和故障定位,最后达到接近问题的目的。服务监控和追踪可以合并,但要明确各自的职责。服务治理
服务监控能够发现问题,服务追踪能够定位问题,解决问题就得靠服务治理。服务治理是通过一系列手段来保证在各种意外情况下,服务调用仍能够正常运行。
创建微服务首先需要考虑服务的如下三个方面
- 通信框架:解决客户端和服务端如何建立连接、管理连接、服务端如何处理请求的问题。采用同步还是异步,是在单连接上传输还是多路复用?
- 通信协议:解决客户端和服务端采用哪种数据传输协议,是采用四层的TCP、UDP,还是采用七层的HTTP?
- 序列化和反序列化:解决客户端和服务端采用哪种数据编解码问题,采用JSON、Protobuf?
角色
微服务架构下主要存在三种角色
- 服务提供者(Provider:Server)
服务提供者提供服务,服务启动时根据服务发布文件中的配置信息向注册中心注册自身服务,并向注册中心定期发送心跳汇报存活状态。
- 服务消费者(Consumer:Client)
服务消费者调用服务,启动时根据服务引用文件中配置的信息,向服务中心订阅服务,将注册中心返回的服务节点列表缓存在本地内存中,并于服务端建立连接。
当服务端列表发生变更时,注册中心会同步变更,客户端感知后会刷新本地内存中缓存中的服务节点列表。
客户端从本地缓存的服务节点列表中,基于负载均衡算法选择一台服务端发起调用。
- 服务注册中心(Registry)
3.1 注册中心必须提供最基本的API
- 服务注册接口:服务提供者通过调用服务注册接口来完成服务注册,一般使用租约或TTL、PUT设置值。
- 服务反注册接口(delete):服务提供者通过调用服务反注册接口来完成服务注销
- 心跳汇报接口:服务提供者通过调用心跳汇报接口完成节点存活状态上报,一般会使用租约来续租。
- 服务订阅接口(watch):服务消费者通过调用服务订阅接口完成服务订阅,获得可用的服务提供者节点列表。
- 服务变更查询接口(get):服务消费者通过调用服务变更查询接口获取最新的可用服务节点列表
3.2 除此之外,为了便于管理,注册中心还必须提供一些后台管理的API。
- 服务查询接口:查询注册中心当前注册了那些服务信息
- 服务修改接口:修改注册中心某些服务的信息
服务注册和发现
微服务或分布式环境下,各个服务的独立部署和分布,组合成一个分布式应用。服务和服务之间相互关联调用,如何管理这些服务,服务注册和发现应运而生。
服务注册和发现主要解决服务依赖问题,通常如果服务A调用服务B,最直接的做法是配置IP地址和端口,随着服务依赖变多时,配置将会庞杂。当服务发生迁移时,所有相关服务的配置均需修改,这将难以维护且易出错。为了解决这种服务依赖关系,服务注册和发现应用而生。
服务注册与发现主要分为
- 服务信息发布:主要包括服务名、IP信息、附件元数据,通过注册接口注册到服务注册发布中心。
- 存活检测:当服务意外停止时,客户端需感知到服务停止,并将服务的IP地址踢出可用的IP地址列表,可使用定时心跳去实现。
- 客户端负载均衡:通过服务注册和发现可实现一个服务部署堕胎实例,客户端实现在实例直接的负载均衡,从而实现服务的横向扩展。
因此,服务注册和发现可以概括为:
- 服务将信息上报
- 客户端拉取服务信息
- 通过服务名进行调用
- 当服务宕机时客户端踢掉故障服务
- 服务新上线时客户端自动添加到调用列表
服务调用
服务调用方式主要是指微服务中服务之间调用的方式,主要可分为两类:
-
基于负载均衡:通过负载均衡设备对外提供VIP地址来实现服务的调用
基于注册中心:微服务之间通过服务注册中心进行节点发现,然后再服务端直接调用对应的节点进行调用。
基于负载均衡的服务调用
基于负载均衡的服务调用是指通过LVS、Haproxy、Nginx等负载均衡软件来构建一个负载均衡服务,所有的服务都通过负载均衡器,负载均衡器的这种模式下主要有两个问题:
- 中心化:负载均衡设备成为微服务的中心,后期可能会成为微服务的系统瓶颈。
- 流量增倍:内网流量会被放大1倍,即客户端到负载均衡,负载均衡到后端节点。
负载均衡这种实现在早期是普遍适用的,可做一些负载均衡、长链接维护、分布式跟踪等。
基于注册中心的服务调用
所有的服务都启动后通过注册中心来i注册自己,同时把注册中心中的服务信息拉回本地,后续调用就直接检查本地服务和节点信息来进行服务节点的调用,是当前微服务架构中最普遍的做法。
注册中心的核心架构设计
注册中心单点实现的核心目标是提供注册表的高并发访问,为了提高性能并且尽可能保持一致性,在设计上通过全量同步和增量同步,来减少拉取的数据量从而提高系统的吞吐。主要核心有两点
- 注册表:注册表存储全量信息,提供hashcode用于做一致性校验。
- 事件队列:存储最近变更事件,后续只需增量同步即可保证一致性。
注册中心
- 服务的注册和发现是微服务必不可少的功能
服务端将服务的地址信息保存到注册中心后,定时的心跳检查或定时的重新注册。客户端监听注册中心,最好将服务信息保存到本地,监听服务的变动,更新缓存。当调用服务端的接口时,根据客户端的服务列表和负载算法选择服务端进行通信。
- 注册中心的位置
注册中心的好处在于:客户端和服务端都只需要感知注册中心的存在,而无需感知对象的存在。
- 服务端启动后向注册中心发送注册消息,注册中心得知该服务已经启动,处于可用状态。一般来说,服务端还需定期向注册中心发送心跳,证明自己还活着。
- 客户端向注册中心询问,当前那些服务是可用的,注册中心将可用的服务列表返回给客户端。
- 客户端根据注册中心得到服务列表,选择其一发起调用。
如果没有注册中心,客户端需要硬编码服务的地址,而且没有机制保证服务端是否处于可用状态。注册中心还可以提供比如配置的动态同步、通知机制等功能。
- 基于注册中心的服务调用
所有的服务启动后通过注册中心来注册自己,同时把注册中心中的服务信息拉回本地,后续调用,就直接检查本地的服务和节点来进行服务节点的调用。
- 注册中心的服务注册表
每个服务节点都会到注册中心进行服务注册,那么数据如何在服务端进行保存呢?其实就是注册表,等同于Windows中的注册表。每个服务都来注册,将自己的信息上报上来,然后注册中心把注册表返回给客户端。这样服务之间就知道需要调用服务的节点了。
需求分析
作为服务注册中心需实现的基本功能包括
- 服务注册:接受来自服务提交的注册信息并保存起来
- 服务下线:接受服务主动下线请求,并将服务从注册信息表中删除
- 服务获取:调用方从注册中心拉取服务信息
- 服务续约:服务健康检查,服务通过心跳保持(主动续约)告知注册中心服务可用。
- 服务剔除:注册中心将长时间不续约的服务实例从注册信息表中删除