微服务 to 变 or not to 变?

原著作者介绍:

Viktor Farcic

CloudBees资深顾问,熟悉多种编程语言,从最早的Pascal,Basic,ASP,C,C++,Perl,Python,ASP,NET,Visual Basic,C#,JavaScript等等。热衷于微服务、持续部署和测试驱动开发(TDD)。著有《Test-Driven Java Development》一书,该书由Packt出版。

巨兽型可变服务器

今天,在创建和部署应用的时候,最常用的方式就是可变服务器。我们会创建一个web服务器,该服务器上具有完整的应用,每次有新的版本发布时我们就会对服务器进行更新。服务器中具体的改动包括配置改动(属性文件、XML文件、数据库表等)、代码工件(JAR、WAR、DLL、静态文件等)、数据库模式和数据。因为每当有新版本时我们就会对服务器进行相应的改动,因此这种服务器叫做可变服务器。

对于可变服务器来说,我们不清楚开发、测试和生产环境是否相同,甚至是生产中的不同节点也可能会产生不利的差异问题。代码、配置文件或静态文件在某些实例中是否全部完成升级更新也未可知。

可变服务器是一种巨兽服务器,它包含了我们需要的所有东西,构成了一个简单的实例,后端、前端、API接口等等都包括在内。此外,这种服务器会不断成长。一段时间后可能没有人知道生产中某一部分的配置详情,而要想准确复制(新生产节点、测试环境等等)就只能复制整个虚拟机,然后开始进行配置(IP、主机文件、数据库连接等)。我们不断的在服务器中添加新东西,渐渐地就会失去对服务器的把控。过一段时间,当初设计完美惊艳的架构就会面目全非。

新添加的层次、新耦合的代码、还有源源不断的修补程序(补丁),最终你会迷失在迷宫一样的代码中。一开始还很美丽的小项目变成了一头丑陋的巨兽。你满怀希望的项目,到最后也成为了大家茶余饭后的笑话。对于这样的项目,人们可能会说最好的处理方式就是扔到一旁重新来过。但事已至此,巨兽一旦形成就难以重新开始了,已经投入了太多资源,重新开始将会耗费大量时间,而且会产生很多风险。所以巨石架构可能还会持续相当长的一段时间。

可变部署看起来简单,实则不然。它将所有东西都耦合在一起,试图把复杂性隐藏,但这也使各个实例之间更容易产生差异。

发布新版本应用时,何时重启这样的服务器很关键。因为在重启时,服务器通常都是不工作的,而这不仅会造成经济上的损失,还会丧失客户的信任。在今天的商业世界里,我们应当提供全天候运行的服务。此外,新版本发布时通常也意味着研发小组需要在夜间加班工作。面对这样的情况,持续部署看起来遥若星辰,可望而不可及。

测试同样也存在问题。不论我们在研发和测试环境中进行了多少次测试,只有我们将软件部署在生产环境中,让测试员和用户都能够使用,才开始真正意义上的第一次生产测试。

另外,这种服务器几乎无法实现快速回滚。因为服务器的可变性,所以不存在之前版本的“快照”。除非我们为整个虚拟机创建一个快照,但这又会产生很多新问题。

如果采用可变服务器,那么我们之前所描述到的需求是不可能全部满足的。由于服务器无法实现零宕机和快速回滚,我们也无法对其进行持续(频繁)部署。可变服务器的特性也决定了我们不可能实现全自动化(有风险),这样就延缓了我们的研发速度。

如果不能经常部署,那么我们只能不断的积累各种改变,而这些最终都会在发布的时候才暴露问题,很容易就会导致研发的失败。

为了解决这些问题,我们应该采用不可变部署方式,同时部署中应当包括小型、独立且自给自足性的应用。我们的目标很明确,零宕机时间、回滚能力、自动化以及快速功能。此外,我们还应当在用户接触软件前就在生产环境中对发布版本进行测试。

不可变服务器和反向代理

每一种“传统”的部署方式中,对系统的改动都会呈现在服务器上,从而增加了风险。而如果我们采用不可变部署方式,那么就可以立竿见影,获得成效。由于我们不需要考虑应用(应用是不可变的),因此环境的准备工作将变得极为简单。当我们在生产服务器上部署一个新的镜像文件或容器时,我们很清楚该文件或容器就是我们一直在开发和测试的东西。

