在所有的服务治理框架中,服务注册与发现都是其中核心功能,在之前文章中也提到过,Dubbo-go 也是一样。所以,接下来,首先需要了解什么是服务发现。
什么是服务发现
在开发一个单体系统时,方法与方法的调用,是通过本地栈帧完成。但是在开发一个大型分布式系统时,方法与方法间的调用很可能变为服务与服务间的远程调用。在远程调用的过程中,调用端(下称:Consumer)需要知道关于远程服务(下称:Provider)的一些信息才可以发起调用,例如:Provider的网络地址(IP地址和端口)。运行在物理硬件上的传统应用中,Provider 的网络地址是相对静态,可以从一个配置文件中获取 Provider 的网络地址,进行访问。Provider 集群架构,可以从一个配置文件中获取 Provider 的域名,进行访问。而基于云原生的微服务架构,该问题会变得复杂,因为在云原生的环境里,IP 可能会动态变更,通常会在应用更新(实际上是容器重启)、扩缩容、Provider 配置变化等时机,而这些则是服务发现机制需要解决的问题。
所以,一套完善的服务发现机制就成为了在云原生微服务架构里面重要的机制之一。
在了解 Dubbo-go 如何实现服务发现机制之前,首先要了解,业界常用服务发现的机制有什么模式?主要会有以下两种模式:服务端发现模式(server-side discovery)与客户端发现模式(client-side discovery)。接下来,先分析的是:服务端服务发现。
服务端发现模式
图 1
客户端通过负载均衡器向一个服务发送请求,这个负载均衡器会查询服务注册表,并将请求路由到可用的服务实例上。通过客户端的服务发现,服务实例在服务注册表上被注册和注销。
服务器端服务发现模式也是优势和缺陷并存。最大的好处在于服务发现的细节被从客户端中抽象出来,客户端只需要向负载均衡器发送请求,不需要为服务客户端使用的每一种语言和框架,实现服务发现逻辑;另外,这种模式也有一些问题,即使这个负载均衡器是由部署环境提供的,也是另一个需要启动和管理的可用的系统组件,会提高运维成本。
客户端发现模式
图 2
当使用客户端服务发现的时候,客户端负责决定可用的服务实例的网络地址,以及围绕他们的负载均衡。客户端向服务注册表(service registry)发送一个请求,服务注册表是一个可用服务实例的数据库。客户端使用一个负载均衡算法,去选择一个可用的服务实例,来响应这个请求,如图 2。
客户端的服务发现模式有优势也有缺点。这种模式相对直接,但是除了服务注册表,没有其它动态的部分了。而且,由于客户端知道可用的服务实例,可以做到相对智能的,应用明确的负载均衡决策。比如一直用 hash 算法。这种模式的一个重大缺陷在于,客户端和服务注册表是一一对应的,必须为服务客户端用到的每一种编程语言和框架实现客户端服务发现逻辑。
相信大家已经对服务发现的模式有一定的了解,而 Dubbo-go 采取的是更容易适应云原生环境的客户端发现模式。那服务注册进行应用级注册改造之后,服务发现是否需要做改造呢?答案是肯定需要,对于服务发现来说,只需要新增一个模型支持。接下来的应用级发现模型实现分析,带你了解如何使用应用级的注册信息,调用相关方法。
应用级服务发现是什么?
在了解应用级服务发现模型是什么之前,应该先了解为什么需要新的模型。在 Dubbo-go 1.4 时,使用的是以服务(接口)为维度往注册中心注册信息的服务级别注册模型(见样例1)。
`"com.xxx.User":[`
`{"name":"instance1", "ip":"127.0.0.1", "metadata":{"timeout":1000}},`
`{"name":"instance2", "ip":"127.0.0.2", "metadata":{"timeout":2000}},`
`{"name":"instance3", "ip":"127.0.0.3", "metadata":{"timeout":3000}}`
`]`
样例 1 - 服务级注册模型
但服务注册模型会存在以下几个问题:
-
与 Spring Cloud、k8s 的注册模型不一样,他们使用应用 - IP 的形式作为注册模型。
-
在集群庞大的情况下,每次上下线往注册中心写入的数据过多。
而应用级服务发现的出现,则是针对这两个问题作出的解决方案,通过分离出元数据中心、注册中心只支持 IP+ port 应用级信息,结合元数据中心,达到 Dubbo-go 与 Sping Cloud、k8s 兼容目的。除此之外,保证将来的云原生模式是:微服务和云原生共存。
那可能大家会觉得奇怪,原来 Dubbo 协议是只支持服务级别服务发现,是怎么改造成支持应用级服务发现?除此之外,可能还会存在以下问题:
-
支持了应用级服务发现之后,又如何得知使用哪一种注册中心?
-
原来在服务级发现模型中,包含的方法名、方法参数等附加信息放在哪?
-
应用信息与附加信息在什么时候关联?
这几个问题,贯穿于应用级服务发现整个启动流程,只要理解了这几个问题的解决方案,即明白整个应用级服务发现功能核心实现。
图 3
前文也提到过应用级服务发现虽然作为一种新的模型,与旧的模型肯定存在差异,差异主要体现在:
-
注册中心数据主要以“应用名-实例列表”存储,除此之外还包含一部分应用元数据信息,而服务元数据信息另外存放(见图 3)。
-
服务元数据信息自行协商。
通过差异能看出来,最关键的点就在于如何获取到服务元数据信息。所以本质上来说,如何使用应用级的注册信息,就是 Consumer 如何正确获取并使用服务元数据信息并组织成对应的 invoker,再发起调用(见图 3 红色部分)。接下来,则会以 Dubbo-go 如何实现元数据中心与实现应用级服务发现为核心,对进行更深入的分析。
关注公众号【部长技术之路】,在公众号后台回复关键字【dubbogo】加入社区。