永不失联!如何实现微服务架构中的服务发现?
Posted 灵雀云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了永不失联!如何实现微服务架构中的服务发现?相关的知识,希望对你有一定的参考价值。
编者按:在一文中,介绍了如何逐步地将单体应用改造为一系列的微服务。本文是系列文章的第四篇,将为大家讲述如何在微服务架构实现服务发现。作者首先介绍了服务发现的两种实现模式,接下来介绍了服务发现中最重要的服务注册如何实现。
作者简介:Chris Richardson是Cloudfoundry.com的创始人,现在为提供开发和部署应用的咨询服务。
以下为译文:
在一个现代的,基于云的微服务应用中,这个问题就变得复杂多了,如下图所示:
有两种主要的服务发现模式:客户端服务发现(client-side discovery)和服务器端服务发现(server-side discovery)。我们首先来看下客户端服务发现。
Netflix OSS提供了一个客户端服务发现的好例子。Netflix Eureka是一个服务注册表,提供了REST API用来管理服务实例的注册和查询可用的实例。Netflix Ribbon是一个IPC客户端,和Eureka一起处理可用服务实例的负载均衡。下面会深入讨论Eureka。
客户端的服务发现模式有优势也有缺点。这种模式相对直接,但是除了服务注册表,没有其它动态的部分了。而且,由于客户端知道可用的服务实例,可以做到智能的,应用明确的负载均衡决策,比如一直用hash算法。这种模式的一个重大缺陷在于,客户端和服务注册表是一一对应的,必须为服务客户端用到的每一种编程语言和框架实现客户端服务发现逻辑。
下图展示了这种模式的架构
客户端通过负载均衡器向一个服务发送请求,这个负载均衡器会查询服务注册表,并将请求路由到可用的服务实例上。通过客户端的服务发现,服务实例在服务注册表上被注册和注销。
AWS的ELB(Elastic Load Blancer)就是一个服务器端服务发现路由器。一个ELB通常被用来均衡来自互联网的外部流量,也可以用ELB去均衡流向VPC(Virtual Private Cloud)的流量。一个客户端通过ELB发送请求(HTTP或TCP)时,使用的是DNS,ELB会均衡这些注册的EC2实例或ECS(EC2 Container Service)容器的流量。没有另外的服务注册表,EC2实例和ECS容器也只会在ELB上注册。
HTTP服务器和类似nginx、Nginx Plus的负载均衡器也可以被用做服务器端服务发现负载均衡器。例如,Consul Template可以用来动态配置Nginx的反向代理。
Consul Template定期从存储在Consul服务注册表的数据中,生成任意的配置文件。每当文件变化时,会运行一个shell命令。比如,Consul Template可以生成一个配置反向代理的nginx.conf文件,然后运行一个命令告诉Nginx去重新加载配置。还有一个更复杂的实现,通过HTTP API或DNS去动态地重新配置Nginx Plus。
服务器端服务发现模式也是优势和缺陷并存。最大的好处在于服务发现的细节被从客户端中抽象出来,客户端只需要向负载均衡器发送请求,不需要为服务客户端使用的每一种语言和框架,实现服务发现逻辑;另外,这种模式也有一些问题,除非这个负载均衡器是由部署环境提供的,又是另一个高需要启动和管理的可用的系统组件。
正如上面提到的,Netflix Eureka是一个服务注册表的好例子。它提供了一个REST API用来注册和查询服务实例。一个服务实例通过POST请求来注册自己的网络位置,每隔30秒要通过一个PUT请求重新注册。注册表中的一个条目会因为一个HTTP DELETE请求或实例注册超时而被删除,客户端通过一个HTTP GET请求来检索注册的服务实例。
其它服务注册的例子包括:
Etcd:一个高可用,分布式,一致的key-value存储,用来共享配置和服务发现。Kubernetes和Cloudfoundry都使用了etcd;
Consul:一个发现和配置服务的工具。客户端可以利用它提供的API,注册和发现服务。Consul可以执行监控检测来实现服务的高可用;
Apache Zookeeper:一个常用的,为分布式应用设计的高可用协调服务,最开始Zookeeper是Hadoop的子项目,现在已经顶级项目了。
一些系统,比如Kubernetes,Marathon和AWS没有一个明确的服务注册组件,这项功能是内置在基础设置中的。
下面我们来看看服务实例如何在注册表中注册。
前面提到了,服务实例必须要从注册表中注册和注销,有很多种方式来处理注册和注销的过程。一个选择是服务实例自己注册,即self-registration模式。另一种选择是其它的系统组件管理服务实例的注册,即第third-party registration模式。
在self-registration模式中,服务实例负责从服务注册表中注册和注销。如果需要的话,一个服务实例发送心跳请求防止注册过期。下图展示了这种模式的架构:
Netflix OSS Eureka客户端是这种方式的一个好例子。Eureka客户端处理服务实例注册和注销的所有问题。Spring Cloud实现包括服务发现在内的多种模式,简化了Eureka的服务实例自动注册。仅仅通过@EnableEurekaClient注释就可以注释Java的配置类
self-registration模式同样也是优劣并存。优势之一在于简单,不需要其它组件。缺点是服务实例和服务注册表相对应,必须要为服务中用到的每种编程语言和框架实现注册代码。
在third-party registration模式中,服务实例不会自己在服务注册表中注册,由另一个系统组件service registrar负责。service registrar通过轮询部署环境或订阅事件去跟踪运行中的实例的变化。当它注意到一个新的可用的服务实例时,就会到注册表中去注册。service registrar也会将停止的服务实例注销,下图展示了这种模式的架构。
service registrar的一个例子是开源的Registrator项目。它会自动注册和注销像Docker容器一样部署的服务。Registrator支持etcd和Consul等服务注册。
另一个service registrar的例子是NetflixOSS Prana。主要用于非JVM语言编写的服务,它是一个和服务实例配合的『双轮』应用。Prana会在Netflix Eureka上注册和注销实例。
service registrar是一个部署环境的内置组件,由Autoscaling Group创建的EC2实例可以被ELB自动注册。Kubernetes服务也可以自动注册。
third-party registration模式主要的优势在于解耦了服务和服务注册表。不需要为每个语言和框架都实现服务注册逻辑。服务实例注册由一个专用的服务集中实现。缺点是除了被内置到部署环境中,它本身也是一个高可用的系统组件,需要被启动和管理。
服务发现的关键部分是服务注册表。服务注册表是一个可用的服务实例的数据库。服务注册表提供了一个管理API和一个查询API。服务实例的注册和注销通过管理API实现,查询API用来寻找可用的服务实例。
有两种主要的服务发现模式:客户端服务发现和服务器端服务发现。客户端服务发现系统中,客户端查询服务注册表,选择一个可用的实例,响应一个请求;在服务器端服务发现系统中,客户端通过一个路由器发送请求,这个路由器会去查询服务注册表,并将请求发送给可用的实例。
有两种形式可以实现服务实例的注册和注销,一种是self-registration模式,一种是third-party registration模式。
一些部署环境中,需要通过类似Netflix Eureka,etcd或Apache Zookeeper的组件,启动自己的服务发现基础设施。其它的部署环境中,服务发现是内置的。比如,Kubernetes和Marathon处理服务实例的注册和注销,还会在每个集群host上运行一个代理,作为服务器端服务发现路由器的角色。
一个HTTP反向代理和Nginx也可以被用做服务器端服务发现负载均衡器。服务注册表可以推送路由信息到Nginx,引起配置更新,比如可以用Consul Template。Nginx Plus支持动态的重配置机制,可以从注册表中拉取服务实例相关的信息,还提供了远程配置的API。
微服务
以上是关于永不失联!如何实现微服务架构中的服务发现?的主要内容,如果未能解决你的问题,请参考以下文章
网易蜂巢微服务架构:用RabbitMQ实现轻量级通信(有彩蛋)
Atitit.架构设计趋势 设计模式 ---微服务架构 soa