我们对微服务的了解

你好 我叫Vadim Madison,负责系统平台Avito的开发。 关于我们公司如何从单一架构转换为微服务架构,已经不止一次地被提及。 现在该分享一下我们如何改造基础架构,以充分利用微服务而不让自己迷失其中。 PaaS如何在这里为我们提供帮助,如何简化部署并将微服务的创建减少到一键式操作-请继续阅读。 并非我在下面编写的所有内容都已在Avito中完全实现,部分是我们开发平台的方式。


(在本文的最后,我将讨论由微服务架构专家Chris Richardson参加为期三天的研讨会的机会)。



我们如何来到微服务


Avito是世界上最大的分类广告之一,每天发布超过1500万个新广告。 我们的后端每秒接受超过2万个请求。 现在我们有数百种微服务。


我们已经建立微服务架构几年了。 确切地说,我们的同事在RIT ++ 2017的部分中进行了详细发言 。在CodeFest 2017(请参见视频 )上,Sergey Orlov和Mikhail Prokopchuk详细解释了为什么我们需要过渡到微服务,以及Kubernetes在这里扮演了什么角色。 好吧,现在我们正在尽一切努力使这种体系结构固有的扩展成本最小化。


最初,我们没有建立一个可以全面帮助我们开发和推出微服务的生态系统。 他们只是收集了明智的开源解决方案,在家里启动了它们,并建议开发人员对其进行处理。 结果,他去了十几个地方(仪表板,内部服务),此后,他变得更加坚强,渴望以一种整体的方式削减旧代码。 下图上的绿色表示开发人员用自己的双手进行的另一种方式,黄色表示自动化。



现在,在PaaS CLI实用程序中,一个团队创建了一个新服务,另外两个团队添加了一个新数据库并部署到Stage。



如何克服“微服务碎片化”时代


使用单片式架构,为了保持产品更改的一致性,开发人员被迫弄清邻居的情况。 使用新架构时,服务上下文不再相互依赖。


另外,为了使微服务架构有效,需要建立许多过程,即:


•日志记录;
•查询跟踪(Jaeger);
•错误汇总(Sentry);
•Kubernetes的状态,消息,事件(事件流处理);
•竞赛极限/断路器(可以使用Hystrix);
•控制服务连接(我们使用Netramesh);
•监测(格拉法纳);
•集会(TeamCity);
•通讯和通知(松弛,电子邮件);
•任务跟踪; (吉拉)
•编制文件。


为了在系统扩展时不会丢失其完整性并保持有效,我们重新考虑了Avito中微服务的工作组织。


我们如何处理微服务


在众多微服务中执行统一的“聚会政策”有助于Avito:


  • 基础设施分为几层;
  • 平台即服务(PaaS)概念;
  • 监视微服务发生的一切。

基础结构抽象层包括三层。 让我们从顶部到底部。


A.上层服务网。 最初,我们尝试了Istio,但事实证明它使用了太多资源,这在我们的卷上太昂贵了。 因此,架构团队的高级工程师Alexander Lukyanchenko开发了自己的解决方案-Netramesh (可在开放源代码中使用),我们现在在生产中使用该解决方案,它消耗的资源比Istio少几倍(但不能完成Istio所拥有的一切)。
B.中等-Kubernetes。 我们在其上部署和运营微服务。
C.下部-裸机。 我们不使用云和诸如OpenStack之类的东西,而是完全坐在裸机上。


PaaS将所有层组合在一起。 而这个平台又由三部分组成。


I.通过CLI实用程序控制的生成器。 是她帮助开发人员以正确的方式并以最小的努力来创建微服务。


二。 通过公共仪表板将收集器与所有工具的控制结合在一起。


三, 仓库 。 它会干扰计划者,后者会自动为重大操作设置触发器。 有了这样的系统,就不会因为有人忘记将任务放在Jira中而错过任何一项任务。 为此,我们使用一个称为Atlas的内部工具。



Avito中微服务的实现也根据单一方案执行,从而简化了在开发和发布的每个阶段对其的控制。


标准微服务开发管道如何工作


一般而言,微服务创建链如下:


CLI推送→连续集成→烘烤→部署→人工测试→Canary测试→压缩测试→生产→服务。


