43

性能提升 50%、资源占用节约 70%,知乎问答服务 Go 语言重构实践

 4 years ago
source link: https://www.tuicool.com/articles/vQvQzq7
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2019 年 3 月,Go 语言官方博客发布了 2018 年 Go 语言调查报告 , 共有来自 103 个国家的 5883 名开发者参与到这次的调查中。调查结果显示,目前将 Go 语言作为日常使用的编程语言的受访者已经达到 50%,在工作中使用 Go 语言开发的人数从 68% 增加至 72%,且受访者普遍都拥有了 2 年以上的 Go 语言开发经验。

rM3QJbm.png!web

虽然绝大多数受访者表示 Go 语言是他们最喜欢的编程语言,也在积极实践,但不可否认的是,他们对于 Go 语言的使用熟练度远不如其它语言高。如何才能更好的让 Go 语言为我所用呢?我们采访了知乎业务架构组技术负责人姚钢强。

据了解,知乎从 2017 年开始尝试使用 Go 语言来构建业务系统,目前知乎的问答、评论、文章、个人页、部分反作弊系统、部分搜索和商业的业务是使用 Go 语言进行搭建的,单元测试覆盖率一般在 70% 左右。

Go 语言在知乎的实践历程

从 2017 年开始使用 Go 语言构建业务系统到 2019 年使用 Go 语言重构老系统、开发新系统,这中间知乎一直在不间断的探索 Go 语言在企业中的实践。如果要把 Go 语言在知乎的实践历程划分成不同的阶段,姚钢强认为可以按照年份分为三个阶段:

2017 年,知乎技术平台和个别业务开始尝试使用 Go 语言构建自己的系统,但此时配套的基础设施并不完全,所以在这一年中,前架构团队开发了部分基础设施(RPC 框架、监控),并且使用 Go 语言重写了流量最大的内部 RPC 服务 member。

2018 年,随着知乎的发展,部分 Python 老服务资源消耗严重,于是团队开始针对评论和问答业务进行 Go 语言重写,在重写期间完善了基础设施(日志、降级、单元测试、Sentry),并确定了基础的代码组织结构。2018 年 7 月,知乎完成了评论业务的全部重写和问答业务主要流量接口的重写。2018 年底,知乎完成了关于问答业务 Python 与 Go 语言部分的基于业务的垂直拆分。

2019 年,知乎社区事业部开始针对占用资源较大的老 Python 业务进行 Go 语言重写,同时使用 Go 语言进行大部分新业务的开发。

知乎问答服务重构:Go 语言还是 Java,这是个问题?

问答服务是知乎目前对外流量最大的服务,之所以要重构的原因是随着知乎的发展,流量不断增加,原先使用 Python 构建的项目占用了太多的资源。

重构时是如何进行编程语言选型的呢?姚钢强表示:“我是 2018 年开始负责重构工作,当时我们主要是在 Java 和 Go 语言之间做选择,最终选择了 Go 语言的主要原因是当时在知乎 Go 语言的基础设施相对于 Java 更全面,RPC 框架、监控等基础设施已经完备。另外,知乎 Go 语言的群众基础更好,因为基础架构部门已经使用 Go 语言进行了一些 Proxy 的开发,工程师对于 Go 语言的兴趣更高。”

至于 Java ,姚钢强表示:“如果原先知乎是使用 Java 进行项目开发的话,可能也就不需要重构了。”

重构过程中遇到的挑战

与新建一个系统不同,项目重构更多的是变换过程,将之前的代码变换得到新的代码,而新代码的外部接口和输入输出还要和之前的代码保持一致。所以,项目重构面临的挑战很多,不仅要解决业务方面的问题,同时也要考虑与原有系统之间的关系。

知乎在重构问答服务时,主要的挑战有两个方面。

