作者
,译者两年前,Uber先前的聊天应用程序开始显示出无法适应我们的发展的迹象。有应用程序崩溃、性能打嗝以及停电中断,削弱了我们公司在线有效沟通的能力。用户满意度一直走低,所以我们需要一个新的解决方案。
我们的运营分布在620多个城市,能让Uber员工无论处于世界何地都能在台式机和移动设备上可靠地进行通信,这一点非常重要。为此,我们制定了一些核心要求。首先,我们需要一些东西能够扩展以支持不断増长的员工人数,同时也能控制其成本。我们还需要一个可以轻松与各种内部工程、业务和操作工具相集成的平台。
当我们评估互联网中继聊天(IRC)和许多其他流行的聊天客户端时,很明显,没有一个完整的第三方解决方案可以满足Uber的核心要求。
所以,在测试了多个现成的替代方案后,我们利用开源平台Mattermost和Puppet构建了uChat,它是我们的定制内部消息平台,是用于部署配置管理的Uber标准。在本文中,我们将讨论如何在短短三个月内,我们的团队让公司转变到能够在一个统一的聊天环境中每天向数万用户可靠地发送超过一百万条消息的新解决方案。
走向开源
为了加快开发进程,我们决定基于开源平台构建我们的解决方案。这个选择尤其有吸引力,因为我们希望直接影响路线图并控制长期的经常性成本。如果从零开始就会更加困难。
为了充分利用我们的混合构建方法,我们需要一个功能强大的开源构建块,它得有多功能的API、高质量的代码库和充满活力的开发社区。我们评估了各种XMPP、Erlang和基于JavaScript的选项。由于我们的主要要求是能够支持Uber的增长,因此我们特别留意那些可扩展性很好的聊天平台。
作为性能验证的一部分,我们将每个开源产品的性能推到了突破点。例如,我们的初始目标之一就是在一个单一的聊天环境中模拟50,000个用户的聊天行为。很快,很多这些平台就无法进行这些基本的负载测试。
图1a:我们对测试实体线程(Thread)的设计尽可能简单,从而将注意力集中在快速验证产品声明上。
对于其他的性能选择,我们编写了一个测试工具来模拟成千上万的用户。测试集的设计(上图1a)非常简单,这确保了我们可以用最小的努力来验证产品声明。在这个测试环境中,简单的Go结构的EntityConfig(下图1b)封装了可以登录、加入渠道和发送消息的用户。结合Go的本地协同程序,很容易达到我们的模拟目标。随着时间的推移,测试工具能提供更强大的功能,更好地模拟复杂的用户场景。
图1b:EntityConfig代表着平台上用户的基本交流需求。
经过数月的测试和供应商审查,我们选定了Mattermost。Mattermost大大超出了我们的最低性能预期,并与Uber现有的技术堆栈很一致。此外,他们的客户端用户界面类似于那些很受Uber员工喜欢的聊天应用程序界面。
下一个合乎逻辑的步骤是,评估该平台是否能够跟上Uber的高增长并维持我们对聊天的操作依赖性。仔细考虑了必要的因素之后,我们问自己:Mattermost能否达到Uber规模?
为了测试Mattermost在适应这些条件方面的能力,我们的负载测试旨在识别出可能影响性能的软件架构和服务器代码的主要瓶颈。我们模拟了可变消息发送速率、升高窗口和并发用户峰值以建立基准。我们创建了成千上万的假用户帐户,并编程用以登录、加入聊天室和进行聊天,目的在于触发崩溃和数据库锁定。
图2:在对基于Mattermost的聊天解决方案测试期间,当主数据库连接达到最大值而且数据库锁定时,消息发送速率下降。
在测试期间,我们并不惊讶地发现,不仅仅是后台显示出了有限的可扩展性。我们测试过的大多数用户界面都不能达到我们积极的目标:譬如,聊天室仅能容纳约一百个用户,而且现有的用户界面不能同时搜索20,000多个频道。
当在规模测试期间遇到瓶颈时,我们针对最具影响力的性能违规者进行了修复,并从已知的稳定负载水平重复了该过程。同时,我们继续更新测试,以模仿更加现实的用例。我们的初始目标是7万个并发用户、发送速率为每秒80到200条消息。如果能够成功管理这种负载,我们可以确保有足够的空间来支持将来的增长。
与开源社区合作,我们不断剖析日志、识别根本原因并发布新的修复。这里,周转速度至关重要。随着每个新的发现和构建,我们对整体系统的局限和快速适应可扩展需求的能力有了更深入的认识。
渐渐地,我们清楚地看到Mattermost在当时最能够发展成熟到Uber规模,我们对他们的平台也有了信心。为了帮助其他人使用我们的新合作伙伴去开发聊天平台,我们把测试工具贡献到了开源社区。
用Puppet来管理uChat软件架构
在对Mattermost平台进行负载测试时,我们需要持续可靠地更改新解决方案的基础架构和应用配置。Mattermost的高可用性(High Availability)模式仍然处于早期测试阶段,因此我们经常在代码中遇到错误。
在早期的测试和开发阶段,Uber基础设施团队手动地修改了这些代码。可以预料的是,让新的uChat构建和服务器配置稳定下来是一个乏味且易于回归的过程,需要频繁地进行更改以修复无意的配置错误。很明显,人工基础设施管理正在放缓我们的速度,于是我们转向了Puppet。
我们使用Puppet来编码软件架构和服务器配置,为管理支持uChat快速改进所需的各种服务器和网络环境提供了坚实的基础。 Puppet可以对数据库拓扑中的多个机器实现一致的和可重复的更改,并允许我们审核更改和执行部署代码审查。
图3:uChat最初的Puppet工作流不能达到我们的解决方案所需要的能可靠地迭代和扩大规模的速度。
最初引入Puppet极大地减少了部署期间的无意错误。然而,即使基本的Puppet基础架构代码解决了我们的一些重复性和一致性问题,我们仍然没有达到所需要的速度。在这个阶段,我们没有使用不可变的服务器,这意味着改变高可用架构的Puppet代码带来了意想不到的副作用的巨大风险。此外,我们正在使用一个大型monorepo,其中所有与Puppet相关的更改必须收敛,从而使得问题更严重。
这种约束意味着我们无法快速地部署新的基础架构和应用程序版本以满足我们的需求,严重限制了我们的迭代速度。因此,更新的Puppet部署配置可能需要一两天才能安全完成。同时,每小时都可收到无关的uChat性能提升。我们新的基于Puppet的工作流程更好,但仍有改进的余地。
图4:uChat目前的Puppet部署流为由我们的网站可靠性工程师维护的Puppet模块集成了一个单独的存储库。
为了加快uChat部署,我们将基础架构代码转换为单独的存储库作为Puppet模块。这将允许我们独立地管理版本、隔离和测试与uChat应用程序特定相关的配置更改,而不用管服务器基础结构配置。
在重构并彻底测试了新的Puppet模块后,我们依靠Puppet代码管理器将基础设施更改推向新建的模拟和生产环境。这种基于模块的方法使我们能够将应用程序配置问题与基础设施/服务器配置问题分开,更容易地根据uChat应用程序本身的需求和发布时间表来分发更改。
图5:上面详细介绍的uChat软件架构完全由Puppet编排。这有利于可靠地部署和微调平台所需的高质量变更控制。
通过Puppet模块、Puppet代码管理器和对A/B部署的支持,我们终于实现了所需要的快速而一致的部署变更控制。现在,我们可以在不到一天的时间内可靠地完成整个模拟和生产环境。
创造无缝用户体验
在让基础架构变得成熟的同时,我们还必须建立一套直观的Uber-fied网络、桌面和移动应用程序。首先,我们克隆了Mattermost桌面应用程序,并开始对内部客户进行简单的白色标签。另一方面,Mattermost移动应用程序需要进行完整的重组,以实现我们正在寻找的用户体验(UX)类型。
图6:我们团队的设计批评改进了Mattermost/uChat中的用户界面,在使用UX识别问题点时没有任何遗漏之处。
原先的基于iOS和Android的uChat应用程序集成了一个简单的网络视图来加载整个uChat网页,导致加载时间极慢。另外,网络视图引起刷新,强制不必要的加载、不完整的文件下载和不均匀的体验。为了增强我们的员工并加快建设,我们与Fullstack Labs合作,在React Native中重写这些应用程序。正如我们与Mattermost所支持的平台的做法一样,我们向开源社区贡献了所构建的一切。
目前,uChat移动客户端通过我们的内部应用程序商店进行部署,通过Chef和System Center Configuration Manager(SCCM)来管理桌面客户端。为了限制移动uChat版本数量,并简化持续的支持,我们在iOS和Android应用程序中构建了自定义机制,提示用户在新的uChat版本可用时进行升级。我们还设计了一项功能,用于在需要强制升级的情况下让旧客户端版本实效。
uChat移动应用程序可以让Uber员工轻松在即时和跨设备进行通信。
我们对可扩展性平台的远景确保了我们提供与生态系统中的其他工具相集成的UX。为了实现这一目标,我们花了几个月的时间将以前的解决方案中的50多个旧功能集成到了uChat。API和webhooks允许现有的内部服务集成和扩展聊天功能,例如Uber的内部部署系统uDeploy,它在新的构建完成时通知工程师;或者Envoy,它支持我们的办公室访客注册服务。
构建用户的信任
在实现任何的企业应用程序时,推动用户采用产品和改变现有行为是很有挑战性的。在将公司转移到诸如uChat这样的本土工具的同时,需要额外的关注,以灌输uChat比现有的消息平台更可靠的信心。为了建立这种信心,并尽可能无缝地过渡到uChat,我们预先为所有员工提供了帐户,并迁移了近20,000个聊天室,员工不必重新创建或重新加入他们以前用过的任何聊天室。
尽管我们尽了最大努力,但还是有坎坷。随着我们将越来越多的员工集成到uChat上,间歇性中断使得一些早期用户不愿意完全采用该应用程序。为了减轻顾虑,在uChat逐渐稳定并有更多的时间展示自己的同时,我们也保留了旧版聊天应用程序在线。
为了进一步将uChat与员工进行整合,我们提高了透明度。当发现错误时我们就宣布它们、发布修复计划并部署布丁。我们还制作了广泛的监控图表,这样,任何感兴趣的人都可以看到uChat的实时健康状况。
一旦我们能够持续显示uChat的99.9%的可用性,我们将传统聊天系统设为depreciated。我们逐渐禁用房间创建和集成等功能,直到将插件从旧系统中完全剥离出来,从而完成了全面的调整。我们经常公布产品更新、共享使用技巧和整理如常见问题和用户指南等资源,以确保员工得到全方位的支持。我们还开设了一个反馈渠道,员工可以立即获得帮助,也可以建议新的功能。
我们从这次经验中学到的关键一课是,弃用现有聊天应用程序所需的计划和组织调整水平,需要更多的买帐和协调,远远超过我们最初所预期的。但是,通过保持透明、易用和快速的改进,我们与应用程序的早期采用者们建立了良好的关系基础,并随着时间的推移让整个公司得以过渡。
uChat的未来
在接下来的几个月里,我们将实现新的特征,继续检测用户的反馈,并将Mattermost, Inc.公司和开源社区所提供的额外改进整合到产品中。
uChat只是我们团队为促进Uber的协作、沟通和生产力所建立的众多解决方案之一。我们不断开发、部署和维护Uber的内部工具包,每年为公司节省数百万的回收生产力和软件许可费用。如果你对在像Uber这种快速增长的全球性公司里的下一代内部系统感兴趣,请考虑向Uber的员工效率工具团队(Employee Productivity Tools team)申请职位。
关于作者
Marissa Alvarado-Lima是Uber技术服务团队的技术撰稿人,Stanley Chan和Chris Duarte是Uber员工效率工具团队的软件工程师,Ed Wolf是Uber员工效率工具团队的资深产品经理。软件工程师Sameer Patan和Josh Schipper、资深网站可靠性工程师Matt Beard、软件工程经理Benjamin Booth和产品设计师Nayong Park对此文也作出了贡献。
查看英文原文:THE ROAD TO UCHAT: BUILDING UBER’S INTERNAL CHAT SOLUTION
转自 http://www.infoq.com/cn/news/2017/08/UCHAT-way-uber-inset-wechat