我们完全按照此顺序进行操作。


CLI推


•创建微服务
我们苦苦挣扎了很长时间,教每个开发人员如何制作微服务。 包括在Confluence中写的详细说明。 但是,这些计划进行了更改和补充。 底线-在旅程的开始就形成了一个瓶颈:启动微服务所花的时间比允许的多得多,而在创建微服务时,仍然经常出现问题。


最后,我们构建了一个简单的CLI实用程序,该实用程序可以自动创建微服务时的基本步骤。 实际上,它代替了第一个git push。 她就是这样做的。


-根据模板在“向导”模式下逐步创建服务。 我们在Avito后端提供了主要编程语言的模板:PHP,Golang和Python。


-只需一条命令,即可在特定机器上部署环境以进行本地开发-Minikube出现,Helm图表自动生成并在本地kubernetes中运行。


-连接所需的数据库。 开发人员无需知道IP,登录名和密码即可访问他所需的数据库-至少在本地,至少在Stage中,至少在生产中。 此外,该数据库可立即以容错配置并平衡地部署。


-它本身执行实时汇编。 假设开发人员通过其IDE在微服务中修复了某些内容。 该实用程序将查看文件系统中的更改,并基于这些更改重新组装应用程序(对于Golang)并重新启动。 对于PHP,我们只需在多维数据集内转发目录,即可“自动”获得live-reload。


-生成自动测试。 以碟片的形式,但相当适合使用。


•部署微服务


以前部署微服务有点沉闷。 必填项:


I.Dockerfile


二。 配置
三, Helm图表,它本身很庞大,包括:


-图表本身;
-模板;
-考虑不同环境的特定值。


我们摆脱了重做Kubernetes清单的痛苦,现在它们是自动生成的。 但最重要的是,它们将部署简化到了极限。 从现在开始,我们有了一个Dockerfile,开发人员将整个配置写入一个简短的app.toml文件中。



是的,并且在app.toml本身现在只需一分钟。 我们记下要提高多少服务副本(在开发服务器上,在登台上,在生产上)指示其依赖关系。 注意[engine]块中的行大小=“ small”。 这是将通过Kubernetes分配给服务的限制。


进一步基于该配置,将自动生成所有必需的Helm图表,并创建与数据库的连接。


•基本验证。 这样的检查也是自动的。
需要跟踪:
-是否有一个Dockerfile;
-是否有app.toml;
-是否有文件;
-依存关系是否有序;
-是设置警报的规则。
到最后一点:服务所有者自己指示要监视的产品指标。


•准备文件。
还是一个有问题的地方。 这似乎是最明显的,但同时也是破纪录的“经常被遗忘”的记录,因此也是链条中脆弱的一环。
该文档必须在每个微服务下。 其中包含以下块。


I.服务的简要说明 。 关于他的工作和需要做什么的几句话。


二。 链接到架构图 。 快速浏览它很容易理解,这一点很重要,例如,您是使用Redis进行缓存还是在持久模式下用作主要数据存储。 到目前为止,在Avito中,这是Confluence的链接。


三, Runbook 。 启动服务的简短指南以及处理它的复杂性。


IV。 常见问题解答 ,可以很好地预测您的同事在使用该服务时可能遇到的问题。


V. API端点的描述 。 如果您突然没有指明目的地,几乎可以肯定会得到与您的微服务有关的同事的薪水。 现在,我们为此使用Swagger,我们的解决方案称为brief。


VI。 标签 或显示服务所属公司的产品,功能,结构部门的标记。 例如,如果您没有看到同事一周前针对同一业务部门推出的功能,它们将帮助您快速了解。


七。 服务的所有者 。 在大多数情况下,可以使用PaaS自动确定一个或多个,但是对于保险,我们要求开发人员手动指定。


最后,与代码审查类似,审查文档是一个好习惯。


