当前位置: 首页 > 科技观察

Dubbo为什么要用Go重写?

时间:2023-03-12 00:23:08 科技观察

先说几句。走路的时候经常会想很多技术性的“whyquestions”。有时候一个问题想了很久,直到把问题的每一点都说服自己才算结束。所以想把这些想法记录下来,形成一篇文章,也算是一个新的系列。你可能看不到这些文章中的代码,但你可以瞥见一些容易被忽视的问题,以及问题更深层次的“原因”。今天带来第一篇,为什么要用Go重写Dubbo?Dubbo诞生于阿里巴巴,2011年开源,至今已走过10个年头。2019年用Go重写并开源。两年后,从最初的V1.0.0版本发展到V3.0.0,至今已有3800颗星。曾经有同事问我,为什么Dubbo这么“老”的项目要用Go重写?有什么实际意义吗?今天我来谈谈我的一些看法。承前启后,我觉得要回答好这个问题,还得从Dubbo-go的初衷说起。在github主页上是这样介绍自己的:官方中文翻译是用ApacheDubboGo语言实现的,它搭建了Java和Golang之间的桥梁,与gRPC/Dubbo生态互联互通,引领Java生态享受云原生时代的技术红利。我简单翻译一下:一个公司或者部门有人用Java版的Dubbo,有人用Go。两者需要通信,于是就有了Dubbo-Go来解决通信问题。那么第一个问题就是,一个公司为什么要用Java和Go?编程语言的选择对于编程语言的选择,在商业公司,我认为最重要的考虑是效率。至于其他的点都是次要的。因为商业公司的主要目的是盈利,不管是什么语言,只要能以最低的成本获得同等的收益,就是好语言。效率包括几个方面:开发效率。开发效率高,可以尽快上线项目,占领市场,还可以节省人力成本。运营效率。运行效率高,可以节省服务器成本纵观国内很多商业公司的选择,都是这个考虑,比如阿里。阿里早期使用PHP,选择PHP主要考虑的是开发效率。但是随着业务的发展,PHP的性能支撑不住了,需要换一种运行效率高的语言。运行效率高自然会想到C/C++,但这两种语言的开发效率低下,必须在开发效率和运行效率之间找到一个平衡点,所以阿里选择了Java。阿里官方在知乎上回答为什么选择Java时,主要有以下考虑:性能、易学、生态丰富、社区活跃把性能放在首位、易学、生态丰富、社区活跃开发效率,它与这些优点说明开发效率高。阿里巴巴在选择Java的时候,自研了大量的Java中间件,培养了大量的Java人才。所以其他公司在选择技术的时候也参考了阿里巴巴,导致越来越多的公司选择Java。选择Go也是一样。一些年轻的公司早期可能会使用PHP、Python等脚本语言。他们变强之后,不得不面对和阿里一样的问题:业绩问题。2012年Go发布时,大家又多了一个选择。Go具有高性能并且非常易于使用。像字节跳动这样的新公司专注于围棋。所以综合来说,选择Java或者Go是合??理的,存在也是合理的。为什么有的公司选择Java,要用Go?与Java相比,Go语言具有启动快、编译快、内存占用小、擅长高并发(协程)等特点。因此,已经有Java的公司也会使用它。考虑一下Go,但目前这样的公司并不多。有些公司没有强制性的技术栈,新部门、新业务可以摆脱束缚,选择新的语言Go进行开发。总结综上所述,选择Java还是Go是合理的。在一家公司里两者都选也是合理的。虽然占比不大,但还是有Java和Go通信的需求。Dubbo在RPC框架中的获胜公司,前期通常使用单体服务。当规模达到一定程度,单体应用无法支撑业务发展时,就会选择微服务架构。这时候就需要一个好用的RPC框架了。在能适配Java语言的RPC框架中,Dubbo是国内最早开源的,2011年就开源了。类似他的竞品如SpringCloud在2014年开源,微博上的Motan开源2017年开源,2015年开源跨语言gRPC,2007年开源Thrift。只有Thrift比它更早,但Thrift只是一个RPC框架,Dubbo包含开箱即用的服务管理能力,比如服务注册和发现、负载均衡、容错、动态配置等等。可以说,早期Java的RPC框架是没有选择的。即便是在RPC框架百花齐放的时代,有这么多公司的使用和阿里的背书,Dubbo也有它的一席之地。总结当一个公司选择了Java编程语言和Dubbo框架(选择还是很多的),后来想尝试Go,或者一些新业务、新部门想尝试Go时,他们面临一个问题,如何跟上去?Java的Dubbo通信。由于Dubbo协议是一个私有协议,用Go重新实现它的成本还是相当高的。于是Dubbo-Go应运而生。从这个角度来说,Dubbo-Go在Java和Go的通信上还是有相当大的价值的。结束与线程池的斗争如果你使用Dubbo框架,你往往需要一个Dubbo网关。Dubbo网关可以参考我的文章:《微服务网关演进之路》。在这篇文章中,我详细介绍了踏上Dubbo网关的背景、难点、选型、设计、演进和心得。其中,我花了很多时间介绍“与线程池的斗争”,线程是很宝贵的,但是如果同步调用dubbo网关,一个请求必须占用一个线程,导致并发失败,线程池满了会影响其他请求。所以解决办法要么隔离线程池,要么改成异步调用。隔离线程池只是解决了请求互不影响的问题,但是并发还是上不去。改成异步调用可以完美解决,但是编码太复杂。Go的协程正好可以解决这个问题。Go的协程非常轻量级,调度效率更高,所以我们可以用简单的代码写出一个非常高效的网关。比如你可以直观的感受到Nginx的性能是有目共睹的,但是如果用Java来实现,不知道要堆多少台机器才能达到Nginx的性能。但是百度在反向代理上用Go写的BFE来代替Nginx。可见其性能有多么夸张。关于协程的介绍和原理,可以参考我的文章:《写了一年golang,来聊聊进程、线程与协程》。总结所以在Dubbo网关上,Dubbo-Go也提供了一种新的解决方案。涂鸦智能已经有上线的Dubbo-Go网关,并开源为Dubbo-go-pixiu。为DubboMesh铺路ServiceMesh逐渐成为下一代微服务架构。Go绝对是Mesh上一颗闪亮的明星语言。K8S、Docker等云原生基础设施都是用Go编写的,或者说Go的开发速度和协程的高并发性使其成为Mesh的首选语言。基于此,Dubbo-Go也为DubboMesh铺平了道路,但DubboMesh还处于小规模阶段,完整的解决方案并未开源。从这个角度来看,如果一家公司想要借助DubboMesh走向全球化,Dubbo-Go或许也是他们重点考虑的因素之一。总结说了这么多,是时候正面回答为什么Dubbo要用Go重写了。这个问题的答案还是官方那句话:在Java和Golang之间架起一座桥梁。至于我们为什么要“架起这座桥”,参考下图: