Dubbo 如何成为链接异构微服务体系的最佳服务开发框架

从编程开发的角度来讲,Apache Dubbo (如下简称 Dubbo )首先是一款 RPC 服务框架,它最大的优点在于提供了面向接口代理的服务编程模型,对开发者屏蔽了底层的远程通讯细节。同时 Dubbo 也是一款服务治理框架,它为分布式部署的微服务提供了服务发现、流量调度等服务治理解决方案。apache

在这篇文章中,咱们将以以上基础能力为背景,尝试突破 Dubbo 体系自身,探索如何利用 Dubbo 对多协议、多服务发现模型的支持,来实现异构微服务体系间的互联互通。在实际业务场景中,这能够用来解决异构技术体系共存场景下的通讯问题,帮助公司实如今异构技术体系间做平滑迁移,解决大规模跨区域、多集群部署场景的地址发现及流量调度等问题。编程

面向接口代理的透明服务开发框架

咱们仍是从 Dubbo 是一个微服务开发框架 这个你们熟知的概念开始。就像 Spring 是开发 Java 应用的基础框架同样,咱们常常会选用 Dubbo 做为开发微服务业的基础框架。 Dubbo 框架的最大优点我认为就在其面向接口的编程模型,使得开发远程服务调用就像开发本地服务同样(以 Java 语言为例):api

  1. 服务定义
public interface GreetingsService {
    String sayHi(String name);
}

  1. 消费方调用服务
// 和调用本地服务同样,彻底透明。
@Reference
private GreetingService greetingService;

public void doSayHello(String name) {
  greetingService.sayHi("Hello world!");
}

下图是 Dubbo 的基本工做原理图,服务提供者与服务消费者之间经过注册中心协调地址,经过约定的协议实现数据交换。网络

1

同构/异构微服务体系面临的问题

关于 Dubbo 协议自己及其服务治理相关功能细节并非本文的重点,咱们今天将从一个更高的层次,来看看公司内部构建微服务体系所面的挑战,以及 Dubbo 能为架构选型和迁移等提供哪些解决思路。架构

一个公司内部的微服务可能都是基于某一个相同的服务框架开发的,好比说 Dubbo,对于这样的架构,咱们称之为是同构的微服务体系;而有些公司的微服务多是使用多个不一样的服务框架所建设,咱们称之为异构的微服务体系,多个不一样技术栈微服务体系的共存在大型组织内仍是很是广泛的,形成这种局面可能有不少缘由。好比,多是遗留系统带来的,也多是公司正在作技术栈迁移,或者就是不一样业务部门为了知足各自特殊需求而作的独立选型(这也意味着异构微服务体系的长期共存)。负载均衡

1. 异构微服务体系共存框架

咱们很容易想到的一个挑战是:不一样的体系间一般是使用不一样的 RPC 通讯协议、部署独立的注册中心集群,面对这种多协议、多注册中心集群的场景,要如何实现相互之间透明的地址发现和透明的 RPC 调用?若是咱们什么都不作,那么每一个微服务体系就只能感知到本身体系内的服务状态,流量也在各自的体系内封闭。而要作到从体系 A 平滑的迁移到体系 B,或者想长期的保持公司内部多个体系的共存,则解决不一样体系间的互联互通,实现流量的透明调度将是很是重要的环节。分布式

2

2. Dubbo 体系内部微服务

多协议、多注册中心集群的问题在同构的微服务体系中也可能存在,尤为是当一个组织内部的微服务规模增加到必定量级的时候。性能

  • 咱们可能要在不一样的服务之间采用不一样的通讯协议,由于不一样的服务面临不一样的业务场景,而这也进一步致使了数据传输特色的不一样,咱们须要分别采用更适合各种业务特色的协议。好比典型的场景:咱们可能对于普通的业务服务采用 Dubbo 协议,对于和 FrontEnd 交互的服务须要 HTTP 协议,而对于须要流式数据传输的业务则采用 gRPC 协议等等。
  • Dubbo 体系内部另外一个常出现的问题是,在大规模分布式部署的场景下,微服务系统会作跨区域、跨注册中心的部署,这个时候就会出现多集群间地址同步和流量调度的问题。

总结起来,不管是同构体系仍是异构体系,都面临对多协议通讯、多注册中心集群地址发现的问题。Dubbo 目前是支持多协议、多注册中心的,能够说就是为解决咱们上面分析的 Dubbo 同构体系内的场景而设计的,所以下面咱们从同构体系的多协议、多注册中心场景讲起,先了解 Dubbo 多协议、多注册中心的基本支持状况以及它们是如何工做的。而在后面的一章再进一步探索怎么扩展这个能力来支持异构微服务体系的互联互通。

