uber改造整体单一式代码库后的微服务架构实践 -买球官网平台

引用

原文:
作者: emily reinhold,uber的工程师
翻译:孙薇
责编:钱曙光,关注架构和算法领域,寻求报道或者投稿请发邮件[email protected],另有「csdn 高级架构师群」,内有诸多知名互联网公司的大牛架构师,欢迎架构师加微信qshuguang2008申请入群,备注姓名 公司 职位。

几个月前,我们讨论到 uber 决定将原有的整体单一式代码库更换成模块化、更具灵活性的微服务架构。从那时起,uber 有许多工程师投入了数千小时,改造拓展 uber 微服务的生态环境。新的架构使用了多种语言以及很多不同的框架结构,鉴于重构任务非常庞大,我们也利用此机会在 uber 使用了一套新的微服务构建技术。借助适合 soa 迁移的技术堆栈及标准,我们改进了在 uber 开发服务的方式。

开始一项新服务
在一家快速成长的工程类公司,想要追踪所有进行中的任务是非常困难的,需要有相应的方法,才能避免各团队工作重复。在 uber,我们通过要求新服务的编写者提交 rfc(request for comments) 来解决这个问题。rfc 是一份关于新服务的详细议案,其中需要列出新服务的目的、架构、依赖与其他执行细节,让 uber 工程部门的其他员工一并参与讨论。

提交 rfc 有两个目的:
1.为即将开发的服务征集反馈,以提高服务质量;
2.避免工作重复,或者提供合作机会。

其他一些熟悉该领域的工程师会审阅这份服务设计稿,一旦将反馈融入到服务议案中,我们就可以开始快乐地投入新服务的构建了。



无论你在什么地方,都可以点击按钮随时叫车,tincup会为你确保自动使用当前所在国的货币单位支付车费。

通过新技术来引导微服务
构建 tincup 需要重构所有与货币和汇率相关的逻辑,这正好为我们提供了机会,重新评估 uber 一些很久之前所做的设计决策。我们使用了一些新的框架、协议和约定来执行 tincup。

mvcs

首先,我们搞定了货币与汇率相关的整体代码结构。近几年,我们修改了 uber 很多数据集的持久层(点击查看样例),由于所有变化都是长期而繁琐的,从这个过程中我们学到:如果可能的话,最好将持久层规范从应用逻辑中分离出来。这样就形成了我们所谓的 mvcs 应用开发方法:扩大常见的 mvc 方法,将应用逻辑所在的服务层也包括在内。通过隔离服务层中的应用逻辑以及应用的其他部分,就能在无需重构业务逻辑的情况下,修改或替换持久层的内容——只需改动直接与存储/读取相关的那部分代码。

udr

其次,我们考虑了货币与汇率的持久层。在使用 tincup 之前,这些数据存储在postgresql 关系数据库中,以增量整数 id 为标记。然而这种数据存储方法无法支持 uber 数据中心在全球范围内执行数据复制,无法匹配我们的 all-active(所有数据中心同时提供行程服务)工作架构。由于访问货币和汇率时,需要涉及所有的数据中心,我们换掉了持久层,用 udr(uber 的全球复制可扩展数据库)来代替。

预测微服务成长中的问题
在决定对货币及汇率作出设计改动后,我们解决了随着工程生态环境中的微服务数量增长而自然出现的新问题。

tornado

网络吞吐堵塞是非常严重的问题,可能会导致 uwsgi 的 worker 无事可做,如果类似 tincup 的所有服务请求都是同步的,某个服务出现问题会导致连锁反应,并影响所有调用者。我们决定采用 tornado,这是一个基于 event-loop 的 python 异步框架,目的是为了防止出现阻塞。由于我们从 flask 整体单一式数据库中剥离了大量的代码,选择使大多现有应用逻辑保持不变的异步框架让风险降到最低,对我们来说非常重要。tornado 符合这一需求,因为它允许同步查看代码,但不会堵塞输入/输出。另外还有个替代方案:为了解决上述的吞吐问题,很多服务提供者都在使用新语言 go。

tchannel