持续整合


  • 准备存储库。
  • 在TeamCity中创建管道。
  • 设置权限。
  • 搜索服务所有者。 有一种混合方案-手动标记和PaaS的最小自动化。 全自动方案无法将支持服务转移给另一个开发团队,或者例如,如果服务开发人员退出了。
  • 在Atlas中进行服务注册 (请参见上文)。 及其所有所有者和依赖项。
  • 检查迁移。 我们检查其中是否有任何潜在的危险。 例如,在其中一个中,弹出一个alter table或其他可能破坏数据在不同版本的服务之间的兼容性的操作。 然后,不执行迁移,而是进行订阅-PaaS应在安全使用服务时向服务的所有者发出信号。


下一步是在部署之前打包服务。


  • 生成应用程序。 根据经典-在Docker映像中。
  • 为服务本身和相关资源生成Helm图表。 包括用于数据库和缓存。 它们是根据CLI推送阶段生成的app.toml配置自动创建的。
  • 为管理员创建票证以打开端口 (必要时)。
  • 单元测试运行和代码覆盖率计算 。 如果代码覆盖率低于给定的阈值,则很可能该服务将进一步失败-部署。 如果濒临允许,则将为服务分配一个“悲观”系数:然后,如果指标随着时间的推移没有改进,则开发人员将收到通知,说明测试没有任何进展(需要做一些事情)。
  • 考虑内存和CPU限制 。 我们主要在Golang中编写微服务,并在Kubernetes中运行它们。 从这里开始,有一种与Golang语言的特殊性有关的微妙之处:默认情况下,计算机上的所有内核都在启动时使用,如果您未显式设置GOMAXPROCS变量,并且当在同一台计算机上启动多个此类服务时,它们开始争夺资源,互相干扰。 下图显示了如果在没有竞争的情况下和在资源竞争中运行应用程序,运行时将如何变化。 (图的来源在这里 )。


交货时间越短越好。 最大值:643毫秒;最小值:42毫秒。 该照片是可单击的。



手术时间越少越好。 最大值:14091 ns,最小值:151 ns。 该照片是可单击的。


在准备程序集的阶段,您可以显式设置此变量,也可以使用Uber家伙提供的automaxprocs库。


部署


•约定验证。 在开始将服务程序集交付到预期的环境之前,需要检查以下内容:
-API端点。
-符合API响应端点方案。
-日志格式。
-设置服务请求标头(netramesh现在正在这样做)
-在向总线(事件总线)发送消息时设置所有者令牌。 这对于通过总线跟踪服务的连接性是必需的。 您可以将幂等数据发送到不增加服务连接性的总线(这是很好的),以及可以增强服务连接性的业务数据(这是非常糟糕的!)。 当这种连通性成为问题时,了解谁编写和读取总线有助于正确划分服务。


虽然Avito中的约定不多,但是它们的库正在扩大。 这种协议以易于理解和方便的命令形式出现的越多,维护微服务之间的一致性就越容易。


综合测试


•闭环测试。 对于他来说,我们现在正在使用开源Hoverfly.io 。 首先,它记录服务上的实际负载,然后(仅在一个闭环中)进行仿真。


•负载测试。 我们尝试使所有服务达到最佳性能。 每个服务的所有版本都应进行压力测试-这样我们就可以了解该服务的当前性能以及与同一服务的先前版本的区别。 如果服务更新后其性能下降了一半半,这对于其所有者来说是一个明确的信号:您需要深入研究代码并解决问题。
例如,我们以收集到的数据为基础,以便正确实现自动缩放,最后,我们通常会了解服务的可伸缩性。


在压力测试期间,我们检查资源消耗是否符合设定的限制。 我们主要关注极端情况。


a)我们查看总负载。
-太小-如果负载突然下降几次,很可能根本无法工作。
-太大-需要优化。


b)我们看一下RPS的临界值。
这里我们看一下当前版本与前一个版本之间的差异以及总数。 例如,如果一项服务产生了100 rps,那么它要么写得不好,要么是它的特殊性,但是无论如何,这都是一个非常仔细地观察服务的机会。
相反,如果RPS过多,则可能是某种错误和某些端点停止执行有效负载,但是触发了某种return true;


金丝雀测试