Dubbo 体系内的多协议、多注册中心机制

咱们将经过两个场景示例,来分别具体的讲一下 Dubbo 的多协议、多注册中心机制的使用方式和工做原理。

多协议

3

以上是使用 Dubbo 开发的一套微服务,服务间通讯使用到了不一样的协议,根据咱们的调研发现,公司内部启用多协议实际上是很是广泛需求,具体场景在此咱们暂不作解释。

应用 B 做为服务提供者,发布了 5 个服务,其中:

  • DemoService1 DemoService2 经过 dubbo 协议发布
  • DemoService3 DemoService4 经过 gRPC 协议发布
  • DemoService0 经过 dubbo 、gRPC 双协议发布

应用 A 做为消费者,使用 dubbo 协议消费 DemoService1 DemoService2,使用 gRPC 协议消费 DemoService0

应用 B 做为消费者,使用 gRPC 协议消费 DemoService2 DemoService4,使用 dubbo 协议消费 DemoService0

如下是具体的代码配置:

  1. 提供端应用 B
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService1" protocol="dubbo"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService2" protocol="dubbo"/>

<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService3" protocol="grpc"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService4" protocol="grpc"/>

<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService0" protocol="dubbo, grpc"/>

  1. 消费端应用 A
<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService1"/>
<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService2"/>

<dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService0"/>

  1. 消费端应用 C
<dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService3"/>                                                                                     <dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService4"/>

<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService0"/>

Dubbo 多协议支持现状

Dubbo 目前所支持的协议包括 Dubbo、REST、Thrift、gRPC、JsonRPC、Hessian 等,基本涵盖了业界大多数主流的 RPC 通讯协议。须要注意的是,这些协议的支持都是以直接集成官方 Release 实现的形式来作的,我认为这是一个很好的选择,既保证了协议解析自身的稳定性,又能使 Dubbo 社区更专一的将更多的精力放在 Dubbo 外围服务治理能力的改善上。试想若是 Dubbo 社区本身为每一个协议提供实现,那是要花费多少精力和时间才能使每种协议达到稳定的生产可用。

除了以上官方提供支持的协议以外,得益于 Dubbo 灵活的扩展机制,想要为 Dubbo 扩展协议很是容易,开发者能够随时为 Dubbo 增长更多的协议支持,包括自有协议扩展。

关于对 gRPC (HTTP/2) 协议的支持,请参阅《Dubbo 在跨语言和协议穿透性方向的探索:支持 HTTP/2 gRPC》

4

多协议能解决的问题

  • 将 RPC 框架无缝地接入 Dubbo 的服务治理体系。

经过协议扩展将 RPC 协议归入 Dubbo 服务开发体系,从而复用 Dubbo 的编程模型和服务发现、流量管控等能力。好比 gRPC,其服务治理体系相对比较弱、编程 API 不够友好,很难直接用于微服务开发。

  • 知足不一样场景的调用需求。

各个服务多是为了知足不一样业务需求而开发,同时外围消费端应用的技术栈也可能多种多样,经过启用不一样的通讯协议,能够最优化不一样场景的通讯需求。

  • 实现协议间的迁移。

经过支持多种协议,借助注册中心的协调,能够快速知足公司内协议迁移的需求。如从自有协议升级到 Dubbo 协议,Dubbo 协议自身升级,从 Dubbo 协议迁移到 gRPC,从 REST 迁移到 Dubbo 协议等。

多注册中心

当服务集群规模小的时候,一个中心化的集群部署方案能很好的解决咱们的业务问题。可是随着应用规模的增加、用户流量的增长,咱们就不得不考虑要为业务系统引入跨区域、多集群的部署方案,而此时同业务系统密切相关的注册中心集群也面临部署方案的选型:

  1. 继续维持全局共享的注册中心集群。这种架构方案的优势是简单;缺点是注册中心集群因为要保存全量的地址数据,存储和推送压力会变得很大,另外对于一些注册中心产品(如 Zookeeper 等)在跨集群网络部署的场景下稳定性和性能可能都会面临挑战。
  2. 每一个业务集群部署独立的注册中心集群。多注册中心集群的优势是能解决跨集群网络可用性的问题,同时也可以减轻注册中心的存储和推送压力;缺点则是要求服务框架(如 Dubbo 等)能有同时发布/监听多个注册中心集群的能力。

下面咱们具体看一下,Dubbo 为多注册中心集群场景提供的解决方案。

5