曾经对单独一个api的调用,现在可能扇出成大量对微服务的调用。为了促进在大型生态系统中发现其他服务,并找出故障点,uber 的微服务在 hyperbahn 上使用了开源的 tchannel ,这是一个 rpc 内部开发的网络多路复用和框架协议。tchannel 为客户端和服务器提供协议,hyperbahn 的智能路由网将这两者连接起来。这样一来,微服务中产生的几个核心问题都得以解决:

服务的发现:所有生产者和使用者都注册到了路由网上,使用者可以通过名称来访问生产者,而无需知道主机或端口名。

容错问题:路由网络追踪类似故障率和sla违反之类的指标,它可以检测到出现问题的主机,将其从可用的主机池中移除出去。

速率限制与断路器:这些功能可以确保在请求出错的情况下,或者从客户端发回的响应速度过慢的时候,不会造成级联故障。

thrift

由于所调用服务的数量增长迅猛,很有必要为每个调用维护一个定义良好的接口。由于想用 idl 来管理这个接口,最终我们决定了使用 thrift。thrift 强制服务所有者发布严格的接口定义,从而简化了服务的合成过程。不遵守接口定义的调用在 thrift 层面上就被拒绝了。对接口公开声明的策略也强调了向后兼容的重要性,因为某个服务thrift 接口的多个版本可能会在指定时间内同时使用。服务编写者绝对不能对接口定义作出重大修改,只能添加一些影响不大的内容,直到消费者不再使用为止。

为生产环境的服务联合做好准备
最终,在 tincup 的实现阶段几近完成时,我们使用了一些有用的工具为生产环境做准备:

hailstorm

首先,我们知道 uber 的流量在每天、每周以及每年的时间中都是变化的,在我们预测的时间——比如新年年夜及万圣节时会出现流量高峰,因此我们必须在发布前确保这些服务能够处理这些增额负载。按照规定,每当在 uber 发布新服务的时候,我们会使用内部构建的 hailstorm 服务来加载并测试 tincup 的端点,确定缺陷以及在压力下出现断点的地方。

ucontainer

下一步我们考虑到了 uber 工程部的另一个主要目标:更高效地使用硬件。由于 tincup 是很轻量级的服务,可以很容易地与其他微服务共享机器,分享就是关爱不是吗?当然也并非总是如此:我们还想确保每项服务都能独立运行,不会影响在同一台机器上所运行的其他服务。为了避免这种问题出现,我们使用 ucontainer(uber 的 docker)来执行资源隔离与限制的任务。ucontainer “人”如其名,借助 linux 的容器性能以及 docker 来容器化 uber 的服务。它会将某个服务打包到某个隔离的环境中,以确保无论在同一台主机上还有什么其他进程运行,这项服务都能持续运行。ucontainer 在 docker 的基础上添加了:1. 更灵活的构建功能;2. docker 容器可见度更高的工具。

udestroy

最后,为了迎接在生产环境中不可避免会出现的宕机及网络连接的问题,我们使用了一个内部工具udestroy,以测试在我们控制的混乱下服务的表现——通过模拟宕机的情况,来观察系统的弹性。在定期、有目的地破坏系统的过程中,我们可以发现漏洞并不断努力提高系统的耐久性。

实现完成后的心得
通过构建tincup来,我们学到了一些经验:
  • 用户迁移是一项长期、缓慢的过程,因此尽可能将其简单化。提供代码实例,预测迁移完成的时间。
  • 我们了解到:技术堆栈最好存在于小的服务中,tincup 的应用逻辑非常简单,因此开发者得以集中精力来研究新的技术堆栈,而不需要将精力浪费在业务逻辑的迁移细节上。
  • 一开始先开发通用单元并执行集成测试,如果是在开发环境中,使用代码来debug要容易得多(压力也更小)。
  • 尽可能提早、频繁地执行负载测试,没有什么能比在花了数周或数月时间执行实现,却发现系统无法应付峰值流量更糟糕了。

uber的微服务
uber 迁移到 soa 的过程为许多服务的拥有者,甚至是行业经验贫乏的人展示了机会。开发并拥有一项服务是很大的责任,不过 uber 开放性的知识共享文化使得选择一套新技术以及拥有代码库都成为了让人收获颇丰的珍贵体验。
  • 大小: 162.9 kb