通过综合测试后,我们将在少量用户上运行微服务。 我们从精心的服务入手,服务的预期受众中只有一小部分-不到0.1%。 在此阶段,在监控中建立正确的技术和产品指标非常重要,这样它们才能尽快在服务中显示问题。 金丝雀测试的最短时间为5分钟,主要时间为2小时。 对于复杂的服务,我们将时间设置为手动模式。
我们分析:
-特定于语言的指标,尤其是php-fpm工作者;
-哨兵中的错误;
-回应情况;
-响应时间(响应时间),准确且平均;
-延迟;
-处理和未处理的异常;
-食物指标。


挤压测试


挤压测试也称为挤压测试。 该技术的名称是在Netflix中引入的。 其本质是,首先我们用实际流量填充一个实例到故障状态,然后设置其极限。 接下来,添加另一个实例并加载这对-再次达到最大值; 我们看到他们的天花板和三角洲的第一个“挤压”。 因此,我们每步连接一个实例并计算变化的模式。
通过“挤压”获得的测试数据也涌向了通用指标数据库,在该数据库中,我们可以用它们丰富人工加载的结果,甚至可以将它们替换为“合成”。


生产量


•缩放。 通过将服务推广到生产环境,我们可以跟踪其扩展方式。 在这种情况下,根据我们的经验,仅监视CPU指示器效率低下。 使用RPS基准测试以其纯格式进行自动缩放有效,但仅适用于某些服务,例如在线流。 因此,我们主要关注特定于应用程序的产品指标。


结果,在扩展时,我们分析:
-CPU和RAM指示灯
-队列中的请求数,
-响应时间
-根据历史数据进行预测。


在扩展服务时,监视其依赖关系也很重要,这样就不会证明我们是扩展链中的第一项服务,并且它所指的服务也处于负载之下。 为了为整个服务池建立可接受的负载,我们查看“最近”依赖服务的历史数据(基于CPU和RAM以及特定于应用程序的指标的组合),并将它们与初始化服务的历史数据进行比较,依此类推,沿着整个“依赖链” ”,从上到下。


服务专区


微服务投入运营后,我们可以将触发器挂在其上。


这是引发火灾的典型情况。
-检测到潜在的危险迁移。
-安全更新已发布。
-服务本身未更新很长时间。
-服务的负载已大大降低,或者其任何产品指标均超出正常范围。
-该服务已停止满足新平台要求。


一些触发器负责工作的稳定性,某些触发器负责系统的服务-例如,某些服务很长时间未部署,并且其基本映像已停止通过安全检查。


仪表板


简而言之,仪表板是我们整个PaaS的控制面板。


  • 有关服务的单点信息,包括有关服务覆盖范围的数据,测试的数量,产品副本的数量,版本等。
  • 用于按服务和标签(属于业务部门的标记,产品功能等)过滤数据的工具
  • 与用于跟踪,记录,监视的基础架构工具集成的手段。
  • 单点服务文档。
  • 所有服务事件的单一观点。





合计


在引入PaaS之前,新的开发人员可能需要花费数周的时间来挑选出在生产中启动微服务所需的所有工具:Kubernetes,Helm,我们的TeamCity内部功能,以容错的形式建立与数据库和缓存的连接等。现在,需要花费几个小时才能阅读快速入门并制作服务本身。




我针对HighLoad ++ 2018做了关于此主题的报告,您可以观看视频演示文稿


已读完书的人可获得奖金


我们在Avito的组织者将为微服务架构专家Chris Richardson的开发人员组织一次为期三天的内部培训。 我们想给这个帖子的读者之一提供参与的机会。 是一个培训计划。


培训将于8月5日至7日在莫斯科举行。 这些工作日将被全部占用。 午餐和培训将在我们的办公室,选定的参与者自己支付旅行和住宿。


您可以申请参加此Google表单 。 来自您-为什么您确实需要参加培训以及有关如何与您联系的信息的问题的答案。 用英语回答,因为克里斯将选择参加培训的参与者。
我们将不迟于7月19日在Avito面向开发人员的社交网络( Facebook上的 AvitoTech, VkontakteTwitter )上宣布培训参与者的姓名,作为对本帖子的更新。


UPD,07/19:我们收到了数十份申请。 克里斯检查了他们并选择了一名参与者:Andrei Igumnov将与我们的同事一起去学习。 恭喜你!

Source: https://habr.com/ru/post/zh-CN454780/


All Articles