为什么要使用服务发现?
设想一下,我们正在写代码使用了提供REST API或者Thrift API的服务,为了完成一次服务请求,代码需要知道服务实例的网络位置(IP地址和端口)。传统应用都运行在物理硬件上,服务实例的网络位置都是相对固定的。例如,代码可以从一个经常变更的配置文件中读取网络位置。
而对于一个现代的,基于云微服务的应用来说,这却是一个很麻烦的问题。其架构如图所示:
服务实例的网络位置都是动态分配的,而且因为扩展、失效和升级等需求,服务实例会经常动态改变,因此,客户端代码需要使用一种更加复杂的服务发现机制。
目前有两大类服务发现模式:客户端发现和服务端发现。
我们先来来讨论一下客户端发现。
客户端发现模式
当使用客户端发现模式时,客户端负责决定相应服务实例的网络位置,并且对请求实现负载均衡。客户端从一个服务注册服务中查询,其中是所有可用服务实例的库。客户端使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。
下图显示的是这种模式的架构图:
服务实例的网络位置是在启动时注册到服务注册表中,并且在服务终止时从注册表中删除。服务实例注册信息一般是使用心跳机制来定期刷新的。
Netflix OSS提供了一种非常棒的客户端发现模式。Netflix Eureka是一个服务注册表,为服务实例注册管理和查询可用实例提供了REST API接口。Netflix Ribbon是一种IPC客户端,与Eureka合同工作实现对请求的负载均衡。我们会在后面详细讨论Eureka。
客户端发现模式也是优缺点分明。这种模式相对比较直接,而且除了服务注册表,没有其它改变的因素。除此之外,因为客户端知道可用服务注册表信息,因此客户端可以通过使用哈希一致性(hashing consistently)变得更加聪明,更加有效的负载均衡。
而这种模式一个最大的缺点是需要针对不同的编程语言注册不同的服务,在客户端需要为每种语言开发不同的服务发现逻辑。
我们分析过客户端发现后,再看看服务端发现。
服务端发现模式
另外一种服务发现的模式是服务端发现模式(server-side discovery pattern),下图展现了这种模式的架构图:
客户端通过负载均衡器向某个服务提出请求,负载均衡器向服务注册表发出请求,将每个请求转发往可用的服务实例。跟客户端发现一样,服务实例在服务注册表中注册或者注销。
AWS Elastic Load Balancer(ELB)是一种服务端发现路由的例子,ELB一般用于均衡从网络来的访问流量,也可以使用ELB来均衡VPC内部的流量。客户端使用DNS,通过ELB发出请求(HTTP或者TCP)。ELB负载均衡器负责在注册的EC2实例或者ECS容器之间均衡负载,并不存在一个分离的服务注册表,而EC2实例和ECS实例也向ELB注册。
HTTP服务和类似NGINX和NGINX Plus的负载均衡器都可以作为服务端发现均衡器。例如,这篇博文就描述如何使用Consul Template来动态配置NGINX反向代理。Consul Template是周期性从存放在Consul Template注册表中配置数据重建配置文件的工具。当文件发生变化时,会运行一个命令。在如上博客中,Consul Template产生了一个nginx.conf文件,用于配置反向代理,然后运行一个命令,告诉NGINX重新调入配置文件。更复杂的例子可以用HTTP API或者DNS动态重新配置NGINX Plus。
某些部署环境,例如Kubernetes和Marathon在集群每个节点上运行一个代理,此代理作为服务端发现负载均衡器。为了向服务发出请求,客户端使用主机IP地址和分配的端口通过代理将请求路由出去。代理将次请求透明的转发到集群中可用的服务实例。
服务端发现模式也有优缺点。最大的优点是客户端无需关注发现的细节,客户端只需要简单的向负载均衡器发送请求,实际上减少了编程语言框架需要完成的发现逻辑。而且,如上说所,某些部署环境免费提供以上功能。
这种模式也有缺陷,除非部署环境提供负载均衡器,否则负载均衡器是另外一个需要配置管理的高可用系统功能。
服务注册表
服务注册表是服务发现很重要的部分,它是包含服务实例网络地址的数据库。服务注册表需要高可用而且随时更新。客户端可以缓存从服务注册表获得的网络地址。然而,这些信息最终会变得过时,客户端也无法发现服务实例。因此,服务注册表由若干使用复制协议保持同步的服务器构成。
如前所述,Netflix Eureka是一个服务注册表很好地例子,提供了REST API注册和请求服务实例。 服务实例使用POST请求注册网络地址,每30秒必须使用PUT方法更新注册表,使用HTTP DELETE请求或者实例超时来注销。可以想见,客户端可以使用HTTP GET请求接受注册服务实例信息。
Netflix通过在每个AWS EC2域运行一个或者多个Eureka服务实现高可用性,每个Eureka服务器都运行在拥有弹性IP地址的EC2实例上。DNS TEXT记录用于存储Eureka集群配置,其中存放从可用域到一系列Eureka服务器网络地址的列表。当Eureka服务启动时,向DNS请求接受Eureka集群配置,确认同伴位置,给自己分配一个未被使用的弹性IP地址。
Eureka客户端—服务和服务客户端—向DNS请求发现Eureka服务的网络地址,客户端首选使用同一域内的服务。然而,如果没有可用服务,客户端会使用另外一个可用域的Eureka服务。
另外一些服务注册表例子包括:
-
etcd – 是一个高可用,分布式的,一致性的,键值表,用于共享配置和服务发现。两个著名案例包括Kubernetes和Cloud Foundry。
-
consul – 是一个用于发现和配置的服务。提供了一个API允许客户端注册和发现服务。Consul可以用于健康检查来判断服务可用性。
-
Apache ZooKeeper – 是一个广泛使用,为分布式应用提供高性能整合的服务。Apache ZooKeeper最初是Hadoop的子项目,现在已经变成顶级项目。
另外,前面强调过,某些系统,例如Kubernetes、Marathon和AWS并没有独立的服务注册表,对他们来说,服务注册表只是一个内置的功能。
现在我们来看看服务注册表的概念,看看服务实例是如何在注册表中注册的。
服务注册选项
如前所述,服务实例必须向注册表中注册和注销,如何注册和注销也有一些不同的方式。一种方式是服务实例自己注册,也叫自注册模式(self-registration pattern);另外一种方式是为其它系统提供服务实例管理的,也叫第三方注册模式(third party registration pattern)。我们来看看自注册模式。
自注册方式
当使用自注册模式时,服务实例负责在服务注册表中注册和注销。另外,如果需要的话,一个服务实例也要发送心跳来保证注册信息不会过时。下图描述了这种架构:
一个很好地例子是 Netflix OSS Eureka client。Eureka客户端负责处理服务实例的注册和注销。Spring Cloud project,实现了多种模式,包括服务发现,使得向Eureka服务实例自动注册时更容易。可以用@EnableEurekaClient注释Java配置类。
自注册模式也有优缺点。一个优点是,相对简单,不需要其他系统功能。而一个主要缺点则是,把服务实例跟服务注册表联系起来。必须在每种编程语言和框架内部实现注册代码。
另外一个方法,不需要连接服务和注册表,则是第三方注册模式。
第三方注册模式
当使用第三方注册模式时,服务实例并不负责向服务注册表注册,而是由另外一个系统模块,叫做服务管理器,负责注册。服务管理器通过查询部署环境或订阅事件来跟踪运行服务的改变。当管理器发现一个新可用服务,会向注册表注册此服务。服务管理器也负责注销终止的服务实例。下图是这种模式的架构图。
一个服务管理器的例子是开源项目Registrator,负责自动注册和注销被部署为Docker容器的服务实例。Reistrator支持多种服务管理器,包括etcd和Consul。
另外一个服务管理器例子是NetflixOSS Prana,主要面向非JVM语言开发的服务,也称为附带应用(sidecar application),Prana使用Netflix Eureka注册和注销服务实例。
服务管理器是部署环境内置的模块。有自动扩充组创建的EC2实例可以自向ELB自动注册,Kubernetes服务自动注册并且对发现服务可用。
第三方注册模式也是优缺点都有。主要的优点是服务跟服务注册表是分离的,不需要为每种编程语言和架构完成服务注册逻辑,替代的,服务实例是通过一个集中化管理的服务进行管理的。
一个缺点是,除非这种服务被内置于部署环境中,否则也需要配置管理一个高可用的系统。
总结
在一个微服务应用中,服务实例运行环境是动态变化的。实例网络地址也是动态变化的,因此,客户端为了访问服务必须使用服务发现机制。
服务发现关键部分是服务注册表,也就是可用服务实例的数据库。服务注册表提供一种注册管理API和请求API。服务实例使用注册管理API来实现注册和注销。
请求API用于发现可用服务实例,相对应的,有两种主要服务发现模式:客户端发现和服务端发现。
在使用客户端发现的系统中,客户端向服务注册表发起请求,选择可用实例,然后发出服务请求
而在使用服务端发现的系统中,客户端通过路由转发请求,路由器向服务注册表发出请求,转发此请求到某个可用实例。
服务实例注册和注销主要有两类方式。一种是服务实例自动注册到服务注册表中,也就是自注册模式;另外一种则是某个系统模块负责处理注册和注销,也就是第三方注册模式。
在某些部署环境中,需要配置自己的服务发现架构,例如:Netflix Eureka、etcd或者Apache ZooKeeper。而在另外一些部署环境中,则自带了这种功能,例如Kubernetes和Marathon 负责处理服务实例的注册和注销。他们也在每个集群节点上运行代理,来实现服务端发现路由器的功能。
HTTP反向代理和负载据衡器(例如NGINX)可以用于服务发现负载均衡器。服务注册表可以将路由信息推送到NGINX,激活一个实时配置更新;例如,可以使用 Consul Template。NGINX Plus 支持额外的动态重新配置机制,可以使用DNS,将服务实例信息从注册表中拉下来,并且提供远程配置的API。
在未来的博客中,我们还将深入探讨微服务其它特点。可以注册NGINX邮件列表来获得最新产品更新提示。
http://mp.weixin.qq.com/s?__biz=MzI4OTU3ODk3NQ==&mid=2247483738&idx=1&sn=97c698144bbac5d5ec3ac75bb1b0c1ab&chksm=ec2c4beadb5bc2fc690a6155eb00b073ee9d789c31ce6a6b57dfbd00bb8fce0fe53ce8a556b7&mpshare=1&scene=23&srcid=12250g9aGbOkM3d2GQl4SVb2#rd
相关推荐
1. **技术实践**:该项目不仅是一个理论上的案例分析,更是一个实际可行的系统设计方案。通过参与该项目的开发,开发者可以深入理解微服务架构的设计理念及其应用场景。 2. **业务模式创新**:代驾服务作为一种新兴...
投标人需明确表述自身的核心竞争力,如技术团队的专业技能、过往的成功案例、服务质量、项目管理经验等,以增强评审委员会的信心。 1. **成功案例**: 提供具体的成功案例,特别是与本次招标项目类似或相关的案例...
- **实战案例**:通过分析真实的系统架构设计案例,加深对理论知识的理解,提高解决实际问题的能力。 8. **软考策略** - **考试形式与要求**:了解考试结构、题型和评分标准,制定有效的复习策略。 - **模拟试题...
3. **编程实践**:提供具体的编程案例,展示如何运用C++实现面向对象设计。 #### 第七章:测试与改错 1. **测试策略**:概述软件测试的基本类型,包括单元测试、集成测试、系统测试等。 2. **缺陷管理**:讨论缺陷...
2. **架构模式与原则**:讲解常见的架构模式(如MVC、SOA、微服务)以及设计原则(如单一职责、开放封闭原则)。 3. **架构技能**:培养分析问题、决策制定和沟通协调的能力,这些都是架构师的重要素质。 4. **...
5. 实践经验:通过案例研究和实际项目经验,提高解决复杂问题的能力。 通过这份《系统架构设计师章节分类真题》的学习,考生不仅可以提升专业技能,也能积累实战经验,为成功通过考试和成为优秀的系统架构设计师...
《系统架构设计师试题及答案详解》是一份针对2014年下半年系统架构设计师考试的珍贵资料,涵盖了综合知识、案例分析以及论文等重要考试部分。这份压缩包文件旨在帮助考生全面理解和掌握系统架构设计的核心知识,提升...
这套课件可能会通过实例、案例分析和实战练习来帮助学习者理解和掌握这些概念,使他们能够将理论知识应用于实际项目中。无论你是计算机专业的学生,还是已经在职场的软件工程师,都能从中受益,提升自己的软件工程...
软件设计师考试是针对计算机软件设计与开发人员的一项专业资格...在实际考试中,下午题通常涉及设计案例分析,因此,对07软考设计师模拟试题6(下午题)da.doc的深入理解和解答将有助于考生熟悉这种题型,提升实战能力。
【标题】"MBA代码存储库:mba-fib,专注Web和移动应用软件工程实践" 在软件开发领域,尤其是在Web和移动应用...同时,对于学生和初学者来说,这是一个极好的实战案例,有助于他们理解和掌握Web和移动应用的开发流程。