上图有两个业务集群,分别部署在北京和上海,每一个业务集群有本身独立的注册中心集群,要解决两个业务集群间服务的透明 RPC 通讯问题。

  1. 服务提供端,双注册中心发布
<dubbo:registry id="beijingRegistry" address="zookeeper://${zookeeper.address1}" default="false"/>                                                                           <dubbo:registry id="shanghaiRegistry" address="zookeeper://${zookeeper.address2}" />
                                                                                          
<dubbo:service interface="org.apache.dubbo.samples.multi.registry.api.HelloService" ref="helloService" registry="shanghaiRegistry,beijingRegistry"/>
<dubbo:service interface="org.apache.dubbo.samples.multi.registry.api.DemoService" ref="demoService" registry="shanghaiRegistry,beijingRegistry"/>

  1. 服务消费端,根据消费需求作单/双注册中心订阅
<dubbo:registry id="beijingRegistry" address="zookeeper://${zookeeper.address1}" default="false" preferred="true" weight="100"/>                                                                                         <dubbo:registry id="shanghaiRegistry" address="zookeeper://${zookeeper.address2}" default="true" weight="20"/>

<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.DemoService"/>

<dubbo:reference  interface="org.apache.dubbo.samples.multi.registry.api.DemoService" registry="beijingRegistry, shanghaiRegistry"/>

<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.HelloService" registry="beijingRegistry"/>

<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.HelloService" registry="shanghaiRegistry,shanghaiRegistry"/>

Dubbo 对异构注册中心集群的支持

虽然咱们会作多注册中心集群部署,但一般状况下,咱们部署的都是相同的注册中心产品,如都是 Zookeeper、Nacos;而对于注册中心迁移的场景,则要求 Dubbo 能提供对更多的注册中心产品的支持,或者最重要的要有很好的扩展能力。Dubbo 官方目前支持的注册中心实现有:

6

这里须要特别提到的一点是,当前 Dubbo 的服务注册/发现模型是以接口为粒度的,而从 2.7.5 版本开始,Dubbo 新引入了应用粒度的服务注册/发现模型。这一方面有助于优化 Dubbo 当前服务发现机制、提高服务容量,另外一方面对于联通以 SpringCloud 为表明的微服务体系也很是重要(关于这点在下一章中有进一步说起)。更多关于《应用粒度服务发现:服务自省》的介绍,咱们将在接下来的文章或文档中予以补充,请持续关注。

多订阅带来的流量调度问题

在引入多注册中心集群后,Dubbo 在流量选址时的多了一层注册中心集群间的负载均衡:

7

在 Cluster Invoker 这一级,咱们支持的选址策略有(2.7.5+ 版本,具体使用请参见文档):

  • 指定优先级

    <!-- 来自 preferred=“true” 注册中心的地址将被优先选择,只有该中心无可用地址时才 Fallback 到其余注册中心 -->
    <dubbo:registry address="zookeeper://${zookeeper.address1}" preferred="true" />

  • 同 zone 优先

    <!-- 选址时会和流量中的 zone key 作匹配,流量会优先派发到相同 zone 的地址 -->
    <dubbo:registry address="zookeeper://${zookeeper.address1}" zone="beijing" />

  • 权重轮询

    <!-- 来自北京和上海集群的地址,将以 10:1 的比例来分配流量 -->
    <dubbo:registry id="beijing" address="zookeeper://${zookeeper.address1}" weight=”100“ />
    <dubbo:registry id="shanghai" address="zookeeper://${zookeeper.address2}" weight=”10“ />

  • 默认,stick to 任意可用

多注册中心适用的场景

  • 同区域流量优先调度

出于容灾或者服务伸缩性需求,服务/应用每每须要部署在多个独立的机房/区域,在每一个区域有独立注册中心集群的场景下,实现同区域的流量优先调度就能很好的解决延迟和可用性问题。

  • 注册中心迁移

公司的服务一直以来多是存储在某一个注册中心,如 Zookeeper,但到了某个时间节点,由于各类各样的缘由,当咱们要迁移到另外的注册中心时,多注册中心模型可以保证平滑的迁移。

  • 异构系统互通

不一样微服务体系开发的服务,都封闭在各自的服务发现体系中,而经过统一的多注册中心模型,能够实现不一样体系的服务互相发现。

借助 Dubbo 联通异构的微服务体系

上文咱们提到了在组织内存在异构微服务体系的各类合理可能性,如今咱们来具体看一下异构微服务体系的实际场景,以及使用 Dubbo 实现互联互通的解决方法。首先咱们先经过一张图来看一下,联通异构的微服务体系具体是一个什么样的场景。

8

