Go 博客

奇虎 360 和 Go

周扬
2015 年 7 月 6 日

这篇客座博客文章由奇虎 360 软件工程师周扬撰写。

奇虎 360 是中国主要的互联网和移动安全产品及服务提供商,并运营着主要的基于 Android 的移动分发平台。截至 2014 年 6 月底,奇虎拥有约 5 亿月活跃 PC 互联网用户和超过 6.4 亿移动用户。奇虎还运营着中国最受欢迎的互联网浏览器和 PC 搜索引擎之一。

我的团队,即推送服务团队,为公司 50 多种产品(包括 PC 和移动)提供基础消息服务,包括我们开放平台上的数千个应用程序。

我们与 Go 的“爱情故事”可以追溯到 2012 年,当时我们首次尝试为奇虎的一款产品提供推送服务。初始版本使用 nginx + lua + redis 构建,由于负载过重,无法满足我们对实时性能的要求。在这种情况下,我们注意到了新发布的 Go 1.0.3 版本。我们在一周内就完成了原型,这在很大程度上得益于它提供的 goroutine 和通道功能。

最初,我们的基于 Go 的系统运行在 20 台服务器上,总共 2000 万个实时连接。系统每天发送 200 万条消息。该系统目前运行在 400 台服务器上,支持 2 亿多个实时连接。它现在每天发送超过 100 亿条消息。

随着业务快速扩展和对推送服务的应用需求不断增加,最初的 Go 系统很快就遇到了瓶颈:堆大小增加到 69G,垃圾回收 (GC) 的最大暂停时间为 3-6 秒。更糟糕的是,我们必须每周重新启动系统才能释放内存。如果我们不考虑放弃 Go,而是用 C 重写整个核心组件,那就不诚实了。然而,事情并没有完全按照我们的计划进行,我们在迁移业务逻辑层代码时遇到了麻烦。因此,当时只有我一个人无法维护 Go 系统,同时确保逻辑迁移到 C 服务框架。

因此,我决定继续使用 Go 系统(这可能是我做过的最明智的决定),并且很快取得了重大进展。

以下是我们进行的一些调整和主要收获

  • 用持久连接替换短连接(使用连接池),以减少通信过程中缓冲区和对象的创建。
  • 适当地使用对象和内存池,以减少 GC 的负载。
  • 使用任务池,这是一种机制,它有一组长期运行的 goroutine 消费连接 goroutine 发送的全局任务或消息队列,以替换短命 goroutine。

  • 监控和控制程序中的 goroutine 数量。缺乏控制会导致 GC 承受难以承受的负担,这是由于不受限制地接受外部请求而导致的 goroutine 激增造成的,因为发送到内部服务器的 RPC 调用可能会阻塞最近创建的 goroutine。

  • 请记住,在移动网络下,为连接添加 读写截止时间;否则,可能会导致 goroutine 阻塞。在局域网下谨慎使用,否则会影响 RPC 通信效率。

  • 使用管道(在 TCP 的全双工功能下)来提高 RPC 框架的通信效率。

因此,我们成功发布了架构的三个迭代版本,以及两个 RPC 框架的迭代版本,即使人力资源有限。这都可以归功于 Go 的开发便利性。您可以在下面找到最新的系统架构

持续改进过程可以用表格说明

此外,在这些优化之后,不需要临时释放内存或重新启动系统。

更令人兴奋的是,我们开发了一个用于分析 Go 程序的在线实时可视化平台。我们现在可以轻松地访问和诊断系统状态,找出任何潜在的风险。以下是系统运行的屏幕截图

这个平台最棒的地方在于,我们可以通过应用分布式压力测试工具(也是用 Go 构建的)来模拟数百万在线用户的连接和行为,并观察所有实时可视化数据。这使我们能够评估任何优化的有效性,并通过识别系统瓶颈来预防问题。

到目前为止,几乎所有可能的系统优化都已实施。我们期待 GC 团队带来更多好消息,这样我们就可以从繁重的开发工作中解脱出来。我想我们的经验有一天也会过时,因为 Go 仍在不断发展。

这就是为什么我想通过表达我对参加 Gopher 中国 的机会表示衷心的感谢来结束我的分享。这是一个让我们学习、分享和展示 Go 在中国受欢迎程度和繁荣的窗口。奇虎内部的许多其他团队已经开始了解 Go,或者尝试使用 Go。

我相信,在可预见的未来,将有越来越多的中国互联网公司加入我们的行列,使用 Go 重新创建他们的系统,而 Go 团队的努力将惠及更多开发人员和企业。

下一篇文章:Go、开源、社区
上一篇文章:Gopher 中国之旅报告
博客索引