作者 | 李志信  于雨
来源|阿里巴巴云原生公众号

自从 2011 年 Dubbo 开源之后,被大量中小公司采用,一直是国内最受欢迎的 RPC 框架。2014 年,由于阿里内部组织架构调整,Dubbo 暂停维护了一段时间,之后随着 Spring Cloud 的面世,两个体系在融合中一起助推了微服务的火热。

不过这世界变化快,自从以 docker 为代表的的容器技术和以 K8s 为代表的容器编排技术登上舞台之后,云原生时代到来了。在云原生时代,不可变的基础设施给原有的中间件带来了不可变的中间件基础设施:gRPC 统一了底层通信层;protobuf 统一了序列化协议;以 envoy + istio 为代表的 service mesh 逐渐统一了服务的控制面与数据面。

dubbogo 的天然使命是:Bridging the gap between Java and Go。保持 Go 应用与 Java 应用互联互通的同时,借助 Go 语言(事实上的第一云原生语言)的优势拥抱云原生时代。dubbogo 社区 2020 年勠力打造三支箭:

  • 已经发布的对齐 dubbo 2.7 的 dubbogo v1.5 版本;
  • 近期将要发布的 sidecar 形态的 dubbo-go-proxy 项目;
  • 以及处于进行时的 dubbogo 3.0。

用一句话概括 dubbogo 3.0 即是:新通信协议、新序列化协议、新应用注册模型以及新的服务治理能力!本文主要着重讨论 dubbogo 3.0 的新通信协议和应用级服务注册发现模型。

dubbogo 3.0 vs gRPC

知己知彼,方能进步。dubbogo 3.0 的通信层改进主要借鉴了 gRPC。

gRPC 协议,简单来说就是 http2 协议的基础之上,增加了特定的协议 header:“grpc-” 开头的 header 字段,采用特定的打解包工具(protobuf)对数据进行序列化,从而实现 RPC 调用。

众所周知,gRPC 几乎没有服务治理能力,而阿里云现有 dubbo 框架兼具 RPC 和服务治理能力,整体实力不逊于 gRPC。但在“大家都用 gRPC” 这样的背景之下,dubbogo 3.0 的新通信协议就必须完美兼容 gRPC,对开发者已部署的服务完全兼容,并在此基础之上延续已有 dubbo 协议和服务治理能力,进而推出一系列新策略:比如 mesh 支持、应用级服务注册等。

dubbogo 3.0 vs dubbogo 1.5

目前已有的 dubbo 2.7 协议已经尽可能实现了 gRPC 的支持。开发者可以通过 protoc-gen-dubbo 工具将 pb IDL 协议转换为框架支持的 stub,再借助底层 gRPC conn 的 RPC 过程,将已有的服务治理能力自上而下传递给 gRPC,因此实现了 gRPC 服务的支持。

dubbo-go v1.5.x 也支持 gRPC 的 Stream 调用。和 unary RPC 类似,通过产生框架支持的 stub,在底层 gRPC stream 调用的基础之上,将流式 RPC 的能力和并入框架。但由于 dubbo v2.7.x / dubbo-go v1.5.x 本身并不支持流式调用,所以没有对 gRPC stream 调用的进行上层服务治理支持。

开发者所面临的问题就是:我们在使用 dubbo-go2.7 进行 grpc 协议传输的时候,或多或少不是那么放心。

而即将推出的 dubbo-go 3.0 协议将从根源解决这个问题。

协议兼容的三种层次

笔者认为,一款服务框架对于第三方协议的支持可分为三个程度:应用层次、协议层次、传输层次。

一款框架如果在一个协议的 sdk 之上封装接口,可以认为它处于应用层次支持,这样的框架需要遵循下层 sdk 的接口,可扩展性较差。

处于协议层次的框架,从配置层到服务治理层均由本框架提供,而在此之下的协议层到网络传输层均使用某个固定的通信协议,这样的框架可以解决服务治理的问题,但框架本身无法与第三方协议完全适配,如果不适配就会出现对第三方协议支持的削弱,比如上面说到的 dubbo-go 1.5 对 stream rpc 支持的缺陷。

