热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么Uber微服务架构使用多租户

为什么,uber,微服,务,

云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!


Uber服务的高性能主要依赖于在当前平台上快速以及稳定的开发新特性能力,和对应服务使用什么技术栈无关。Uber平台最根本的能力是基于微服务架构,这是一种常用的结构化风格,也就是由各种互操作的服务组成的应用。

微服务架构可以提供很好的伸缩性,同时也能够支持稳定的部署和模块化。在Uber,不同的工程师团队都是基于互操作的服务来工作,所以确保我们的技术栈既要能够安全的发布新的变动,也要能够基于模块化方式可靠的使用架构的已有部分,这点非常重要。总而言之,这些功能能够提高开发者的开发速度以及快速的发布周转(turnaround)次数,另外还可以给我们提供基于独立调度(schedules)构建的灵活性,同时依然可以满足服务级别协议(SLAs)。

在一个微服务架构中允许多系统共存是利用微服务稳定性以及模块化最有效的方式之一,这种方式一般被称为多租户(multi-tenancy)。租户可以是测试,金丝雀发布,影子系统(shadow systems),甚至服务层或者产品线,使用租户能够保证代码的隔离性并且能够基于流量租户做路由决策。对于传输中的数据(data-in-flight)(例如,消息队列中的请求或者消息)以及静态数据(data-at-rest)(例如,存储或者持久化缓存),租户都能够保证隔离性和公平性,以及基于租户的路由机会。多租户可以帮助我们在一个简单的微服务栈上实现多种功能,比如改进的集成测试框架,影子流量路由,记录和重放流量,为了实验功能做的实时流量的密封重放,容量规划,实际的性能测试,甚至一次运行多个产品线。

综上所述,多租户的好处是利用了一个更灵活和可伸缩的微服务架构,这个架构能够带来更大的生产效能以及改进的应用程序性能,这些会让工程师以及平台用户这类人受益。

微服务架构(landscape)

微服务架构能够让开发团队不依赖于其他服务就可以推出新的功能以及bug修复,这可以增加开发者的开发速度。例如,一个团队拥有四个服务(作为一个整体称为系统1),这些服务具有约定的SLA,这些约定的SLA定期与具有其自己的SLA的多个其他服务交互。

下面的图表1说明了这四个服务,A,B,C和D之间的交互。在这个图表中,服务A从系统2中接收请求。系统1通过连接到服务B来处理请求,而服务B去连接服务C和服务D,最终完成请求处理。

1

图表1。在系统1中,服务A通过连接到服务B来处理系统2的请求,而服务B去连接服务C和服务D,最终完成请求处理

在这个例子中,如果我们对服务B做出改变,我们需要确保它仍然能够和服务A,C,D正常交互。在微服务架构中,我们需要做这些集成测试场景,也就是测试和该系统中其他服务的交互。通常来说,微服务架构有两种基本的集成测试方式:并行测试和生产环境测试。

并行测试

并行测试需要一个和生产环境一样的过渡(staging)环境,并且只是用来处理测试流量。如下图表2所示,这个环境栈一直启动并且运行生产环境代码,但是和生产环境栈是隔离的,并且它的规模要比生产环境要小:

2

图表2。并行测试需要工程师创建一个过渡环境来处理测试流量并且考察生产环境栈最终是否满足SLA

在并行测试中,工程师团队首先完成生产服务的一次变动,然后将变动的代码部署到测试栈。这种方法可以在不影响生产环境的情况下让开发者稳定的测试服务,同时能够在发布前更容易的识别和控制bug。

并行测试需要确保测试流量不能够泄漏到生产环境栈,这个可以通过物理隔离方式给它们分配独立的网络以及确保测试工具仅仅在测试栈中操作。

