Dubbo-go 服务代理模型

简介:HSF 是阿里集团 RPC/服务治理 领域的标杆,Go 语言又因为其高并发,云原生的特性,拥有广阔的发展前景和实践场景,服务代理模型只是一种落地场景,除此之外,还有更多的应用场景值得我们在研发的过程中去探索和总结。

作者 | 李志信

背景

Dubbo-go 生态包括 Dubbo-go v3.0 、v1.5、pixiu 等子项目,在可扩展性上提供了灵活的定制化方式。

众所周知,HSF 是阿里集团 RPC/服务治理 领域的标杆框架。HSF-go 是 go 语言实现的 HSF 框架,由中间件团队维护,由于 Go 语言的特性,在跨语言调用场景,云原生组件集成服务代理场景扮演重要角色,目前拥有 Dapr Binding实现,并且在函数计算(FC)场景,跨云场景,脱云独立部署场景产生价值,并在钉钉、Lazada、高德等技术团队拥有落地场景。HSF-go 属于 Dubbo-go 生态体系内的一环,是开源项目 Dubbo-go 的定制化实现。

纵观 HSF-go 的一系列和服务代理相关的场景,我希望在这里分享一下其作为服务代理的实践与原理,欢迎和大家一起交流。

HSF-go 泛化调用模型

1、泛化调用

首先了解一下 Dubbo 的泛化调用,就是不依赖二方包的情况下,通过传入方法名,方法签名和参数值,就可以调用到下游服务。

而 Golang 的泛化调用和 Java 角度略有不同,这与语言特性有关。Go 不支持类继承和方法重载,并且没有二方包的概念。Java 的二方包可以抽象为一套由客户端和服务端约定好的接口信息,包含接口名、方法名、参数列表、具体参数定义,这些基础概念在任何 RPC 场景都是必须的,只是表现形式不同:对 Java 来说就是二方包,对 gRPC 来说就是 proto 文件以及编译产物,对兼容 Dubbo 协议的 Dubbo-go 来说,就是使用兼容 Java 版本的 Hessian 序列化接口。当然使用 Go 编写 Hessian 接口这种适配方式带来了一些困扰,就是让 Go 开发者写起来比较头疼的,对应Java 版本的  POJO 结构和接口存根。

下面是 Dubbo-go 生态习惯写法中,一个使用 Hessian 序列化,兼容 Java 的 Go 客户端例子。

// UserProvider 客户端存根类
type UserProvider struct {// dubbo标签,用于适配go侧客户端大写方法名 -> java侧小写方法名,只有 dubbo 协议客户端才需要使用GetUser  func(ctx context.Context, req int32) (*User, error) `dubbo:"getUser"` 
}func init(){// 注册客户端存根类到框架,实例化客户端接口指针 userProviderconfig.SetConsumerService(userProvider)
}// 字段需要与 Java 侧对应,首字母大写
type User struct {UserID   string UserFullName string  `hessian:"user_full_name"`UserAge  int32 // default convert to "userAge"Time time.Time
}func (u *User) JavaClassName() string {return "org.apache.dubbo.User" // 需要与 Java 侧 User 类名对应
}

Go 相比于支持方法重载的 Java,对接口的元数据信息依赖较弱,可以更轻松地定位目的方法从而发起调用。但本质上,还是需要上面所提到的 “约定好” 的接口信息,从而保证能正确命中下游方法,以及保证参数解析正确。

在泛化调用的情景下,在代码上不需要引入 “二方包”, 在增大了自由度的同时,失去了 “二方包” 接口的限制,因此客户端需要在泛化调用传递参数时尽可能小心,保证传递的参数完全和服务端提供的接口对应,从而正确调用。

泛化调用包含服务端泛化和客户端泛化调用。如果客户端泛化是把中间代理当做 consumer 端的反向代理,那么服务端泛化就是把中间代理当做服务 provider 端的正向代理,把请求转发到后端真正的服务提供方。服务端泛化,开发者在编写服务时,不需要声明具体的参数,框架将请求解析成通用的方法名和参数列表数组并传递至用户层,开发者编写的代码需要直接操作这些动态的数据,可参考文末的例子。而用的相对较多的是客户端泛化,即上面聊的,客户端在代码层面并没有拿到服务端提供的接口依赖,而是通过传入方法名和参数,由框架生成泛化调用请求,从而达到和通过真实接口调用一样的效果。