如上图所示,咱们有部分微服务能够是基于 SpringCloud、gRPC、K8S 或者是自建体系构建的,他们各自之间默认是相互隔离没法联通的。当咱们再构建一套基于 Dubbo 的微服务体系时,则利用 Dubbo 的多协议、多服务发现模型,咱们就能够作到和各个微服务体系间的两两之间的互联互通。进一步的,如图中橙色箭头所示,依赖 Dubbo 体系做为桥接层,咱们还能够实现两个异构微服务体系间的打通。

对于如下几个示例场景,因为在地址发现层面目前没有统一的标准,咱们暂且假设地址发现层面不一样的体系建是没有障碍的,咱们将重点关注迁移的基本流程以及通讯协议环节。(关于地址发现部分,咱们将在后续《服务自省:基于应用粒度的服务发现》以后再深刻探讨)

Dubbo 体系内的协议迁移(共存)

绝大多数开发者对 Dubbo 有这么一个固有认知:使用 Dubbo 开发微服务系统,则就要用 Dubbo 协议来做为服务间的通讯协议才是最优方案。实际上,咱们彻底没有必要只束缚在 Dubbo RPC 协议上。Dubbo 做为微服务开发框架和 Dubbo 做为 RPC 协议这是两个概念,实际上是彻底能够分开来看待的,好比咱们用 Dubbo 框架开发的业务系统,选用 rest、gRPC 通讯是彻底没有问题的(参加 Dubbo 支持的协议列表),具体用什么协议根据业务特色和技术规划才是最适合的。

9

当前在云原生、Mesh 的大背景下, HTTP1/二、gRPC 协议开始受到愈来愈多的关注,一方面缘由天然是由于它们在标准化方面作的更好,获得的更多的网络设备和基础设施的支持,具有更好的通用性和穿透性。对于不少有云原生迁移意愿的企业来讲,往此类协议迁移无疑将对以后的架构升级有更多的帮助。

下图演示了在 Dubbo 体系内,从 Dubbo 协议向 gRPC 协议迁移的一个中间状态。

10

  • 最左边的表明还没有迁移的老应用,这类应用在迁移过程当中仍然要消费和提供 Dubbo 协议的服务。
  • 中间的表明处于迁移中的应用,他们中间可能有些是服务提供者,既要为左边的老系统提供提供 Dubbo 协议服务;又要为右边的新系统提供 gRPC 服务;所以他们都是双协议暴露服务。
  • 最右边则表明是新开发的或者已经迁移完成的应用,这个体系内已能彻底用 gRPC 协议通讯。
  • 最终度过中间态后,咱们指望全部的应用都达到最左边应用的状态,实现彻底的 gRPC 协议通讯。

Spring Cloud 体系迁移到 Dubbo 体系(共存)

如前文所述,因为 SpringCloud 和 Dubbo 间服务发现模型的问题,要两个体系间的地址互通须要 Dubbo 侧做相应的适配,关于这部份内容将在接下来的 2.7.5 版本《服务自省》部分发布,在此咱们暂且认为已经打通。

11

Dubbo 体系内的部分应用做为透明的联通两个体系的关键节点,部分服务提供者应用要双协议发布、部分消费者应用要作到选定协议消费。因为老的 Spring Cloud 体系不容许作任何改动,所以联通两套体系的关键是 REST 协议,对 Dubbo 侧的应用来讲:

  • 部分应用可能要以 REST 协议消费 SpringCloud 的服务;
  • 部分应用可能要暴露 REST 协议共 SpringCloud 消费;
  • Dubbo 自有体系内则经过本身选定的协议通讯,这里就比较灵活了,能够是 Dubbo、REST、gRPC 等其中的任一种。而若是选定 REST 协议则对于与 SpringCloud 体系的联通就变得更加天然了,由于两端的协议都是统一的。

对于消费 Spring Cloud 服务的应用,要配置服务 :

<dubbo:reference interface ="xxx.SpringService" protocol="rest"/>

对于提供服务给 Spring Cloud 侧消费的应用,则指定服务暴露为 rest 协议,或者双协议暴露(因若是这个服务还要被新体系内的应用调用到):

<dubbo:service interface="xxx.NewService" protocol="rest,dubbo"/>

做为 Dubbo 的维护者,虽然咱们这里有明显的偏向性,讲的是从如何从 SpringCloud 体系迁移到 Dubbo 体系。可是反过来考虑,若是你已经或者即将选型 Dubbo 来开发微服务,则将来从 Dubbo 迁移到 SpringCloud 也是一样的思路,Dubbo 的多协议、多注册模型为双向迁移都提供了一样的灵活性。

原文连接

本文为阿里云内容,未经容许不得转载。

相关文章
相关标签/搜索