尽管并行测试是一种非常有效的集成测试方法,但是它也带来了一些可能影响微服务架构成功的挑战:

  • 额外的硬件成本:需要给测试提供整个栈,以及所有的数据存储,消息队列和其他基础组件,这意味着需要额外的硬件和维护成本。
  • 同步问题:测试栈只有在和相应的生产栈保持一致才有作用。当两个栈有偏差时,测试栈对于生产栈的反映(mirror)变得越来越困难,并且对于基础组件来说,要保持两个栈的同步也需要额外的负担。
  • 不可靠性测试:当团队把他们实验性的并且有潜在bug的代码部署到测试栈,这些服务可能无法正常的运行,这就会导致测试失败。例如,拥有服务A的团队执行了并行测试去查看他们的新代码是否正常,但事实由于服务B存在一个bug导致测试失败了。因为我们测试的构建和生产环境的完全不一样,这会让我们很难定位bug;此外,我们只有在测试通过整个流程之后才会知道对于服务A做的变动是否是安全的,这意味着我们需要等待拥有服务B的团队把他们干净的代码部署回测试栈。可以通过使用路由框架将流量路由到另一个沙盒环境(在该沙盒环境中待测试的服务已经启动)来缓解这一特殊缺点。
  • 不精确的负载容量(capacity)测试:为了评估整个栈或者子栈的负载容量,我们需要在测试栈上运行测试负载。如果要测试特定容量,则必须先增加测试栈的容量,然后才能将增量负载(即目标容量相对于当前生产环境负载的增加)施加到测试栈上。此增量负载可能无法使测试栈饱和,这会导致我们不清楚应向生产栈中增加多少容量以实现目标容量。

生产环境测试

微服务架构中的另一种集成测试方法是使生产栈支持多租户并且允许测试流量和生产流量流入。下图3就是这样的一个例子:

3

图表3。利用多租户生产栈,我们可以在运行生产服务的同时测试新增或者更新的微服务。

这种方法很有野心,因为这需要确保栈中的每一个服务要能够处理生产请求以及测试请求。

使用这种方法,我们可以把待测试的服务B在一个隔离的沙盒环境中启动,并且在沙盒环境下可以访问生产服务C和D。我们把测试流量路由到服务B,同时保持生产流量正常流入到生产服务。服务B仅仅处理测试流量而不处理生产流量。另外要确保生产流量不要被测试流量影响。

上面的例子只是一个简化的视角,但是却能够很好的解释多租户怎样解决集成测试的问题。生产中的测试提出了两个基本要求,它们也构成了多租户体系结构的基础:

  • 流量路由:能够基于流入栈中的流量类型做路由。
  • 隔离性:能够可靠的隔离测试和生产中的资源,这样可以保证对于关键业务微服务没有副作用。

这里的隔离要求特别广泛,因为我们希望隔离所有可能的静态数据,包括配置,日志,指标,存储(私有或公共)和消息队列。这种隔离要求不仅仅作用于待测试的服务,对于整个栈也是一样。

除了集成测试意外,多租户也为其他用例铺平了道路,例如分阶段部署以及流量重放。

金丝雀部署

当开发者对他们的服务做了变动,即使这个变动已经被严格的审查和测试,我们也不能够一次就把变动部署到所有运行的服务实例上。这是为了确保在变动有问题或者bug的情况下,整个用户群不会受到攻击。理想的做法是首先将变动应用到一小部分实例上,这被称为金丝雀。然后,我们使用反馈回路监视金丝雀,并逐步应用代码变动到所有服务实例上。

在多租户架构中金丝雀可以被视为另一种租户形式,并且可以把金丝雀作为请求中的一个属性来做路由选择。使用金丝雀的时候,资源在部署中也是隔离的。在任何给定时间,一个服务都有可能部署了金丝雀,并且所有金丝雀流量都会路由给已经部署的金丝雀。可以在靠近架构的边缘基于请求自身的属性来采样金丝雀请求,例如用户类型,产品类型,以及用户位置。

捕获/重放和影子流量

对于所做变动的安全性,一个行之有效的测量方法是在为实际的生产流量服务的同时,能够看到服务费用(service fare)发生怎样的变化。在一个封闭的安全环境中重放之前捕获的实时流量或者重放实时生产流量的一份影子拷贝是另一种多租户的用例。

4

图表4。创建影子流量到测试服务涉及到把生产流量的拷贝路由出生产栈并且路由进一个安全的测试环境。

在这个案例中,我们对被测试实例所有出站调用都添加了响应。捕获和重放生产流量可以被视为集成测试的一个子类别,因为这些用例都属于测试和实验范围。

从技术上说,重放流量是测试流量并且可以是测试租户的一部分,允许和其他租户隔离。通过重放流量,我们可以灵活地分配单独的租户,用来进一步隔离其他测试流量。

因此,多租户体系架构的一个重要功能是其保护和隔离多个关键业务产品线或不同用户群的能力。

面向租户的架构

在面向租户的微服务体系架构中,租户被视为一等对象(first class object)。传输中的数据和静态数据都有租户的概念。做一个多租户微服务架构涉及到给入站请求绑定上下文(context),然后在请求的生命周期内把上线文传递下去,这样可以让用户基于上下文做路由。