如果想进一步支持更多的第三方协议,需要从传输层下手,真正了解第三方协议的具体字段、所依赖的底层协议(比如 HTTP2)的帧模型和数据流,再开发出与第三方协议完全一致的数据交互模块,作为本框架的底层。这样做的好处是最大程度赋予了协议的可扩展性,可以在兼容已有协议的基础之上,可选地增加开发者需要的字段,从而实现已有协议无法实现的功能,就比如 dubbogo 3.0 将支持的反压策略。

基于 HTTP2 的通信流程

gRPC 一次基于 HTTP2 的 unary rpc 调用传输主要流程如下:

  • client 发送 Magic 信息:
    PRI * HTTP/2.0rnrnSMrnrn;
  • server 收到并检查是否正确;
  • client 和 server 互相发送 setting 帧,收到后发送 ACK 确认;
  • client 发送 Header 帧,包含 gRPC 协议字段,以 End Headers 作为 Header 结束标志;
  • client 紧接着发送 Data 帧,包含 RPC 调用的 request 信息,以 End Stream 作为 Data 结束标志;
  • server 调用函数获得结果;
  • server 发送 Header 帧,包含 gRPC 协议字段,以 End Headers 作为 Header 结束标志;
  • server 紧接着发送 Data 帧,包含 RPC 调用回传的 response 信息;
  • server 紧接着再次发送 Header 帧,包含 RPC 状态和 message 信息,以 End Stream 作为本次 RPC 调用结束标志。

其中包含 gRPC 调用信息的 HTTP2 Header 帧如下图:

另外,在 gRPC 的 stream 调用中,可在 server 端回传的过程中发送多次 Data,调用结束后再发送 Header 终止 RPC 过程,并汇报状态信息。

dubbogo 3.0 的通信层将在 HTTP2 通信协议之上采用同样的通信流程,以保证与 gRPC 的底层通信沟通能力。

dubbogo 3.0 预期通信架构

除了通信协议采用 HTTP2 外,dubbogo 3.0 将采用基于 google protobuf 的 triple 协议【下面称为 dubbo3 协议】作为 dubbogo 3.0 的序列化协议,为 dubbo 将来支持更多的编程语言打下通信协议层面的基础。

目前设计的 dubbogo 3.0 传输模型如下:

  • 为保证同时支持 unary RPC 和 stream RPC,在 server 端和 client 端增加数据流结构,以异步调用的形式完成数据传递;
  • 继续支持原有的 TCP 通信能力;
  • 在 HTTP2 的通信协议之上支持 dubbo3 协议,decode 过程兼容 gRPC 使用的 protobuf,保证与 gRPC 服务打通。

应用级服务注册发现

1. 应用级服务注册发现介绍

dubbogo 3.0 使用的新一代服务注册发现体系,将摒弃旧版的“接口级注册发现”,使用“应用级别注册发现”。

简单地说,接口级别注册发现,在注册中心中以 RPC 服务为 key,以实例列表作为 value 来组织数据的,而我们新引入的“应用粒度的服务发现”,它以应用名(Application)作为 key,以这个应用部署的一组实例(Instance)列表作为 value。这带来两点不同:

  • 数据映射关系变了,从 RPC Service -> Instance 变为 Application -> Instance;
  • 数据变少了,注册中心没有了 RPC Service 及其相关配置信息。

可以认为,基于应用粒度的模型所存储和推送的数据量是和应用、实例数成正比的,只有当我们的应用数增多或应用的实例数增长时,地址推送压力才会上涨。

而对于基于接口粒度的模型,数据量是和接口数量正相关的,鉴于一个应用通常发布多个接口的现状,其数量级一般是比应用粒度的数十倍。另外一个关键点在于,接口的定义更多的是业务侧的内部行为,接口粒度导致的集群规模评估的不透明,而实例、应用增长都通常是在运维侧的规划之中,可控性较好。

工商银行曾经对这两个模型进行生产测算:应用级服务注册模型可以让注册中心上的数据量变成原来的 1.68%,新模型可以让 zookeeper 轻松至成 10 万级别的服务量和 10 万级别的节点量。

2. 元数据中心同步机制的引入

数据中心的数据量变少所造成的结果,是 RPC 服务相关的数据在注册中心消失了,只有 application - instance  这两个层级的数据。为了保证这部分缺少的 RPC 服务数据仍然能被 Consumer 端正确的感知,我们在 Consumer 和 Provider  间建立了一条单独的通信通道,目前针对元数据同步有两种具体的可选方案,分别是:

  • 内建 MetadataService;
  • 独立的元数据中心,通过中细化的元数据集群协调数据。

