本文讲述下微服务架构中的服务发现机制。
为什么要使用服务发现机制
我们在调用微服务的过程中, 假设在调用某个REST API或者Thrift API, 为了完成某次调用请求, 代码里面需要指定服务所在的IP地址和端口, 在传统的应用中, 网络地址和端口是静态的,一般不会改变, 我们只需要把它们配到配置文件中, 就可以通过读取配置文件来完成调用.
但是, 在现代基于Cloud的微服务架构中, 这种方式将失效, 因为服务的实例是动态分配的地址, 网络地址也是动态的, 这样做的好处是便于服务的自动伸缩, 失败处理和升级.
基于此, 我们需要一个复杂的服务发现机制.
有两种服务发现的模型, 一种是客户端侧的服务发现, 另一种是服务侧的服务发现.
客户端侧的服务发现模式
当使用客户端发现时,客户端负责确定可用服务实例的网络位置,并在它们之间负载均衡。客户端查询服务注册表,这是可用服务实例的数据库。然后客户端使用负载均衡算法选择一个可用的服务实例并发出请求。
服务实例的网络位置在服务注册中心启动时注册。当实例终止时,它将从服务注册表中删除。服务实例的注册通常使用心跳机制定期刷新。
Netflix OSS提供了客户端发现模式的一个很好的例子。Netflix Eureka是一个服务注册中心。它提供了一个REST API,用于管理服务实例注册和查询可用实例。Netflix Ribbon是一个IPC客户机,它与Eureka一起工作,在可用的服务实例之间负载平衡请求。
客户端发现模式有许多优点和缺点。这种模式相对简单,除了service registry之外,没有其他可移除或者改变的部分。此外,由于客户端知道可用的服务实例,因此它可以做出智能的、特定于应用程序的负载平衡决策,比如一致性散列。此模式的一个显著缺点是,它将客户端与服务注册中心耦合在一起,我们必须为每个客户端都实现同样的逻辑, 而且这些客户端还不是用同样的语言实现的。
服务端侧的服务发现模式
另一种服务发现模式是服务端的,
客户端通过负载平衡器向服务发出请求。负载均衡器查询服务注册表并将每个请求路由到可用的服务实例。与客户端发现一样,服务实例在服务注册中心注册和注销。
亚马逊的ELB(Elastic Load Balancer) 是基于服务端的服务发现, ELB 主要平衡外部INternet的流量, ELB没有单独的服务注册中心, 相应的实例是在ELB本身进行服务注册的.
HTTP 服务器或者Nginx也可以用来作为一个服务器端的服务发现负载均衡。
在有些部署环境中, 例如Kubernetes, 在集群中的每个主机中都会运行一个代理, 这个代理可以作为负载均衡器, 代理会处理请求, 并透传到集群中正在运行的服务主机上。
服务器端发现模式有优点也有缺点
这种模式的一大好处是发现的细节从客户机中抽象出来。客户端只需向负载平衡器发出请求。这消除了为服务客户端使用的每种编程语言和框架实现发现逻辑的需要。
此外,如上所述,一些部署环境免费提供了此功能。然而,这种模式也有一些缺点。除非部署环境提供了负载平衡器,否则它仍然是您需要设置和管理的另一个高可用的系统组件。