泛化调用请求往往方法名为 $invoke ,包含三个参数,分别是:

  • 真实方法名;
  • 参数名组成的数组;
  • 参数具体值组成的数组。

以一个 HSF-go 泛化调用请求为例:

// 一个 HSF-go 的客户端泛化调用
genericService.Invoke(context.TODO(), "getUser", []string{(&GoUser{}).JavaClassName(), (&GoUser{}).JavaClassName()}, []interface{}{&GoUser{Name: "laurence"}, &GoUser{Age: 22}})

框架接收到这三个参数后,会构造出泛化请求,发送至服务端。

服务端在接收到泛化请求时,会在一层 filter 中过滤出以 $invoke 为方法名的请求,并构造出真实请求结构,向上层传递,从而完成调用并返回。

以上是 Dubbo 体系泛化调用的通用实现,但如果单纯站在 Go 语言的角度来设计,并不需要传递参数列表类型,服务端可以单纯通过方法名定位到方法,再将参数数组反序列化,获得真实参数。

2、泛化调用与服务运维能力

泛化调用的应用场景很广泛,集团的开发人员接触最多的泛化调用,可能就是 MSE/HSF-ops 平台提供的服务测试能力。

集团内使用的 MSE 运维平台是一个强大的、用于 HSF 服务治理的平台,可以在平台上配置运维、服务治理能力、进行服务测试,以及商业化版本 MSE 的压测、流量回放等操作。而其提供的服务测试能力,依赖的就是 HSF 泛化调用。当开发人员在平台上针对一个接口方法发起测试时,会传入一个 json 参数列表,平台会将 json 参数列表转化为 hessian 对象并序列化,构造出上面提到的三参数,并向目的机器发起调用,拿到测试返回值。HSF 服务会默认支持泛化调用。

除了服务测试,还可以使用泛化调用来开发服务网关、服务探活、cli 服务测试工具等。

3、泛化调用与序列化协议的关系

常见的序列化协议很多,例如 Dubbo/HSF 默认的 hessian2 序列化;还有使用广泛的 JSON 序列化;以及 gRPC 原生支持的 protobuf(PB) 序列化等等。

提到的这三种典型的序列化方案作用类似,但在实现和开发中略有不同。PB 不可由序列化后的字节流直接生成内存对象,而Hessian和JSON都是可以的。后两者反序列化的过程不依赖“二方包”,也可以说是存根。一个更好理解的方法是,PB 可以理解为一种类似于对称加密协议,在客户端和服务端必须有存根的情况下,才能解析出对象,而 hessian 和 json 不依赖存根,这决定了 pb 的压缩效果更好。

这也可以解释为什么,使用 PB 序列化的 Triple(Dubbo3) 协议并没有被我们常用的服务运维平台的测试功能所支持。因为上述泛化调用模型只能构造可凭空解析的序列化类型。

如果实在要泛化调用 PB 序列化服务,解决方案还是有的,还是用对称加密举例,只要我拿到和服务端一致的“密钥“,我就可以构造出对方可解析的结构,从而发起泛化调用。这就是 gRPC 反射服务 的原理,反射服务可以让客户端在发起调用之前,拿到这份 proto 接口定义文件,从而获得对称加密的“密钥”,在这份密钥的基础上,填写好参数字段,就能像正常客户端一样发起调用了。

HSF-go 在 Dapr 场景的实践

上面主要聊了 Dubbo 体系的泛化调用模型,上面也提到了,泛化调用的应用场景非常多,也成为了 Dapr 落地的基础之一。Dapr 是阿里云合作的,微软开源的 CNCF 孵化项目,融合了标准化 API、组件可扩展SPI 机制、边车架构、Serverless 等诸多先进理念,在阿里集团有 FC,跨云等许多生产落地场景。

1、Dapr Binding 模型

Dapr 标准化 API 理念是非常新颖和实用的,其中 Bindings 构造块, 是我们服务调用解决方案的基础。