不可变部署减少了未知的风险,我们知道每一个部署的实例和其他实例都是相同的。与可变部署不同,当程序包不可变而且包含了所有东西(应用服务器、配置文件和工件)的时候,我们就可以高枕无忧了。这些东西打包作为整体在部署流程中进行处理,我们只需要确保这些不可变的程序包顺利到达终端服务器就好。不可变部署消除了可变部署带来的不一致性,我们在其他环境中进行测试的程序包和最终到达服务器的程序包是完全相同的。

反向代理可用来实现零宕机。不可变服务器和反向代理可以通过下面这种简单的方式结合使用。

首先我们启动一个反向代理,指向已经完成的完全自给自足的不可变应用程序包。这个程序包可以是虚拟机,也可以是容器。这个不可变的镜像显而易见有别于可变应用。此外,还会有一个代理服务,服务器并不会直接暴露,代理服务会将所有访问(traffic)发送(route)到最终的目标位置。

一旦我们决定要部署一个新版本时,我们就会通过在另外一个独立的服务器上部署单独的镜像来完成。当然,有时候我们可以将这个镜像部署在相同的服务器上,但更多时候,由于巨石应用消耗大量资源,在不影响性能的前提下我们很难在同一节点进行多次部署。

此时,我们就会有两个实例(两台服务器)。一个是老版本,一个是新版本。所有的访问均通过代理服务由老的服务器处理,这样用户就不会察觉到任何改变。因为对于用户来说,我们仍旧在运行之前的服务器和软件。此时我们就可以放心的去做新软件应用的最后测试了,最好这些测试都是自动化的,而且属于部署过程的一部分,但仍需人工检测。

例如,如果我们在前端做了修改,那么就需要在最后做一次用户体验测试。不论我们进测试类型是什么,都需要绕过代理服务针对新发布软件进行测试。做这些测试的时候,我们很清楚自己在测试的软件将来会发布并应用于硬件上,而且我们是在没有影响用户体验(用户此时在使用旧版本软件)的情况下进行的测试。甚至我们可以通过A/B测试的形式选择对一部分用户开放新版本软件。

总的来说,这个时候我们就有了两个服务器实例,一个(旧版本)给用户使用,一个(新版本)用来进行测试。

第二个实例与第一个实例平行部署

不可变应用的新版本部署在独立的节点处

一旦我们完成测试,确保新版本万无一失,那么我们只需要修改代理服务,让访问指向新版本软件即可。旧版本可暂时保留一段时间,供可能的回滚使用。但对用户来说,旧版本已经不复存在了。用户的所有请求都会指向新发布的版本。而我们在此之前已经确保新版本可以投入使用,因此请求指向的改变并不会影响服务体验(而如果在可变部署模式中,这样做就需要重启服务器,导致服务中断,影响用户体验)。当请求路径改变时,我们需要重新加载反向代理。例如,在所有连接转变到新路径之前,nginx会维持所有旧的连接路径。

最后,当所有转变完成后,我们可以移除旧版本,我们甚至可以让新版本去做这件事。这样的话,当到了合适的时间,新版本就会自动移除旧版本并取而代之。

上述方法已经在业内使用了很长时间,我们称之为蓝绿部署。之后我们在讲到Docker打包和部署示例的时候还会提到它。

不可变微服务

我们还能做的更好。不可变部署使得我们可以轻易实现流程的自动化,反向代理实现了零宕机,新旧版本的使用也简化了回滚工作。但由于我们面对的应用仍然过于庞大,因此部署和测试工作可能会花费大量的时间。这可能就会使我们的速度降低,而且无法频繁的进行部署工作。此外,体量庞大的应用在开发、测试和部署时的复杂度也很高。如果可以的话,我们可能会将其分割成易于管理的小部分,这样不仅易于管理操作,还能简化拓展。这些小服务可以部署在同一台机器上,如果其中某个服务到达瓶颈(需要扩展),那么我们就可以在网络中对其进行拓展或复制,而这正是微服务!

