作业帮初期因业务快速发展,做事端采取 PHP 措辞作为紧张开拓措辞,很好支撑了业务快速的迭代发展。
但随着业务发展,以 ODP 为代表的 PHP 做事端技能栈碰着了一些问题,作业帮选择了 GO 作为主推的做事端开拓措辞来替代 PHP。

本文,InfoQ 与作业帮根本架构部门进行了深入互换,理解切换前后须要把稳的所有问题,并分享给广大开拓者和企业。

内部团队的决策过程

InfoQ:谁拍板决定切换这件事情的?

php作业600 办事模块1 万 POD 数目功课帮从 PHP 迁徙至 Go 实战总结 Angular

董晓聪:综合业务部门及根本架构团队的诉求,与公司的技能副总裁及以下的所有业务技能团队一起沟通干系技能问题,大家共同投票决定。

InfoQ:当时有人提过反对见地吗?

董晓聪:2020 年,Go 相对成熟,公司内部技能干系的很多职员或多或少有些 Go 的项目背景,加之 kubernetes 以 Go 措辞为根本,大家对选择 Go 措辞没有那么反对,但对详细哪些模块切换到 Go 上是存在谈论空间的。
起初,大部分业务职员处于不雅观望状态,期望我们可以拿出过硬的成功案例,我们从业务中台入手,改造后收益明显,越来越多的团队加入。

InfoQ:我们在这个过程中向技能副总裁或者其他更高的领导申报请示过这件事情的进展吗?

董晓聪:前段韶光,我们将这个迁移过程整理出来向技能副总裁做了申报请示。
除了性能、开拓效率等层面的变革,我们从最初的云原生险些为零到现在所有架构全部云原生化。
虽然从韶光周期来看,两年韶光有点久,但我们做了很多切换措辞层面之外的事情,比如整体做事的标准化、容器化改造以及多云体系培植。
如果仅仅是纯挚的措辞切换,云原生根本举动步伐支持不好依旧会拖累业务发展。

为什么用 Go 重写全体架构?

InfoQ:为什么以为 PHP 弗成须要切换新的编程措辞呢?

吕亚霖:业务部门希望根本架构部门实现一套 Go 的框架以及标准,紧张希望办理的问题:一是 PHP 高并发场景下表现差,作业帮的并发在几十万旁边,PHP 本身是一个进程模型,资源利用率非常高,业务本钱大,在高并发、高性能的部分场景表现不理想。
业务方希望有一个支撑高并发的措辞办法,当时选择的是 Go;二是作业帮当时正在进行云原生容器化和做事管理方向的改造,PHP 的匹配度严重不敷;三是业务当时的业务技能中台在迭代培植,PHP 微做事架构支持欠缺,比如 ODP 通过 PHPLIB 耦合做事,类单体架构,做事间边界模糊,框架全局支配且缺少当代包管理工具,而 Go 天然可以和微做事很好地结合。

业务部门提出需求之后,我们对不同的编程措辞进行了调研,并拜访了美团、字节跳动等企业,理解 Go 措辞的实际运用情形,由于得到的反馈比较不错,我们决定启动大规模切换。

InfoQ:字节跳动的 Go 措辞利用的很不错,我们当时还找过用其他措辞的企业去聊吗?

吕亚霖:由于作业帮原来的架构是用 PHP 和 C++ 措辞编写的,以是也不想大规模转 Java,如果转 Java 就意味着自底向上全部重构。
一样平常来说,选择 Java 意味着很多做事都须要接入 Java 体系,比如做事管理大多利用基于 Java 的 SpringBoot,而我们是范例的多措辞栈,我们只是希望用 Go 措辞更换掉 PHP 的部分,但是 C++ 措辞编写的底部检索系统、OCR 等部分模块可以保留,毕竟 C++ 在底层的表现还是非常不错的。

InfoQ:为什么不选择用 C++ 统一技能栈呢?

吕亚霖:C++ 的紧张问题在于开拓效率不是特殊高,C++ 和 PHP 的组合也是 10 年前业内比较经典的做法,上层业务逻辑的部分由 PHP 去做,底层性能的部分由 C++ 卖力,达到开拓效率与性能的平衡。
早期,PHP 开拓效率高且稳定。

InfoQ:2020 年决定迁移的时候,PHP 和 GO 的生态环境大概是什么样的?

