作者:禚娴静
这两年,微服务架构火了。在国内,从消费级互联网应用,到企业级应用;从金融领域,到电信领域;从新开发系统到已经开发了十几二十年的遗留系统;一夜之间,好像所有的团队都在谈微服务。
然而,我们为什么采用微服务呢?
是的,让我们的系统尽可能快地去响应变化。其实几十年来我们一直在尝试解决这个问题。如果一定要在前面加个限制的话,那就是低成本的快速响应变化。上世纪九十年代Kent Beck提出要拥抱变化,在同期出现了诸多轻量级开发方法(诸如 XP、Scrum);2001年敏捷宣言诞生,之后又出现了精益、看板等新的管理方式。如果说,这些是为了尽快的响应变化,在软件开发流程和实践方面提出的解决方案,那么微服务架构就是在软件技术和架构层面提出的应对之道。
微服务是如何做到的?
微服务是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
— James Lewis and Martin Fowler
这是James和Martin2014年在《微服务》一文中提到的对于微服务的定义。相对于单体架构和SOA,它的主要特点是组件化、松耦合、自治、去中心化,体现在以下几个方面:
- 一组小的服务
服务粒度要小,而每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情。
- 独立部署运行和扩展
每个服务能够独立被部署并运行在一个进程内。这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
- 独立开发和演化
技术选型灵活,不受遗留系统技术约束。合适的业务问题选择合适的技术可以独立演化。服务与服务之间采取与语言无关的API进行集成。相对于单体架构,微服务架构是更面向业务创新的一种架构模式。
- 独立团队和自治
团队对服务的整个生命周期负责,工作在独立的上下文中,自己决策自己治理,而不需要统一的指挥中心。团队和团队之间通过松散的社区部落进行衔接。
我们可以看到整个微服务的思想就如我们现在面对信息爆炸、知识爆炸是一样的:通过解耦我们所做的事情,分而治之以减少不必要的损耗,使得整个复杂的系统和组织能够快速的应对变化。
My First Law of Distributed Object Design: Don’t distribute your objects (From P of EAA). - Martin Fowler
然而谈到微服务,我们不能忽视的一点是:微服务仍然是典型的分布式系统,它必然有分布式系统固有的问题:诸如怎么部署,出错怎么办,怎么保证数据的最后一致性;与此同时,还有服务要多微?业务变化后服务如何调整?服务规模化后怎么办?如何避免一个服务改动导致的多个级联服务的失败?如何进行测试等等问题。
“微服务不是免费的午餐”。从实战中我们清楚地认识到选择任何架构都有利有弊,服务化也是一样。企业从微服务架构获益的同时,必然要面对切换到由众多服务组成的分布式系统后所带来的挑战。我们认为只有提升团队应对这些挑战的成熟度,才能真正使企业从这种微服务架构中获益.
那么对于即将和已经开始实施微服务的团队,应该如何应对呢?结合我们项目的经验,我认为应从DevOps、服务构建、团队和文化四点入手:
- 首先需要考虑构建DevOps能力,这是保证微服务架构在持续交付和应对复杂运维问题的动力之源;
- 其次保持服务持续演进,使之能够快速、低成本地被拆分和合并,以快速响应业务的变化;
- 同时要保持团队和架构对齐。微服务貌似是技术层面的变革,但它对团队结构和组织文化有很强的要求和影响。识别和构建匹配架构的团队是解决问题的另一大支柱。
- 最后,打造持续改进的自组织文化是实施微服务的关键基石。只有持续改进,持续学习和反馈,持续打造这样一个文化氛围和团队,微服务架构才能持续发展下去,保持新鲜的生命力,进而实现我们的初衷。
在本文中会针对第一点,并以我们项目微服务的发展历程为例介绍我们遇到的各种坑和采取的相关措施,希望能够给正在准备实施和已经实施微服务的团队一些借鉴。
背景
我们于2012年在系统集成需求的驱动下走上了服务化之路,通过将重复的业务能力封装在几个服务之间完成了系统集成,并成功上线。最初只有8个服务支持我们的业务系统,服务与服务之间采取基于HTTP的RESTful API的方式进行通信,通过自动化脚本将应用部署到生产环境。
在随后的2年中我们的业务快速发展,增加到了60多个站点和服务。服务的上线周期也越来越短,从两年到两周。而这样的一套生产环境是由客户的2名运维人员手工维护的(包括基础设施构建),每次发布都会存在大量的人工干预,比如对部署结构和系统权限的修改等,给我们的整个生产部署和运维带来了较大的问题:
- 大量的人工干预,频频出错。
手工方式始终是易错和低效的,而且会导致各种难以重现的环境问题(就如雪花服务器),这使得一些复杂点的运维工作,包括技术平台的整体升级、灾备系统搭建等很难开展,往往要提前半年甚至一年来进行筹备。当我们服务规模化和发布周期缩短之后,它带来的伤害又进一步明显起来。为了减小这种伤害,业务部门不得不降低发布频率,从两周延迟到一个月,因此也影响到了对最终用户的响应速度,并不得不采取Hotfix的方式来修正发布速度的问题,实际上又增加了问题的复杂度。
- 缺乏有效的监控和日志管理,产品环境定位困难。
没有监控,无法及时知晓服务的运行状态。很多问题直到最终用户才能发现,问题反馈周期很长。同时,运维人员不懂开发人员的服务设计和调用流程,开发人员不懂产品环境的配置结构。当产品环境出错之后,往往要花费数小时才能定位到问题根源。
另外,负载均衡和单点服务降级无法真正开展,当一个服务出现问题时,需要关掉其所在的服务器。产品环境资源利用率低,运维成本居高不下。
2015年初,当我们遇到了Powershell的bug和服务不能正常启动的貌似随机问题时,就如遇到了那根压倒骆驼的最后一根稻草,客户对我们明确的提出“不要再添加任何一个服务了”。
残酷的事实再一次向我们证明,在这样一个复杂系统下,传统的手工运维方式必然要被淘汰,微服务的实施有一定的先决条件:基础的运维能力(如监控、快速配置、快速部署)需提前构建,否则就会陷入像我们一般如此被动的局面。而我们也看到,当服务规模化后需要更多自动化和标准化的手段来提升效能和降低成本。
服务治理
随后的一段时间,我们的团队重新梳理了最后一公里和运维的需求,如下图所示,并开始服务治理,从而构建支撑当下架构的交付和运维能力。
1. 基础环境的准备
环境需要能够快速的创建并启用全新的服务,能够快速对现有的环境进行自动更改等,以保持各环境的一致性。我们推荐采用基础设施及代码的实践,通过代码来描述计算和网络基础设施的方法,使得图案度i可以快速安全的搭建和处理由新的配置代替的服务器,服务器之间可以拥有更高的一致性,降低了在“我的环境工作,而你的环境不工作”的可能,也是为后续的发布策略和运维提供更好的支撑。
在技术层面,随着云平台技术的成熟,Docker和围绕Docker生态圈的形成,开发和运维团队如虎添翼。组织可以根据现状选择合适的方式逐步迁移到云平台。另外,对于目前不能采用Docker技术的Windows平台,Chef、Ansible也是不错的选择。
2. 发布部署
要求服务能够快速上线,能够快速部署到各个环境以便尽快得到验证。面对如此庞大的服务及复杂的依赖关系,我们建议分离产品、预发布环境及测试环境。采用部署流水线,由自动化脚本实现全环境的快速部署,包括配置管理、版本管理等。
3. 运行时监控与业务运营
当产品环境出错时,需要快速的定位问题,检测可能发生的意外和故障。而监控是快速定位和预防的不二选择,在微服务架构中更是至关重要。监控包括服务可用状态、请求流量、调用链、错误计数等内容,以便发现问题及时修复,实时调整系统负载,进行必要服务降级,过载保护等等,从而让系统和环境提供高效高质量的业务服务。其中健康状态页面、结构化的日志、实时服务依赖关系可视化、流量统计、事件机制等都是监控领域可采取的基础技术手段。
除此,随着服务越来越多,需要进一步考虑蓝绿部署、灰度发布、服务安全、容器编排等问题和自动化标准化的手段,从而更好的管理大规模下服务产生的运维需求。下图是最近几期ThoughtWorks技术雷达中提到的相关内容,可供不同技术栈和处于不同实施阶段的团队参考:
我们的选择和改进
针对上面的几个痛点和我们项目所处的阶段,结合项目.NET技术栈的生态系统,我们主要采用Chef自动化构建本地构建的基础设施,与运维团队一起优化部署流程,提供服务健康状态页面支持监控,使用Splunk进行集中式日志管理,并可视化服务依赖关系等来进行全面服务治理,我们的部署时间从原来的十几个小时缩短到三十分钟,成功率也大大提高。结合业务部门的需求和现状的分析,对其方面地要求,如独立部署、配置管理、服务发现、过载保护等的改进仍在继续中。
除此之外,我们还做了什么?
You build it, you own it. - Amazon CTO
打造DevOps文化,将运维作为需求提前注入到开发流程
从上一节可以看出,微服务对开发人员和运维人员的工作方式和技能都有新的要求,带来很强的冲击。在2014年随后的一段时间,我们开始将运维的需求内建到整个开发流程。当新业务需求提出的时候会同时交给开发人员和运维人员,后者将整个运维环境的要求(包括监控和安全)进行分析,产出约束规范或非功能需求递给开发人员;开发人员在做技术决策和开发工作时遵循这些约束并满足这些非功能需求,最后将整个产品以及监控的实现交付给运维团队。双方同时也重建了沟通计划,互换技术架构和运维方面的知识,互相支持和深入合作。
在我们整个服务治理的过程中,花了大量的时间去理顺最后一公里和运营监控的问题,与运维团队的合作一步步从无到有,从不信任不合作到逐渐改善,才使得微服务的实施顺利进阶。可以说在企业内要成功实施微服务,最不能少的合作角色就是企业的运维团队。微服务实施要想顺利进行,必须要打破开发团队和运维团队之间的高墙,真正做到“开发自运维”,运维自开发,互生互长。我们也向其他的组织推荐这样的方式,打通DevOps的任督二脉,为微服务保驾护航。
扩展阅读:
- http://martinfowler.com/microservices/
- http://martinfowler.com/bliki/MicroservicePrerequisites.html
- http://martinfowler.com/bliki/InfrastructureAsCode.html
- https://www.thoughtworks.com/insights/blog/microservices-evolutionary-architecture
- http://liguanglei.name/blogs/2015/04/22/devops-chinese-name/
- https://www.thoughtworks.com/insights/blog/macro-trends-technology-industry
原文发布于:微服务的团队应对之道