在研发“巨兽”型应用时,我们往往会产生解耦的层次。前端代码和后端代码分离,业务层和数据接入层分离等等。而在微服务中,我们应当开始换个角度来看问题。我们要分离的不再是业务层和数据接入层,而是各个服务。例如,用户管理服务可以从销售服务中分离出来。另外有一点不同的是在物理表现(physical)上,传统的架构分离是在程序包和类的级别进行,但所有东西还是共同部署的;而在微服务中,各项服务是物理隔离的,可能正在开发的两个服务都不在同一台机器上。

微服务的部署方式与之前描述的方式相同。

我们部署微服务不可变镜像的方式和部署其他软件的方式相同。

所有请求都通过代理服务选择路径

微服务应用是不可变的,部署时作为容器进行部署

当我们准备发布某个微服务的新版本时,会将其与旧版本部署在一起。

当新版本微服务完成测试后,我们改变代理的路径(route)

最终,我们就可以移除旧版本微服务,开始使用新服务。

唯一明显的不同就是,由于微服务体量较小,我们不需要额外的服务器存放新版本。现在,我们终于可以实现持续的(频繁的)自动部署,提高研发速度,零宕机时间,并且可以在出现错误时进行回滚工作。

DevOps 2.0 系列文章持续连载,欢迎保持关注此公众号。

相关文章链接:

老司机谈DevOps 2.0:引子

关乎DevOps成败的三个火枪手

原书链接:

http://download.csdn.net/detail/jiaoxiaogu/9529895

点击文末阅读全文,可直达译者CSDN博客。

关于译者:

胡帅

普元信息高级软件架构师,计算机软件与理论硕士。曾供职于IBM中国开发实验室,参与Rational Team Concert, Rational Insight等产品研发,曾经担任著名开源BI产品BIRT社区顾问。为工行,招行,建行,美国通用等大型企业提供DevOps以及BI产品咨询实施服务。在DevOps以及BI方面积累了丰富的研发与实施经验。

感谢郭威(西安电子科技大学外国语学院)及张振华(西安电子科技大学软件学院)对本文的整理校对。

原文发布于微信公众号 - EAWorld(eaworld)

原文发表时间:2016-11-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏鸿的学习笔记

聊聊分布式系统的时钟问题

诸如此类的问题,还能提出很多,因此需要一个靠谱的时钟来保证分布式系统里事件的处理不会出错。

1541
来自专栏Java职业技术分享

巧用分布式环境下的优雅技术,只有头发少的人才研究过

在分布式数据库系统中,用户感觉不到数据是分布的,即用户不须知道关系是否分割、有无副本、数据存于哪个站点以及事务在哪个站点上执行等。

850
来自专栏极客猴

高并发的那些事

"高并发"对后台开发同学来说,既熟悉又陌生。熟悉是因为面试和工作经常会提及它。陌生的原由是服务器因高并发导致出现各位问题的情况少之又少。同时,想收获这方面的经验...

5413
来自专栏UDNZ

软件系统的黑匣子:我们要怎样写日志

作为一个软件系统,需要写日志,这是不言而喻的,这是大家都会不假思索地说“那当然”的事。不论是什么语言,写日志的专用框架也不一而足,写到文本的,写到数据库的,写到...

6149
来自专栏人人都是极客

手把手教你如何向 Linux 内核提交代码

说到开源大家都会想到黑客和极客,开源的概念最早也是在极客们推出和推崇的。开源的提倡旨在开放源代码使之更方便自由的使用和再创作。随着这一思想的发展,衍生出诸多的开...

2262
来自专栏Android群英传

震惊!我逆向了Android代码居然看见……

1351
来自专栏Golang语言社区

7大决定决定服务器性能的指标,你测试过几个?

一,服务器PING值 PING测试在一定程度上可以代表服务器的宽带速度。 使用站长工具提供的Ping服务(http://ping.chinaz.com),来测试...

5265
来自专栏HaHack

化繁为简的企业级Git管理实战(三):分支管理策略

1304
来自专栏Guangdong Qi

iOS APP版本构建版本无效

2383
来自专栏hadoop学习

hadoop入门教程之DKH安装环境准备

前几天去参加了一个线下的聚会,参加聚会的基本都是从事互联网工作的。会上有人提到了区块链,从而引发了一场关于大数据方面的探讨。我也是从去年才正式接触大数据,一直在...

490

扫码关注云+社区

领取腾讯云代金券