1
1
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java程序猿阿谷:面试字节跳动三轮凉凉,内推4面终拿下抖音offer(java后台研发)​zhuanlan.zhihu.com一、前言测试所使用的环境测试使用的环境是企业主流的ssm 框架即 springmvc spring mybatis。为了节省时间,我直接使用的是我上次的“ssm项目中整合echarts开发”该项目已经搭建完成的ssm环境。标题说的四种姿势指的是哪四种姿势?发送text格式...

  • 读取xml 发送网页版邮件2014-05-170dataset ds = new dataset();ds.readif (ds.tables.count > 0){datatable dt = ds.tables[0];if (dt.rows.count > 0){body = dt.rows[0]["content"].tostring();}}body = body.replac...

  • java常见应用——发送邮件,xml-dom解析 一.发送邮件 1.发送普通邮件 package com.nike.app.javamail; import javax.mail.*; import javax.mail.internet.internetaddress; import javax.mail.internet.mimemessage; import java.util.date;...

  • 文章目录一、说明1.1 项目结构说明1.2 依赖说明二、spring email2.1 邮件发送配置2.2 新建邮件发送基本类2.3 邮件发送的测试 源码gitub地址:https://github.com/heibaiying/spring-samples-for-all 一、说明 1.1 项目结构说明 邮件发送配置文件为springapplication.xml; 简单邮件发送、附件邮件发送...

  • (点击上方的蓝色文字,可快速关注买球官网平台)几个月前,我们讨论到uber 决定将原有的整体单一式代码库更换成模块化、更具灵活性的微服务架构。从那时起,uber 有许多工程师投...

  • 在微服务架构下,人们用单一的整体代码库换取了黑盒,黑盒的功能随时可能发生变化,很容易造成意外情况。 例如,工程师们不得不通过12个不同团队大约50个服务来调查问题的根本原因。 理解服务之间的依赖关系可能会变...

  • 仅仅几年前,由于许多人宣传微服务架构的好处,例如独立部署形式的灵活性,明确的所有权,系统稳定性的改进以及更好的关注点分离,很多人很快采用了微服务架构,近年来人们开始谴责微服务会大大增加其复杂性。...

  • 前言近来,一些关于面向服务架构的话题,特别是针对微服务架构的弊端这个话题上进行了大量的讨论。虽然在几年前,微服务架构受到很多人的青睐,因为它们提供了许多好处,如独立部署的灵活性、明确的所有...

  •  发送邮件是web应用系统的一个基本功能。一般来说,邮件都有特定的类型,比如说密码提醒,欢迎信息,订单确认或者收信确认。尽管不同应用邮件的内容各不相同,但是发送邮件的过程基本上是一样的。 构建消息,发送给邮件服务器,发送。   当使用java开发的时候,我们常常使用javamail api 来连接邮件服务器发送邮件。但是这种方式过于笨重(主要...

  • 内表拼成xml文件,以excel形式作为邮件附件发送 详细代码

  • classpathref="xslt.classpath"               force="true"               in="${jmeter.result.jtlname}"               out="${jmeter.result.htmlname}"               style="${jmeter.home}/extras/jmeter

  • 为什么选择微服务架构? 微服务架构的10个核心优势 总结为什么选择微服务架构? 微服务架构的10个核心优势 总结为什么选择微服务架构? 微服务架构的10个核心优势 总结为什么选择微服务架构? 微服务架构的10个核心优势 ...

  •  【编者的话】本文来自nginx官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战。正如作者所说,微服务架构更适合用于构建复杂的应用,尽管它也有自己的不足。 ...

  • 微服务在当下引起广泛关注,成为文章、博客、社交媒体讨论和大会演讲的热点;...然而,无论是追捧还是质疑,微服务架构拥有巨大优势,尤其是它让敏捷开发和复杂的企业应用交付成为可能。 本系列...

  • 前言近来,一些关于面向服务架构的话题,特别是针对微服务架构的弊端这个话题上进行了大量的讨论。虽然在几年前,微服务架构受到很多人的青睐,因为它们提供了许多好处,如独立部署的灵活性、明确的所...

  • 随着微服务架构的持续火热,网络上针对微服务和单体架构的讨论也是越来越多。去年的时候,社区更多的关注点是在二者的区别...毋庸置疑,微服务的理念正在席卷整个开发者社区,像netflix、uber这样的公司都是非常成

global site tag (gtag.js) - google analytics