Bindings 最直观的理解,是介于用户应用运行时和网络之间的一层流量中间件。

上图可以解释基于 Binding 的整条调用链路,由用户应用运行时调用 Dapr 标准化接口从而发起调用。由 Dapr 运行时将流量交给可扩展的 Binding 构造块,Dapr 可以这种统一化接口和可扩展能力,很方便地支持多种协议的切换,按需激活。如图中伸展出来的 HSF、Dubbo 支持。

被激活的例如 HSF-go 构造块将接管这一请求,将来自应用的标准化的请求头和请求体解析出来,生成 HSF 协议请求,Dapr 边车一般不会拥有下游服务二方包,因此这一请求一定是泛化调用请求。

当然,在请求发出之前,早已完成了服务发现过程,这是用户以及应用运行时无感的,由 Dapr 来接管和封装。上面提到的泛化请求在完成服务发现之后,即可被发送至目的机器 ip,被下游的 Inbound Binding 的 HSF-go 实现所接收和处理,这个下游的组件对应上面提到的“服务端泛化调用”,他接受任何 HSF 请求。下游将 HSF 协议解析出来,参数从泛化调用的三个参数标准化为正常请求参数后,通过 Dapr 提供的 Callback 机制传递至应用运行时。

在这一过程中,泛化调用扮演了极其重要的角色,在客户端负责出流量的 HSF 协议泛化调用发起,在服务端负责入流量的泛化调用解析和传递。

我认为,Dapr 绑定的网络协议模型,是 RPC 协议进一步抽象的体现。将所有的 RPC 协议抽象为 metadata(元数据)和 body 两部分,用户应用/SDK 侧只需要关心这两部分的内容。一旦将这个抽象的请求结构交给 Dapr,具体协议的生成,就由具体激活的构造块来做了,这是我认为 Dapr 提供的一种很精巧的服务调用抽象设计。

2、序列化数组透传的设计

上面提到的入流量与出流量组件都是泛化调用的实现,但如果细究,并不是第一节我们提到的传统泛化调用。

传统泛化调用的入参是结构,调用过程涉及到序列化过程。在 Dapr 这种边车场景下,一次完整的 RPC 调用将会引入至少六次序列化/反序列化过程,这成本是巨大的。

因此在设计中,并没有使用标准泛化调用过程,而是将序列化过程省略掉了,只保留了应用侧的一次序列化,Dapr 边车针对参数部分只进行透传处理。这样来,大大减少了无谓的消耗。

这样一来,在客户端 Outbound 的实现,就成了针对如下泛化调用接口的使用:

//  args 参数为序列化后的byte数组
ProxyInvokeWithBytes(ctx context.Context, methodName string, argsTypes []string, args [][]byte) ([]byte, error)在服务端Inbound 的实现,也成了针对byte数组类型参数的泛化调用// inbound 入参
type RawDataServiceRequest struct {RequestContext *core.RequestContextMethod         stringArgsTypes      []stringArgs           [][]byte // args 参数为序列化后的byte数组Attachment     map[string]interface{}RequestProps   []byte
}

相当于在泛化调用的基础上,删除了序列化操作,将请求参数透传。

HSF-go 服务代理的设计

钉钉团队拥有很多 Go 语言落地场景,在 Dubbo-go 生态项目的发展过程中提供了诸多帮助与实践。

在跨集群通信解决方案中,代理网关是必不可少的,大多数网关需要运维人员手动进行流量配置。部分网关对网络协议存在要求,例如 envoy,因此中间件团队推出基于 Http2 的 Dubbo3(Triple) 协议的原因之一,就是为了适配网关。

在跨集群 RPC 场景下,理想情况是在网关层不需要进行协议转换,并且不需要进行序列化/反序列化过程,并且将服务治理能力融合在网关内部,从而减少资源消耗和运维成本。

这也提出了一种诉求,在集团内跨云场景下,我们需要建立一个支持原生 HSF 协议的代理网关,从而允许集群外部的客户端在无感的情况下,将请求切流量至集群内部,由网关接受来自外界的 HSF 请求,并动态进行服务发现流程,将请求流量转发至集群内对应服务提供者。可以想到,泛化调用在这个过程中将扮演重要角色。