吕亚霖:PHP 的生态环境比较成熟,社区生动度不高,作业帮当时内部的生态和工具比较成体系化,是一个范例的 ODP 体系(ODP 最早是百度提出来的,是在“鸟哥”惠新宸开拓的 PHP 框架 Yaf 根本上做的调度,整合了一些 Web 框架以外的东西,比如 Nginx、PHP 扩展等)。
GO 当时的生态还处在蜕变过程中,GO 的包管理工具 go mod 发布了测试版本,还没有正式推出,但 Go 的社区生动度非常高,国内外的大厂在 Web 和根本组件场景都有非常精良的实践和落地履历。

InfoQ:当时,内部研发团队的措辞背景大概是什么?

吕亚霖:根本架构团队的主措辞背景是 C++ 和 Go。
由于当时 kubernetes 已经盛行,kubernetes 体系内均基于 Go 措辞实现,我们当时也在做容器化,因此在 2019 年前后招聘了很多有 Go 措辞根本的工程师。
业务侧研发职员较多,措辞背景紧张是 PHP 和 C++,全体切换也是业务线主力修正。
根本架构部紧张卖力 Go 的运行时、框架及生态工具的培植,给出业务线案例,并完成帮忙事情,比如帮助业务查问题。

重写过程碰着的坎儿

InfoQ:我们大概花了多永劫光完备切换过来?

蒋帅:大概用时两年,紧张分为几步:一是 DevOps 全体体系由根本架构部门管控,我们对新立项的业务模块(Web 做事)开始建议利用 Go,不供应 PHP 创建的模板;二是切换的同时,我们也在做云原生改造,对高并发性能及稳定性有哀求的核心模块(F0 核心链路上的模块),我们在公司内部统一发起切换,公司级统一排期、统一验收。
非核心链路大概是有半年的韶光,由业务线自行排期,逐步改造并验收;末了是发布系统上半年旁边没有迭代的 PHP 项目,这些模块不逼迫切换,业务根据需求决定。
终极,我们一共完成了 600 多个做事切换。

InfoQ:对核心系统切换时,如何担保整体的稳定性?

蒋帅:紧张有几个方向:一是灰度放量,这是一个范例的 AB 测试过程,PHP 编写的旧模块逐步减量,GO 编写的新模块逐步增量,多机房须要分区域逐步放量。
当所有流量全部切换至新系统且经由一段韶光的不雅观察没有问题之后,再下线旧系统。
二是,基于云原生供应完善的不雅观测能力。
有问题及时接入办理。

InfoQ:我们在全体切换的过程中碰着过哪些比较难的问题?

蒋帅:这里面存在一些问题:一是历史债务问题,当时 PHP 已经在内部用了良久,存在大量的历史债务问题,比如 PHP 的日志都是半构造化的 KV 构造,很难支撑大数据剖析和监督告警,我们后来在 PHP 里面打了却构化和半构造化两条日志,但继续过来之后创造全体日志链路的压力会增加一倍,但由于大数据监控等依赖方的存在,这种问题一贯无法彻底办理,这次切换也把该问题办理掉了。

二是快速召回升级,最初的版本很随意马虎涌现问题,这就须要快速升级到新版本,但由于一个包的利用者浩瀚,以是难以在问题涌现时逐一奉告升级,我们建立了反向包管理工具平台。
通过 CI 剖析,知道所有利用方利用的是哪个包版本。
对某个版本的利用方都明确建立索引关系。

三是 PHP 自身的问题,PHP 属于弱措辞类型,这种弱措辞类型和特种函数带来的问题都须要在 Go 里面兼容,但实际上很多问题都是上线后创造的,比如加解密的私有库。

履历复盘及后续优化

InfoQ:Go 措辞哪些上风让团队以为比较爽?

蒋帅:一是 Go 的社区非常生动,对个人和公司来说,有很多互换和学习的可能,包括对团队的招聘的掩护都有帮助;二是高性能,很多模块从 PHP 切到 Go 之后,性能提升显著,尤其是晚高峰时的性能、吞吐量以及单核支撑的 QPS;三是功率和生态在不断演进,Go 最初的包管理工具不是特殊空想,后来社区推出了公共的包管理工具,而 PHP 的社区掩护、工具完善度以及生态与 Go 比较存在明显差距。

与 C++ 比较,Go 措辞的开拓效率更高,性能略差,但属于在性能和效率之间达到了很好的平衡。

InfoQ:编程措辞的调度对架构有造成什么影响吗?

