dubbo-go 是目前 Dubbo 多语言生态最火热的项目。dubbo-go 最先的版本应该要追溯到 2016 年,由社区于雨同窗编写 dubbo-go 的第一版。当时不少东西没有现成的轮子,如 Go 语言没有像 netty 同样的基于事件的网络处理引擎、 hessian2 协议没有 Go 语言版本实现,加上当时 Dubbo 也没有开始从新维护。因此从协议库到网络引擎,再到上层 dubbo-go ,其实都是从零开始写的。java
在 2018 年,携程开始作 Go 语言的一些中间件以搭建内部的 Go 语言生态,须要有一个 Go 的服务框架能够与携程的现有 dubbo soa 生态互通。因此由我负责重构了 dubbo-go 并开源出这个版本。当时调研了不少开源的 Go 语言服务框架,当时可以支持 hessian2 协议的并跟 Dubbo 能够打通的仅找到了当时于雨写的 dubbo-go 早期版本。因为携程对社区版本的 Dubbo 作了挺多的扩展,源于对扩展性的需求咱们 Go 语言版本须要一个更易于扩展的版本,加上当时这个版本自己的功能也比较简单,因此咱们找到了做者合做重构了一个更好的版本。通过了大半年时间,在上图第三阶段 19 年 6 月的时候,基本上已经把 dubbo-go 重构了一遍,整体的思路是参考的 Dubbo 总体的代码架构,用Go语言彻底重写了一个完整的具有服务端跟消费端的 Golang rpc/ 微服务框架。linux
后来咱们将重构后的版本 dubbo-go 1.0 贡献给 Apache 基金会,到如今已通过去了两个多月的时间,近期社区发布了1.1版本。目前为止,已经有包括携程在内的公司已经在生产环境开始了试用和推广。git
如今的 dubbo-go 已经可以跟 Java 版本作比较好的融合互通,同时 dubbo-go 自身也是一个完成的 Go 语言 rpc/ 微服务框架,它也能够脱离 java dubbo 来独立使用。
这边简单介绍一下用法,写一个 hello world 的例子。github
上图是一个简单的 java service ,注册为一个 Dubbo 服务,是一个简单的获取用户信息的例子。golang
上图是 dubbo-go 的客户端,来订阅和调用这个 Java 的 Dubbo 服务。Go 语言客户端须要显式调用 SetConsumerService 来注册须要订阅的服务,而后经过调用 dubbo-go-hessian2 库的 registerPOJO 方法来注册 user 对象,作 Java 和 Go 语言之间的自定义 pojo 类型转换。具体的服务调用方法就是声明一个的 GetUser 闭包,即可直接调用。web
上图,一样的能够基于 dubbo-go 发布一个 GetUser 的服务端,使用方式相似,发布完后能够被 dubbo java 的客户端调用。apache
如上图所示,如今已经作到了这样一个程度,一样一份 dubbo-go 客户端代码,能够去调用 dubbo-go 的服务端,也能够去调用 Dubbo Java 的服务端;一样一份 dubbo-go 的服务端代码,能够被 dubbo-go 客户端和 Java 客户端调用,因此基本上使用 Dubbo 做为 PPC 框架的 Go 语言应用跟 Java 应用是没有什么阻碍的,是彻底的跨语言 RPC 调用。更重要的是 dubbo-go 继承了 Dubbo 的许多优势,如易于扩展、服务治理功能强大,你们在用 Go 语言开发应用的过程当中,若是也遇到相似须要与 Dubbo Java 打通的需求,或者须要找一个服务治理功能完备的 Go 微服务框架,能够看下咱们 dubbo-go 项目。api
下面介绍一下 dubbo-go 的组成项目,为了方即可以被其余项目直接复用, dubbo-go 拆分红了多个项目,并所有以 Apache 协议开源。服务器
apache/dubbo-go
dubbo-go 主项目, Dubbo 服务端、客户端完整 Go 语言实现。websocket
apache/dubbo-go-hession2
目前应用最普遍,与 Java 版本兼容程度最高的 hessian2 协议 Go 语言实现,已经被多个 GolangRPC & Service Mesh 项目使用。
dubbo-go/getty
dubbo-go 异步网络 I/O 库,将网络处理层解耦。
dubbo-go/gost
基本类库,定义了 timeWheel、hashSet、taskPool 等。
dubbo-go/dubbo-go-benchmark
用于对 dubbo-go 进行简单的压力测试,性能测试。
apache/dubbo-go-hessian2
先简单介绍一下 dubbo-go-hessian2 项目。该项目就是 hessian2 协议的 Go 语言实现,最基本的能够将 Java 的基本数据类型和复杂数据类型(如一些包装类和list接口实现类)与 golang 这边对应。
详情能够参考这里。
另外 Dubbo Java 服务端能够不捕获异常,将异常类经过 hession2 协议序列化经过网络传输给消费端,消费端进行反序列化对该异常对象并进行捕获。咱们通过一段时间的整理,目前已经支持在 Go 消费端定义对应 Java 的超过 40 种 exception 类,来实现对 Java 异常的捕获,即便用 dubbo-go 也能够作到直接捕获 Java 服务端抛出的异常。
另外对于 Java 端 BigDecimal 高精度计算类的支持。涉及到一些金融相关的计算会有相似的需求,因此也对这个类进行了支持。
其余的,还有映射 java 端的方法别名,主要的缘由是 Go 这边语言的规约,须要被序列化的方法名必须是首字母大写。而 Java 这边没有这种规范,因此咱们加了一个 hessian 标签的支持,能够容许用户手动映射 Java 端的方法名称。
基本上如今的 dubbo-go 已经知足绝大多数与 Java 的类型互通需求,咱们近期也在实现对 Java 泛型的支持。
dubbo-go/getty
Go 语言天生就是一个异步网络 I/O 模型,在 linux 上 Go 语言写的网络服务器也是采用的 epoll 做为最底层的数据收发驱动,这跟 java 在 linux 的 nio 实现是同样的。因此 Go 语言的网络处理天生就是异步的。咱们须要封装的实际上是基于 Go 的异步网络读写以及以后的处理中间层。getty 将网络数据处理分为三层,入向方向分别通过对网络 i/o 封装的 streaming 层、根据不一样协议对数据进行序列化反序列化的 codec 层,以及最后数据上升到须要上层消费的 handler 层。出向方向基本与入向通过的相反。每一个连接的 IO 协程是成对出现的,好比读协程负责读取、 codec 逻辑而后数据到 listener 层,而后最后的事件由业务协程池来处理。
该项目目前是与 dubbo-go 解耦出来的,因此你们若是有相似需求能够直接拿来用,目前已经有对于 tcp/udp/websocket 的支持。
Apache / dubbo-go
dubbo-go 主项目,咱们重构的这一版主要是基于 Dubbo 的分层代码设计,上图是 dubbo-go 的代码分层。基本上与 Java 版本 Dubbo 现有的分层一致,因此 dubbo-go 也继承了 Dubbo 的一些优良特性,好比整洁的代码架构、易于扩展、完善的服务治理功能。
咱们携程这边,使用的是本身的注册中心,能够在 dubbo-go 扩展机制的基础上灵活扩展而无需去改动 dubbo-go 的源代码。
目前 dubbo-go 已经实现了 Dubbo 的经常使用功能(如负责均衡、集群策略、服务多版本多实现、服务多注册中心多协议发布、泛化调用、服务降级熔断等),其中服务注册发现已经支持 zookeeper/etcd/consul/nacos 主流注册中心。这里不展开详细介绍,目前 dubbo-go 支持的功能能够查看项目 readme 中的 feature list ,详情参考:https://github.com/apache/dubbo-go#feature-list
目前社区正在开发中的功能,主要是早期用户使用过程当中提出的一些需求,也是生产落地一些必需的需求,如监控、调用链跟踪以及服务路由、动态配置中心等更高级的服务治理需求。
这里详细作几个重点功能的介绍。首先是泛化调用,如上图,这个也是社区同窗提的需求。该同窗公司内部有不少 Dubbo 服务,他们用 Go 作了一个 api gateway 网关,想要把 Dubbo 服务暴露成外网 http 接口。由于内部的 Dubbo 服务比较多,不可能每个 Dubbo 服务都去作一个消费端接口去作适配,这样的话一旦服务端改动,客户端也要改。因此他这边的思路是作基于 dubbo-go 作泛化调用, api-gateway 解析出外网请求的地址,解析出想要调用的 Dubbo 服务的目标。基于dubbo-go consumer 泛化调用指定 service、method ,以及调用参数。
具体的原理是, dubbo-go 这边做为消费端,实际会经过本地 genericService.invoke 方法作代理,参数里面包含了 service name,method name ,还包含被调用目标 service 须要的参数类型、值等数据,这些数据后面会经过 dubbo-go-hession2 作转换,会将内容转化成 map 类型,通过网络发送到对应的 Java 服务端,而后 Java 那边是接收的 map 类型的参数,会自动反序列化成本身的 pojo 类型。这样就实现了 dubbo-go 做为客户端,泛化调用 Dubbo 服务端的目的。
降级熔断这边是基于的是你们比较熟悉的 hystrix 的 Go 语言版本,基于 hystrix ,用户能够定义熔断规则和降级触发的代码段。降级熔断支持是做为一个独立的 dubbo-go filter ,能够灵活选择是否启用,若是不启用就能够在打包的时候不将依赖引入。Filter 层是 dubbo-go 中对于请求链路的一个责任链模式抽象,目前有许多功能都是基于动态扩展 filter 链来实现的,包括 trace、leastactive load balacne、log 等。降级熔断设计成一个服务调用端独立的filter能够灵活知足调用端视角对于微服务架构中“防雪崩“的服务治理需求。
关于动态配置中心, Dubbo 的 2.6 到 2.7 版本作了一个比较大的变化,从以前的 url 配置形式过渡到了支持配置中心 yaml 格式配置的形式,治理粒度也从单服务级别的配置支持到了应用级别的配置,不过在2.7版本中仍是兼容 2.6 版本 url 形式进行服务配置的。dubbo-go 这边考虑到跟 Dubbo2.6 和 2.7 的互通性,一样支持 url 和配置文件方式的服务配置,同时兼容应用级别和服务级别的配置,跟 dubbo 保持一致,目前已经实现了zookeeper和apollo做为配置中心的支持。
最后是你们比较关注的,社区关于 dubbo-go 2019 年下半年的计划,目前来看主要仍是现有功能的补齐和一些问题的修复,咱们的目标就是首先作到 Java 和 Go 在运行时的兼容互通和功能的一致,其次是查漏补缺 dubbo-go 做为一个完整 Go 语言微服务框架在功能上的能够改进之处。
另外值得关注的一点是,预计今年年末, dubbo-go 会发布一个支持 kubernetes 做为注册中心的扩展,积极拥抱云原生生态。关于云原生的支持,社区前期作了积极的工做,包括讨论关于 dubbo-go 与 Service Mesh 的关系以及在其中的定位,能够确定的是, dubbo-go 将会配合 Dubbo 社区在 Service Mesh 方向的规划并扮演重要角色,咱们初步预计会在明年给出与 Service Mesh开源社区项目集成的方案,请你们期待。
dubbo-go 社区目前属于快速健康成长状态,从捐赠给 Apache 后的不到3个月的时间里,吸引了大批量的活跃开发者和感兴趣的用户,欢迎各位同道在使用或者学习中遇到问题可以来社区讨论或者给予指正,也欢迎对 dubbo-go 有潜在需求或者对 dubbo-go 感兴趣的同道能加入到社区中。
做者信息:何鑫铭,目前就任于携程,基础中台研发部技术专家,dubbo-go 共同发起人、主要做者,Apache Dubbo committer,关注互联网中台以及中间件领域。
本文做者:何鑫铭
本文为云栖社区原创内容,未经容许不得转载。