我们沿着之前 Dapr 的思路,如上图所示,将视角从整个调用链路转移到单个实例上,可以看到一个实例可以接受泛化请求,并也可以发起泛化请求,在泛化过程中不涉及序列化过程。这个我们所关注的实例,就是一个网关的抽象表现。

拥有了这样的网关,我们可以实现客户端无感的跨集群调用。在必要的情况下,可以在客户端所在环境进行代理注册。

这样的网关是单向的,可以处理从外部进入内部的流量,如果希望双向打通,跨集群的统一化注册中心将是必要的。在这种情况下,网关需要根据流量查询多个注册中心的信息,从而保证链路正确。

总结

HSF 是阿里集团 RPC/服务治理 领域的标杆,Go 语言又因为其高并发,云原生的特性,拥有广阔的发展前景和实践场景,服务代理模型只是一种落地场景,除此之外,还有更多的应用场景值得我们在研发的过程中去探索和总结。

Dubbo/HSF 生态、Dubbo-go 技术体系将携手用户一同打磨与实践。

原文链接

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索AI视觉技术新应用,夸克扫描王首推“离线模式”端侧AI算法提升隐私安全

手机扫描正在超越传统扫描仪,给大学生和职场人带来更高效、更便捷的信息服务体验。 在基于手机相机功能的搜索行为中,大学生的学习场景占比超过一半。 手机扫描的“离线模式”,让夸克成为第一个将扫描AI算法上端的App。 各大高校开学在即&…

作业帮云原生降本增效实践之路

简介:目前,作业帮已经和阿里云有一个关于 AEP 的 tair 方案的结合,在新的一年希望我们有更大规模的落地。文章里讲得比较多的是关于降本做的一些技术改进,其实在降本增效这里面还有很大一块工作量是运营,成本运营我们也…

基于 Serverless 打造如 Windows 体验的个人专属家庭网盘

简介:虽然现在市面上有些网盘产品, 如果免费试用,或多或少都存在一些问题, 可以参考文章《2020 国内还能用的网盘推荐》。本文旨在使用较低成本打造一个 “个人专享的、无任何限速的、如 Windows 体验的私有云盘”。 作者 | 西流…

Apsara Stack 技术百科 | 数字化业务系统安全工程

简介:数字化平台已经与我们生活紧密结合,其用户规模庞大,一旦系统出现故障,势必会造成一定生活的不便。比如疫情时代,健康码已经成为人们出门必备的条件,一旦提供健康码服务平台出现故障,出行将…

支撑百万级传感器的延时队列

文/升哲科技 刘鹏 摘要:本文主要描述升哲科技在打造物联智慧城市平台过程中关于如何实现延时队列服务的技术选型经验、延时队列服务的架构设计以及延时队列的底层细节实现原理。 背景 升哲科技是一家物联网与人工智能领域的国家高新技术企业、独角兽企业。 要打…

深度解析|基于 eBPF 的 Kubernetes 一站式可观测性系统

简介:阿里云 Kubernetes 可观测性是一套针对 Kubernetes 集群开发的一站式可观测性产品。基于 Kubernetes 集群下的指标、应用链路、日志和事件,阿里云 Kubernetes 可观测性旨在为 IT 开发运维人员提供整体的可观测性方案。 作者:李煌东、炎…

系列解读SMC-R:透明无感提升云上 TCP 应用网络性能(一)| 龙蜥技术

简介:已有的应用若想使用RDMA技术改造成本高,那么有没有一种技术是不做任何改造就可以享受RDMA带来的性能优势? 文/龙蜥社区高性能网络SIG 引言 Shared Memory Communication over RDMA (SMC-R) 是一种基于 RDMA 技术、兼容 socket 接口的内…

技术引领未来, IDC TechScape中国数据安全发展路线图首发

2022年8月26日,IDC 2022 CSO全球网络安全峰会(中国站)在上海隆重开幕,会上首次发布《IDC TechScape:中国数据安全发展路线图,2022》。报告认为,帮助用户构建全方位数据安全治理体系将成为大趋势…

DataV 3D 平面地图 2.0 焕新上线

