作者 | 李志信 于雨
起源 | 阿里巴巴云原生公众号
自从 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 服务买通。
利用级服务注册发现
- 利用级服务注册发现介绍
dubbogo 3.0 应用的新一代服务注册发现体系,将摒弃旧版的“接口级注册发现”,应用“利用级别注册发现”。
简略地说,接口级别注册发现,在注册核心中以 RPC 服务为 key,以实例列表作为 value 来组织数据的,而咱们新引入的“利用粒度的服务发现”,它以利用名(Application)作为 key,以这个利用部署的一组实例(Instance)列表作为 value。这带来两点不同:
- 数据映射关系变了,从 RPC Service -> Instance 变为 Application -> Instance;
- 数据变少了,注册核心没有了 RPC Service 及其相干配置信息。
能够认为,基于利用粒度的模型所存储和推送的数据量是和利用、实例数成正比的,只有当咱们的利用数增多或利用的实例数增长时,地址推送压力才会上涨。
而对于基于接口粒度的模型,数据量是和接口数量正相干的,鉴于一个利用通常公布多个接口的现状,其数量级个别是比利用粒度的数十倍。另外一个关键点在于,接口的定义更多的是业务侧的外部行为,接口粒度导致的集群规模评估的不通明,而实例、利用增长都通常是在运维侧的布局之中,可控性较好。
工商银行已经对这两个模型进行生产测算:利用级服务注册模型能够让注册核心上的数据量变成原来的 1.68%,新模型能够让 zookeeper 轻松至成 10 万级别的服务量和 10 万级别的节点量。
- 元数据中心同步机制的引入
数据中心的数据质变少所造成的后果,是 RPC 服务相干的数据在注册核心隐没了,只有 application – instance 这两个层级的数据。为了保障这部分短少的 RPC 服务数据依然能被 Consumer 端正确的感知,咱们在 Consumer 和 Provider 间建设了一条独自的通信通道,目前针对元数据同步有两种具体的可选计划,别离是:
- 内建 MetadataService;
- 独立的元数据中心,通过中细化的元数据集群协调数据。
- 兼容旧版本 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 地址子集。路由的过程须要依据配置好的路由规定进行筛选,最终取所有路由规定的交加取得后果。多个路由如同流水线一样,造成一条路由链,从所有的地址表中筛选出最终目标地址汇合,再通过负载平衡策略抉择拜访的地址。
- 路由链
能够把路由链的逻辑简略了解为 target = rn(…r3(r2(r1(src))))。对于每一个 router 外部的逻辑,能够形象为输出地址 addrs-in 与 router 中按全量地址 addrs-all 实现切分好的 n 个 互不相交 的地址池 addrs-pool-1 … addrs-pool-n 按实现定义好的规定取交加作为输入地址。以此类推,实现整个路由链的计算。
- failover
在路由规定配置文件中能够配置 failover 字段。在寻找地址失败时能够 failover,抉择其余 subset,并且程序执行下来,直到找到地址,否则最初报地址找不到异样。
- 兜底路由
在的路由规定配置中,能够配置一个没有任何条件的 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 工作。
原文链接
本文为阿里云原创内容,未经容许不得转载。