【微服务架构】3 服务注册与发现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdp12315/article/details/89604997

服务注册与发现

微服务被设计成能够容易水平扩展,需要一种方法来解决多个服务实例如何定位,并且对多个服务的调用如何负载均衡。服务定位包括以下三个部分内容:
1.服务注册
2.服务调用
3.API网关

服务注册

服务注册是一个持久化的存储,用于记录当前可用的微服务列表,以及访问他们的路由信息。微服务之间通信需要注册服务,主要因为以下几个原因:
1.注册
当一个服务成功的部署后,微服务需要通过服务注册进行注册
2.心跳
微服务应该发送规律的心跳信息,到注册中心,用于表明当前微服务是正常工作,可以接受请求。
3.服务发现
为了调用其他服务,微服务需要调用注册中心获取可用的服务实例
4.注销
当一个服务关闭后,需要从注册列表中移除该服务。

第三方注册 VS 自注册

注册微服务可以在服务中实现也可以使用第三方注册服务。使用第三方注册服务,要求微服务准确测定当前状态并将信息传给注册服务。第三方注册服务也可以注销微服务。如果微服务自己执行注册和心跳检测,注册服务可以取消注册,如果发现心跳丢失。

使用第三方注册服务的优势是,可以将注册和心跳检测的逻辑与业务逻辑分离。缺点是软件需要部署额外的部分,微服务也需要提供健康端点给第三方注册服务使用。

自注册(self-registration)将注册和心跳检测逻辑写入到微服务自身中,这种方式需要小心处理代码测试。然而,很多服务注册解决方案提供一种方便的库用于服务注册,来降低编码的复杂度。

服务发现与注册方案

Consul

Eureka

这些都是开源的服务注册工具,Eureka是Netfli公司的技术,能很容易和其他解决方案进行集成,并且提供负载均衡和容错。

可用性 vs 一致性

大部分服务注册中心提供分区容忍,一致性或可用性。他们不可能同时满足CAP理论中三个条件。Eureka提供可用性,Consul和Apache Zookeeper提供一致性。如果我们应用需要在某一个能看到相同的视图,那么选用一致性的服务注册方案;如果需要很快的获得请求的答复,而不需要等待结果的一致性,可以选用可用性的方案。

服务调用

当服务需要与其他服务进行通信时,它需要使用存储到服务注册中心的信息。然后,通过服务端或客户端调用实际的微服务。

服务端

通过服务代理实现服务端通信,Service Proxy作为服务注册中心的一部分,或者独立的服务。当服务需要调用其他服务时,首先调用代理服务端点。这个代理服务会返回从服务注册中心获取的目标服务的地址。代理器将获取的结果和路由返回给原服务,提供给原服务用于发起请求。负载均衡完全在服务端处理。

在这里插入图片描述

使用Server-side调用有以下几个优势:
1.请求简单
请求会很简单,因为微服务调用一个已知的终端。
2.容易测试
使用服务代理将负载均衡或路由逻辑从微服务中剥离,这样可以使用Mocked代理测试服务的所有功能。

然而,这种方式也存在缺陷

1.路由跳转过多
新增的服务代理,增加了网络请求的次数。这方式比客户端方案需要调用的次数更多。而用代理服务次缓存请求是没有价值的,很多情景,请求会走1->4->5->6

客户端(Client side)

在这里插入图片描述

微服务之间的调用也可以直接使用客户端调用。服务注册返回微服务一个或多个实例的地址;然后,由客户端向该地址发出请求。微服务的地址通常会被缓存起来,这样在后续的调用中可以直接访问实际的地址,而不需要向注册服务查询。如果直接访问实际地址失败,客户端将重复第一次操作,向注册服务获取信息。最好对服务地址的缓存设置超时,这样当新版的服务部署后,其他服务不会访问缓存中错误的地址,而访问新的实例。

发起这些请求,以及负载均衡可以使用以下两种方式实现:
1.客户端库(Client library)
2.边车(sidecar)

在这里插入图片描述

两种方式都可以在客户端发起请求。然而,客户端库与微服务是一个整体,一起运行的;而边车(sidecar)是与微服务部署在一起的,可以运行在独立的进程。

client library
客户端库的方式很有效,将与其他远程资源通信的逻辑独立开。对于服务注册中心,client libraris可以是 Consul 或 Netflix Eureka 用于处理服务注册和心跳检测。其他的库,例如Netflix Ribbon,提供客户端的负载均衡。

一般而言,选用一个现有的库而不是自己写。如果所有的微服务使用Java编写,那边我们需要标准化这个库。如果我们有一个微服务系统,最好每个微服务使用相同的库进行请求调用,这样开发者从一个服务向另一个服务过渡不会增加基础设施和构建进程的复杂性。

这种方式的弊端是,我们将复杂的服务调用融入到了服务中,这样测试服务会变得很复杂,需要很好的区分使用了client library的代码和业务逻辑代码。

sidecar
另个比较好的方案是使用边车模式,边车是一个与微服务部署在一起的分离进程,或者一个分离的容器进程,或相关联的分离的容器。

边车调用服务注册中心获取服务注册信息,并保存这些信息,也具有客户端的负载均衡能力,来调用其他服务。

由于边车运行在自己的进程中,他可以使用独立的语言开发。在所有微服务中可以使用相同边车实现,而不需要管微服务使用何种语言。

Netflix Prana是一个开源的边车组件用于提供Ribbon和Eureka客户端的能力。

Kubernates是一个容器编排引擎,提供服务发现和负载均衡能力的sidecar。

API网关

API 网关(API Gateway)能够执行内部或外部客户端的服务的调用。API Gateway与服务代理的角色很像。服务向API网关发送请求,而服务网关向服务注册中心获取服务地址,然后根据地址发起请求,将请求后的结果返回给调用者。与代理服务器不同的是,API网关可以提供不同与原微服务提供的API。

内部的微服务可以使用确切的APIs,同时API网关提供外部客户端调用。一般来说,微服务提供细粒度的APIs,而外部客户端通常不需要那么细粒度的API,这时API网关可以屏蔽内部一些API,向外部客户端提供有用的API。所有的外部客户端通过API网关访问应用。

猜你喜欢

转载自blog.csdn.net/gdp12315/article/details/89604997