3. 兼容旧版本 dubbo-go

为了使整个开发流程对老的 dubbo-go 用户更透明,同时避免指定 provider 对可扩展性带来的影响),我们设计了一套 RPC服务到应用名的映射关系,以尝试在 consumer 自动完成 RPC 服务到 provider 应用名的转换。

这套设计可以让 dubbogo 3.0 中同时保持对 dubbo v2.6.x、dubbo v2.7.x 和 dubbo v3.0.x 三个大版的互联互通。

统一路由的支持

路由在概念上可以理解为从已有的所有 IP 地址列表中,根据特定的路由规则,挑选出需要的 ip 地址子集。路由的过程需要根据配置好的路由规则进行筛选,最终取所有路由规则的交集获得结果。多个路由如同流水线一样,形成一条路由链,从所有的地址表中筛选出最终目的地址集合,再通过负载均衡策略选择访问的地址。

1. 路由链

可以把路由链的逻辑简单理解为 target = rn(...r3(r2(r1(src))))。对于每一个 router 内部的逻辑,可以抽象为输入地址 addrs-in 与 router 中按全量地址 addrs-all 实现切分好的 n 个互不相交的地址池 addrs-pool-1 ... addrs-pool-n 按实现定义好的规则取交集作为输出地址。以此类推,完成整个路由链的计算。

2. failover

在路由规则配置文件中可以配置 failover 字段。在寻找地址失败时可以 failover, 选择其他 subset,并且顺序执行下来,直到找到地址,否则最后报地址找不到异常。

3. 兜底路由

在的路由规则配置中,可以配置一个没有任何条件的 match, 最终的结果是至少会有一个 subset 被选到,以达到地址空保护的作用。

作为 2020 年 dubbogo 社区打造并将在 2021 年初亮出的的三支箭之一,dubbogo 3.0 将带来不同平常且焕然一新的开发体验,敬请广大开发者期待!

如果你有任何疑问,欢迎钉钉搜索群号加入交流群:钉钉群号 31363295。

dubbogo 3.0 目前是社区和 dubbo 官方团队-- 阿里中间件团队共同合作开发。

阿里云-中间件团队招募对 dubbo3 (java & go)、dapr、arthas 有兴趣的开发者。可以钉钉联系 northlatitude,或者发送邮件至 beiwei.ly@alibaba-inc.com。

作者简介

李志信 (GitHubID LaurenceLiZhixin),阿里云云原生中间件团队开发工程师,dubbogo 社区开发者,中山大学软件工程专业在校学生,擅长使用 Go 语言,专注于云原生和微服务等技术方向。

于雨(github @AlexStocks),dubbo-go 项目和社区负责人,一个有十多年服务端做着基础架构研发一线工作经验的程序员,陆续参与改进过 Muduo/Pika/Dubbo/Sentinel-go 等知名项目,目前在蚂蚁金服可信原生部从事容器编排和 service mesh 工作。

原文链接
本文为阿里云原创内容,未经允许不得转载。