蒋帅:首先,编程措辞在架构中起到承上启下的浸染,承上是业务规范及研发质量,启下是云原生架构落地,只有编程措辞这一层没有问题,才能很好地把高下连接起来。
以 PHP 为例,如果基于 PHP 对云原生做适配,PHP-FPM+nginx 以及各种私有库依赖打出来的包动辄便是几百兆,而且同时拉起几千个 POD 很随意马虎涌现延迟的问题,在 mesh 的协议支持上也不友好。
而 Go 只须要 5-10 兆,对落地容器化和做事管理都十分友好。

InfoQ:事后复盘有哪些值得优化的地方?

蒋帅:一是由于切换为 Go 措辞的改动非常大,尤其是在微做事架构下,须要一个稳定、高效的开拓测试环境,如果没有做事管理体系的支撑,很难在本地走完全个流程。

举例来说,如果开拓职员在本地开拓一个模块,该模块须要依赖调用十几个模块,这里面就存在联调测试环境和本地环境互通的问题,PHP 是通过将开拓环境直接挪到做事器上来,工程师在做事器上开拓来办理这个问题的,但在云原生体系下,这个问题可以通过 servicemesh 办理。

二是平台及工具支持先行,不能等业务碰着问题再去办理,这样会导致业务的体验很差。
早期赶进度知足业务快速迁移的过程中,我们翻译了部分公共库的方法,但效果不太好,我们后期开拓了相应的代码天生工具以及配套的迁移文档,合营业务快速完成迁移,并定期在内部进行干系宣讲及答疑。

InfoQ:后续的优化方向是什么?

蒋帅:经由两年的发展,作业帮的 GO 措辞从 0 蜕变成做事端利用数量最多的开拓措辞,已有 GO 项目全部基于 ZGIN 构建(ZGIN 基于 gin 衍生而来,是面向 web 做事的开拓框架,供应了开箱即用的常用组件和功能,侧重通用性和稳定性,兼顾性能和时延,构建了符合公司业务场景的生态体系)。
做事模块数量达 600 余个,做事 POD 数量在 1 万以上。

面向未来,我们将连续从几个方向进行优化,一是安全方向,其他措辞我们都有 RASP 的防护,我们目前在 GO 上考试测验通过 eBPF 内核结合用户态来运行 RASP。

二是适当优化性能,我们现有做事器,大多数以大规格裸金属做事器(256 核)为主,我们针对特定硬件的 numa 拓扑特性做 GMP 调度优化,其次我们做事基本以容器运行为主,自动适配容器场景下 POD 的 limit。

InfoQ:我们有希望 Go 社区可以增加的特性或者优化吗?

蒋帅:一是 GO 官方团队还是优化下 GC 问题,由于我们创造有时候 GO 的 GC 频繁且耗用资源较多,我们是通过自适应 GC 优化了该场景下的问题。
另一个是 Go 运行时的可不雅观测性,我们只能在内核上通过 eBPF 去搞,但实际上这个 Runtime 的不雅观测性该当由 Go 的干系团队卖力,我们是将能力往下沉了。

InfoQ:你以为用什么样的编程措辞与研发团队的规模或者协作模式之间会有关联吗?

蒋帅:我以为和团队规模没有关系,可能与业务场景及措辞生态有关系,以作业帮为例,我们在底层检索系统、搜索引擎和 OCR 上都是 C++,面向业务的 Web 做事都是 Go,大数据用的是 Java,人工智能用 Python 的比较多,我以为一旦公司的产研到了千人规模以上,编程措辞一定会呈现多样化。
但是会有一个主业务措辞,可能一半的人都在用该措辞。

InfoQ:你认为企业处于什么样的发展阶段做这件事情会比较得当一些?

蒋帅:越早越好。
切换周期非常长,投入的人力和精力非常大,如果还没有碰着实际问题,或者说现在 PHP 用的非常好,不要跟风去切,由于我们是出于多方面考虑才做的决定。
如云原生改造,降本增效也有很强诉求等等。

高朋简介

董晓聪,作业帮根本架构卖力人,卖力架构研发、运维、DBA、安全、等团队。

吕亚霖,作业帮根本架构-架构研发卖力人,在作业帮期间主导了云原生架构演进。

蒋帅,卖力作业帮运用技能栈方向,紧张推动了 ODP 框架容器化改造、ODP 转 GO 及 GO 框架生态的培植。