租户上下文

由于微服务架构是在互连的网络上运行的一组完全不同的服务,因此我们需要能够将租户上下文附加到执行序列上。当请求进入边缘网关时,我们可以将包含了租户相关信息的上下文附加到请求上。我们希望该上下文的生命周期要和被附加上的请求相同,并能够传播到同一业务逻辑上下文中生成的任何新请求中,从而保留请求序列的租户信息。

下面是一个简单的租户上下文格式和一些案例:

5

上下文传播

通常来说,当调用链中的任何一个服务接收到一个请求时,我们都希望能够获得租户上下文信息,因为这个服务可能会利用租户上下文信息作为业务逻辑的一部分。但是,这就要求服务在处理该请求时并且需要进一步发出其他请求时能够传播上下文。

大部分服务一般都不需要租户上下文信息,但是有一些需要访问请求中的上下文用来避开一些业务逻辑。例如,需要验证用户手机号的审计服务可能需要避开对测试流量的检测,因为测试请求中的用户都是测试用户。另外,当测试流量通过一个事务处理服务,这个服务和银行网关对接用来处理用户的转账业务,我们可以屏蔽这个银行网关或者和银行的测试网关通信(如果有用于测试的网关),这样可以避免真实的转账。租户上下文的传播可以通过开源工具来实现,比如OpenTracing和Jaeger,这些可以使用一种语言并且跨传输层方式来实现分布式上下文传播。

租户上下文也应该可以被传播到其他传输中的数据对象中,比如Kafka消息队列中的消息。 较新版本的Kafka支持添加标头,并且可以使用开源跟踪工具向消息添加上下文。

我们也希望租户上下文能够被传播到静态数据中,包括各个服务用来存储持久化数据的所有数据存储系统,比如MySQL,Apache Cassandra以及AWS。像Redis和Memcached这样的分布式缓存也可以被归类为静态数据。架构中使用的所有存储系统以及缓存都需要支持存储上下文以及一个合理的数据粒度,这样才能够基于租户上下文来对数据进行查询和存储。在一个更高的维度上,静态数据组件要求能够基于租户信息来对数据和流量进行隔离。

究竟如何隔离数据以及如何将租户上下文与数据一起存储,这些实现细节都和特定存储系统有关。

基于租户的路由

一旦我们能够给请求附上租户信息,我们就可以基于它的租户信息做路由。这种路由对于生产,记录/重放以及影子流量的测试很重要。当然,金丝雀部署也需要把金丝雀请求路由到运行在隔离环境下的特定服务实例。

在确定无缝运行且无开销的路由解决方案时,考虑部署和服务技术当栈非常重要。当选择一个通用的路由方案时,服务编写的语言以及他们之间互相通信的传输和编码也需要考虑。像Envoy或者Istio开源服务网格(Service Mesh)工具也非常适合提供基于租户的路由功能,并且该路由和服务语言以及所使用的传输或编码无关。

通常,可以在服务的出口或入口实现基于租户的路由。在出口处,服务发现层可以根据请求的租户信息决定和什么服务通信。另一种方法是在入口处做路由判断,然后请求被重新路由到正确的实例,如下图5所示:

6

图5。我们可以在入口处做路由判断,上面的例子是从生产环境服务Ap发送测试流量到测试实例A1。

在图5例子中,可以使用一个边车(sidecar)来转发一个测试请求到测试实例上。边车可以是一个代理进程,它负责代理所有进入该服务的流量,并且和服务部署在一起。流量先是被服务边车接收到,然后边车检测请求的租户上下文,接着基于上下文做出路由决策。

基于我们想要的用例,我们可以在租户上下文中增加额外的元数据。例如,对于生产中的测试,我们想把测试流量重定向到一个服务的测试实例上。我们可以在上下文中增加额外的信息,这个可以允许以下的行为发生:

7

当做路由决策时,我们可以检测请求的租户信息是否是测试的以及请求的接收者是否是处于测试下。如果这些请求都满足,我们可以路由该请求到这个<测试实例ID>。

数据隔离

我们想去构建一个架构,在这个架构中每一个基础组件都能够理解租户信息,并且能够基于租户路由隔离流量,同时在我们的平台中允许对运行不同的微服务有更多的控制,比如指标和日志。在微服务架构中典型的基础组件是日志,指标,存储,消息队列,缓存以及配置。基于租户信息隔离数据需要分别处理基础组件。例如,我们可以生成租户信息,然后将其作为服务生成的所有日志和指标的一部分。这个可以帮助开发者基于租户信息做过滤,同时也可能有助于避免错误警报或防止启发式或训练数据出现偏差。