dubbogo 3.0:牵手 gRPC 走向云原生时代的更多相关文章

  1. 进击的 Java ,云原生时代的蜕变

    作者| 易立 阿里云资深技术专家 导读:云原生时代的来临,与Java 开发者到底有什么联系?有人说,云原生压根不是为了 Java 存在的.然而,本文的作者却认为云原生时代,Java 依然可以胜任&qu ...

  2. 进击的.NET 在云原生时代的蜕变

    你一定看过这篇文章 <进击的 Java ,云原生时代的蜕变>,  本篇文章的灵感来自于这篇文章.明天就将正式发布.NET Core 3.0, 所以写下这篇文章让大家全面认识.NET Cor ...

  3. [转帖]从 SOA 到微服务,企业分布式应用架构在云原生时代如何重塑?

    从 SOA 到微服务,企业分布式应用架构在云原生时代如何重塑? 2019-10-08 10:26:28 阿里云云栖社区 阅读数 54   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权 ...

  4. .NET 在云原生时代的蜕变,让我在云时代脱颖而出

    .NET 生态系统是一个不断变化的生态圈,我相信它正在朝着一个伟大的方向发展.有了开源和跨平台这两个关键优先事项,我们就可以放心了.云原生对应用运行时的不同需求,说明一个.NET Core 在云原生时 ...

  5. 【转】.NET 在云原生时代的蜕变,让我在云时代脱颖而出

    原创:张善友 原文:https://www.cnblogs.com/shanyou/p/12198741.html .NET 生态系统是一个不断变化的生态圈,我相信它正在朝着一个伟大的方向发展.有了开 ...

  6. 云原生时代 给予.NET的机会

    .NET诞生于与Java的竞争,微软当年被罚款20亿美元. Java绝不仅仅是一种语言,它是COM的替代者! 而COM恰恰是Windows的编程模型.而Java编程很多时候比C++编程要容易的多,更致 ...

  7. 云原生时代,Java的危与机(周志明)

    说明 本篇文章是转载自周志明老师的文章,链接地址:https://www.infoq.cn/article/RQfWw2R2ZpYQiOlc1WBE 今天,25 岁的 Java 仍然是最具有统治力的编 ...

  8. 云原生时代的Java

    原文链接(作者:周志明):https://time.geekbang.org/column/article/321185 公开课链接:https://time.geekbang.org/opencou ...

  9. CODING —— 云原生时代的研发工具领跑者

    本文为 CODING 创始人兼 CEO 张海龙在腾讯云 CIF 工程效能峰会上所做的分享. 文末可前往峰会官网,观看回放并下载 PPT. 大家上午好,很高兴能有机会与大家分享 CODING 最近的一些 ...

  10. 🏆【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究

    GraalVM 背景 新.旧编程语言的兴起躁动,说明必然有其需求动力所在,譬如互联网之于JavaScript.人工智能之于Python,微服务风潮之于Golang等等.大家都清楚不太可能有哪门语言能在 ...

随机推荐

  1. [置顶] tomcat处理请求导致页面出现ERR_CONNECTION_RESET错误解决方案

    现象: 浏览器发送请求到servlet,servlet处理时间太久,所以导致chrome浏览器出现ERR_CONNECTION_RESET错误 解决方案: 在相应servlet执行最后添加一句代码: ...

  2. tomcat报错Exception loading sessions from persistent storage解决方案

    现象:项目在重启时报错:严重: Exception loading sessions from persistent storage的问题.该问题的原因是tomcat的session持久化机制引起的, ...

  3. ubuntu切换root到user

    目前知道: 从root用户切回user用户有三种方法: 1.su user (user是你自己安装时候的用户名) 2.直接输入exit 3.ctrl+D组合键

  4. [原创] KCP 源码分析(上)

    KCP 协议是一种可靠的传输协议,对比 TCP 取消了累计确认(延迟 ACK).减小 RTO增长速度.选择性重传而非全部重传.通过用流量换取低时延. KCP 中最重要的两个数据结构IKCPCB和IKC ...

  5. demo介绍:uni-app统合--各类大转盘demo介绍

    这里给大家介绍下我做的一个uni-app的demo:抽奖系统 废话不多说直接上效果图: 线上案例: 首页: 大转盘抽奖页面: 轮播机抽奖页面: 九宫格抽奖页面: 翻牌抽奖页面: 奖品列表页面: 抽奖的 ...

  6. 借助Numpy,优化Pandas的条件检索代码

    Numpy其实是最早的处理数据的Python库,它的核心ndarray对象,是一个高效的n维数组结构. 通过这个库,可以高效的完成向量和矩阵运算,由于其出色的性能,很多其他的数据分析,科学计算或者机器 ...

  7. kali2.0 metasploit安装

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_40943540/arti ...

  8. 开发必会系列:《深入理解JVM(第二版)》读书笔记

    一  开始前 HotSpot:http://xiaomogui.iteye.com/blog/857821 http://blog.csdn.net/u011521890/article/detail ...

  9. C# 调用C++DLL时释放非托管内存

    方法一 改变非托管内存的分配方法,将其修改成采用COM的内存分配方法CoTaskMemAlloc来分配内存.这样封送拆收器在释放非托管内存时,就能自动调用COM的内存释放方法CoTaskMemFree ...

  10. Oracle ORA-09925

    Error : 30: Read-only file system 造成这个问题的原因大多数是因为非正常关机后导致文件系统受损引起的,在系统重启之后,受损分区就会被Linux自动挂载为只读. 解决办法 ...