简介:DataV3月,3D平面地图2.0现已上线~ 3D 平面地图 2.0 现已上线~ 让我们来看看更新了哪些功能吧! 01 交互升级,省市区自由下钻 自带行政区域数据,无需配置: 甚至,可以通过「蓝图编辑器」实…

PolarDB-X 发布 2.1.0 版本,Paxos 开源

简介:2022年4月1号,PolarDB-X 正式开源X-Paxos,基于原生MySQL存储节点,提供Paxos三副本共识协议,可以做到金融级数据库的高可用和容灾能力,做到RPO0的生产级别可用性,可以满足同城三机房、两地三…

828成首个B2B企业节,华为联合3万生态伙伴助力中小企业数字化转型

中小企业既是市场的主体,也是保就业的主力军。截至2021年末,中小企业在全国企业中数量占比已超过99%,并贡献了80%的就业机会。 为助力中小企业创新发展,8月28日,华为联合3万家生态伙伴,共同发起了全国首个…

阿里云贾扬清:数据湖正成为企业数据应用创新标配

简介:全球数据湖峰会开幕 数字经济蓬勃发展的今天,越来越多的用户已经从“上好云”,走到了“用好云”的这个阶段。如果说在“上好云这个阶段,大多数用户关心的是如何在成本上获得更好的回报。那么在上好云这个阶段,更…

强强联手,NVIDIA 与 Ampere Computing 重磅推出云原生服务器平台

随着 5G、元宇宙的兴起,云游戏再一次迎来爆发。据 IDC 与中国信息通信研究院联合发布的《全球云游戏产业深度观察及趋势研判(2022年)》显示,2021年,中国地区云游戏市场收入已达 40.6 亿元,同比增长 93.3%。…

有了这款工具,定位线上问题事半功倍|云效工程师指北

简介:有了这款工具,定位线上问题事半功倍,程序员在日常工作中经常会遇到一些线上问题需要排查,本文的主人公程序员小张也不例外。但排查的过程却时常令他困扰不已。让我们一起看看他遇到了哪些问题,又是怎么解决的。 …

云原生时代如何用 Prometheus 实现性能压测可观测-Metrics 篇

简介:可观测性包括 Metrics、Traces、Logs3 个维度。可观测能力帮助我们在复杂的分布式系统中快速排查、定位问题,是分布式系统中必不可少的运维工具。 作者:拂衣 什么是性能压测可观测 可观测性包括 Metrics、Traces、Logs3 个维度。可观测…

基于 KubeVela 的机器学习实践

简介:本文主要介绍如何使用 KubeVela 的 AI 插件,来帮助工程师更便捷地完成模型训练及模型服务。 作者:KubeVela 社区 在机器学习浪潮迸发的当下,AI 工程师除了需要训练、调试自己的模型之外,还需要将模型进行部署上…

Gartner发布2022年云平台服务技术成熟度曲线,iPaaS、低代码将达到成熟期

Gartner 2022年云平台服务技术成熟度曲线显示,集成平台即服务(iPaaS)和低代码应用平台(LCAP)技术将在不到两年的时间内达到生产成熟期(Plateau of Productivity)。 编辑 | 宋慧 供稿 | Gartner…

贼喊捉贼?“盗版”软件开发者向 GitHub 投诉被侵权

整理 | 于轩 出品 | CSDN(ID:CSDNnews)拥有超过2亿个代码存储库,由8000多万用户共享,GitHub已然成为世界上最大和最先进的开发平台。 与其他托管用户生成内容的平台一样,这个庞大的代码库经常会接到版权…

基于 Serverless 架构的头像漫画风处理小程序

简介: 当一个程序员想要个漫画风的头像时... 前言 我一直都想要有一个漫画版的头像,奈何手太笨,用了很多软件 “捏不出来”,所以就在想着,是否可以基于 AI 实现这样一个功能,并部署到 Serverless 架构上让…

异动分析技术解决方案—异动归因之指标拆解

简介:归因的方法有多种,这篇文章的重点是指标拆解,也是我们做业务分析时最常用到的方法。我们的目的是解放人力,将指标拆解实现自动化,一方面可以加快业务迭代速度,快速定位问题;另一方面可以对…