同样的,当考虑存储服务时,底层的存储架构需要考虑能够有效的在租户之间创建隔离。一些存储架构很容易实现多租户。两种高级方法是将租户概念(notion)显式地嵌入到数据旁边,并将不同的租户信息和数据共同放置,或者根据租户信息显式地分离数据,如下图6所示:

8

图6。使用租户信息路由数据和消息队列测试流量到处于测试下的不同组件,这样可以隔离该测试流量,因此不会干扰生产系统。

后一种方法提供了更好的隔离保证,而前一种方法通常需要较少的操作开销。对于像Kafka这种消息队列系统,我们可以给租户推出一个新的主题或者分配一个单独的Kafka集群。

对于数据隔离,上下文需要能够被传播到基础组件。确保服务在数据隔离方面的开销最小,这一点很重要。理想的情况下,我们希望服务不需要显示的处理租户信息。另外,我们也希望将隔离逻辑放置在所有数据流经的中央扼流点。网关就是其中一种可以实现隔离逻辑的扼流点,它是我们的首选方法。客户端库可以是实现基于租户隔离的另一种方法,尽管编码语言的多样性使在所有特定语言的客户端库之间保持逻辑同步变得有点困难。

同样的,对于配置隔离,我们希望对于特定租户下的服务配置是互相独立的,因此确保对于一个租户配置的变动不会影响到其他租户的配置。

展望未来

基于微服务的体系结构仍在发展,并已成为开发人员和整个组织的敏捷性工具促进者(facilitators)。 精心计划的多租户架构可以提高开发人员的生产力并支持不断发展的业务线。

Uber的多租户实施带来了各种好处,例如使代码和配置的自动发布更安全,从而提高了开发人员的速度。 多租户架构的隔离保证使Uber可以出于各种目的(包括测试流量)重新利用同一微服务栈。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-05-12
本文作者:王欢
本文来自:“dockone”,了解相关信息可以关注“dockone”


推荐阅读
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • ZooKeeper 学习
    前言相信大家对ZooKeeper应该不算陌生。但是你真的了解ZooKeeper是个什么东西吗?如果别人面试官让你给他讲讲ZooKeeper是个什么东西, ... [详细]
  • 一面自我介绍对象相等的判断,equals方法实现。可以简单描述挫折,并说明自己如何克服,最终有哪些收获。职业规划表明自己决心,首先自己不准备继续求学了,必须招工作了。希望去哪 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了在RHEL 7中的系统日志管理和网络管理。系统日志管理包括rsyslog和systemd-journal两种日志服务,分别介绍了它们的特点、配置文件和日志查询方式。网络管理主要介绍了使用nmcli命令查看和配置网络接口的方法,包括查看网卡信息、添加、修改和删除配置文件等操作。 ... [详细]
  • ElasticSerach初探第一篇认识ES+环境搭建+简单MySQL数据同步+SpringBoot整合ES
    一、认识ElasticSearch是一个基于Lucene的开源搜索引擎,通过简单的RESTfulAPI来隐藏Lucene的复杂性。全文搜索,分析系统&# ... [详细]
  • “您可以从三个选项中(快速、便宜或好)选择两个”提出这个问题的人可能不是可观测性工程师。但也可能是,在可观测性方面,决定您 ... [详细]
  • zuul 路由不生效_Zuul网关到底有何牛逼之处?竟然这么多人在用~
    作者:kosamino来源:cnblogs.comjing99p11696192.html哈喽,各位新来的小伙伴们,大家好& ... [详细]
  • Linux线程的同步和互斥
    目录1、线程的互斥2、可重入VS线程安全3、线程的同步1、线程的互斥 ... [详细]
  • AstridDAO 专访:波卡稳定币黑马 BAI
    加入Pol ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了VoLTE端到端业务详解|VoLTE用户注册流程相关的知识,希望对你有一定的参考价值。书籍来源:艾怀丽 ... [详细]
  • 科技感英文字体_软件用的很6,理论也掌握了,就差搞懂字体了?
    字体是视觉设计中最重要的传达元素之一,字体本身的视觉特性和品质影响着信息传递的质量,英文字体有自己非常完善的系统,如果要精通则需要从字体的 ... [详细]
author-avatar
林大雨00
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有