我们的服务彼此交互,还与移动设备进行交互,而那些交互对业务状况(比如动态定价)和内部使用(比如调试)来说都很重要。就日志而言,我们使用了多个Kafka集群,数据被归档到Hadoop及/或文件存储Web服务中,然后将数据从Kafka弃用。这些数据还被各个服务实时获取,并索引到ELK堆栈,用于搜索和可视化(ELK代表Elasticsearch、Logstash和Kibana)。
应用程序配置
我们使用Mesos上的Docker容器,借助一致的配置来运行微服务,具有可扩展性,并借助Aurora来处理长时间运行的服务和计划任务。我们的其中一个基础设施团队:Application Platform构建了一个模板库,把服务做入到可交付的Docker镜像中。
路由和服务发现
我们的面向服务架构(SOA)使得服务发现和路由对Uber的成功而言至关重要。在我们的复杂网络中,服务必须能够彼此联系。我们结合使用HAProxy和Hyperbahn来解决这个问题。Hyperbahn是Uber开发的一系列开源软件的一部分:Ringpop、TChannel和Hyperbahn都肩负一个共同的使命,为服务网络增添自动化、智能和性能。
遗留服务使用本地HAProxy实例,通过HTTP请求将JSON路由到其他服务,而前端Web服务器NGINX为后端服务器充当代理。有了这种可靠成熟的数据传输方式,故障排除起来就很容易,这在去年几次迁移到刚开发的系统的过程中显得至关重要。
然而,我们更注重长期可靠性而不是可调试性。替代HTTP的非传统协议(如SPDY、HTTP/2和TChannel)以及像Thrift和Protobuf这些接口定义语言将有助于从速度和可靠性方面改进我们的系统。Ringpop是一致的散列层,它为应用程序层面带来了合作和自愈合。Hyperbahn让服务能够简单而可靠地找到其他服务,并与之联系,即便服务是由Mesos动态调度的。
不是采用过时的轮询方式来查看是否发生了变化,我们改用一种发布-订阅模式(向订户发布更新内容)。HTTP/2和SPDY更容易支持这种推送模式。改用推送模式后,Uber应用程序中几项基于轮询的功能会出现速度大幅提升。
开发和部署
Phabricator支持大量的内部操作,从代码审查、文档编制到过程自动化,不一而足。我们使用OpenGrok这种源代码搜索和相互参照引擎来搜寻代码。至于Uber的开源项目,我们使用GitHub从事开源开发,用于问题跟踪和代码审查。
Uber工程部门竭力让开发环境尽可能酷似生产环境,于是我们主要在云提供商或开发人员的笔记本电脑上运行的虚拟机上从事开发。我们构建了自己的内部部署系统来管理代码构建。Jenkins负责持续集成工作。我们结合了Packer、Vagrant、Boto和Unison,开发用于在虚拟机上构建、管理和开发的工具。我们在开发过程中使用Clusto用于库存管理。Puppet负责管理系统配置。
我们不断努力构建和维护稳定的沟通渠道,不仅仅为了我们的服务,还为了我们的工程师。至于信息发现,我们构建了uBlame(向git-blame致意),跟踪哪些团队拥有某一项服务,并构建了Whober用于查找姓名、面部、联系信息和组织结构。我们使用一个内部的文档编制网站,使用Sphinx,自动从软件库来构建文档。一项企业提醒服务提醒我们随叫随到的工程师,确保系统正常运行。大多数开发人员在其笔记本电脑上运行OS X,我们的大多数生产实例通过运行Debian Jessie来运行Linux。
语言
在较低层面,Uber的工程师主要用Python、Node.js、Go和Java来编写程序。我们最开始使用两种主要的语言:Node.js供市场团队使用,Python供其他所有人使用。如今这些第一语言仍用于在Uber运行的大多数服务。
由于高性能的原因,我们采用了Go和Java。我们为这些语言提供了一流的支持。Java充分利用了开源生态系统,并与外部技术整合起来,比如Hadoop及其他分析工具。Go为我们提供了效率、简单性和运行速度。
我们将原来的代码库分解成微服务时,丢弃并更换了旧的Python代码。异步编程模型为我们提供了更好的吞吐量。我们使用Tornado和Python,但Go直接支持并发的功能非常适合大多数新的注重性能的服务。
必要时,我们用C和C++来编写工具(比如在系统层面开发高效率、快速度代码)。我们使用由那些语言编写的软件,比如HAProxy,但在大多数情况下,我们在实际工作中不用这些语言。
当然了,那些在架构顶层工作的系统是用Java、Go、Python和Node之外的语言编写的。
测试
为了确保我们的服务能够满足生产环境的需求,我们开发了两款内部工具:Hailstorm和uDestroy。Hailstorm驱动集成测试,并在非高峰时段模拟峰值负荷,而uDestroy有意起到了破坏作用,那样我们就能更擅长处理意外故障。
我们的员工使用应用程序的测试版,在发送到用户之前不断测试开发的新品。我们做了一个应用程序反馈报告工具,在部署到用户之前揪出任何代码错误。每当我们在Uber应用程序中拍取屏幕截图,这项功能就会提示我们在Phabricator中提交错误修复任务。
可靠性
编写后端服务的工程师负责服务运营。如果他们编写的一段代码在生产环境中出现故障,就会得到提醒。我们使用Nagios警报机制来进行监控,与一套警报系统结合起来,用于通知。
力求获得最佳可用性和每天处理10亿次打车服务,网站可靠性工程师专注于获得成功所需的服务。
2016年2月的一场技术讨论会介绍了Uber网站可靠性工程的历史。
可观察性
可观察性意味着确保Uber整体以及不同部分都顺利运行。一套系统主要由我们的纽约办事处开发,它们为Uber工程部门充当遍布全球各地的眼睛、耳朵和免疫系统。
遥测
我们用Go开发了M3,收集并存储来自Uber工程部门每一个部分(每台服务器、主机服务和每段代码)的度量指标。
我们收集数据后寻找趋势。我们通过修改Grafana(https://github.com/grafana/grafana)来构建仪表板和图形,以便更直观地将信息置于上下文来研究。每个查看仪表板的工程师往往关注某个集团或地区的数据、一组试验方面的数据,或者是与某个产品有关的数据。我们为Grafana添加了数据交叉分析功能。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有