一是测试,问答服务是知乎很重要的项目,在保证单元覆盖的基础上,功能测试很复杂:读接口是同时发出请求,在线对比通过日志找出差异;写接口就必须在深入了解业务的基础上,与直接负责该业务的同事一起列出所有的 TestCase,先由两位工程师根据 TestCase 分别进行测试,然后交由 QA 进行二次验收;

二是之前的项目大量使用了 Python 的动态特性,尤其是类 GraphQL 的接口。所以,首先知乎团队分析了使用的类 GraphQL 接口,发现只有个别接口需要这种形式;其次,针对需要类 GraphQL 的解析进行一层抽象,单独一层(不使用反射)进行 URL 解析,然后将解析后字段对应到处理函数。

项目重构的收获

Go 语言重构项目完成之后,相比之前的 Python 项目,资源占用减少了 70% - 80% ,复杂接口的性能有 50% 左右的提升。在重构问答服务的过程中,知乎团队也对 Go 语言的基础组件和基础设施进行了完善。

据姚钢强介绍,目前业务中使用到的基础组件主要包括:

●      基于 Thrift 的 RPC 框架;

●      基于 go-chi 的 Web 框架;

●      基于 Sentry 的错误排查系统;

●      基于 go-resiliency 的降级;

●      基于 testify 的单元测试;

●      基于 go-runtime-metrics 的 runtime 监控;

●      基于 Graphite Grafana 打点和监控;

●      基于 Kafka 和 Beanstalk 的离线任务 ;

●      基于存储统一接口(可替换存储)的 cache 库。

知乎的 Go 语言重构计划

据了解,Go 语言已经成为知乎内部项目技术选型的推荐编程语言,不仅新业务的开发会首选 Go 语言,同时也使用 Go 语言重构了很多其它项目。目前知乎对内流量比较高的会员、评论服务和对外流量最大的问答服务都已经完成了重构,文章、个人页等其他服务也完成了部分流量较大接口的重构。

知乎未来是否还有比较大的重构计划?姚钢强表示:“目前没有重构计划,因为我们重构的初衷是节省机器资源,而流量比较大的业务都已经完成了重构,如果再去做其它重构,投入产出比太低了。”

Go 语言重构项目经验总结

什么样的项目适合使用 Go 语言来进行重构呢?姚钢强认为:“如果是占用机器资源比较多,且之前是使用 Python、PHP、Ruby 构建的业务系统,那么使用 Go 语言重构会节省大量机器资源,提高性能。如果原先是使用 Java 构建的业务系统,那么不建议使用 Go 语言进行重构。”

在使用 Go 语言重构项目的过程中,姚钢强认为以下三点是值得注意的:

  • 重构业务系统的第一步永远是了解业务,所以必须要有负责当前业务的同学参与。如果没有了解业务就盲目进行重构,那么很容易出现 Bug,而且还可能导致未来系统难以维护;
  • 项目开发之前要统一代码规范,配置好自动化的严格静态代码检,并且统一错误日志格式,做好调用链路跟踪的打点;
  • 在放量阶段要谨慎一点,针对读接口要先对比,然后逐步灰度放量;针对写接口,要与业务方和 QA 确认好所有的业务 TestCase,工程师先自测,然后交给其他工程师或者 QA 做二次验证。

针对 Go 语言本身,姚钢强也有一些期待:“目前 Go 语言在业务开发方面与 Java 还有很大差距,很多基础组件都不完善,期待之后 Go 语言的基础组件能够更完善,在语法方面能够提供泛型与更好的错误处理。”

采访嘉宾

姚钢强,知乎业务架构组技术负责人。2013 年加入知乎,曾担任首页 Feed 工程技术负责人,通过构架优化使响应时间 P95 从 1.6s 降低到 700ms,稳定性由 99.9% 提升到 99.99%。2018 年开始负责社区业务架构组,与团队一起用 Go 重写了知乎主要的业务模块,完成节省机器资源 75%,并完善了公司的 Golang 基础设施。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK