【图灵学院】微服务架构落地方案施设与应用

概述

为什么需要微服务架构

“微服务”架构是近期软件应用领域非常热门的概念。让我们先来看看传统IT架构面临的一些问题:

使用传统的整体式架构(Monolithic Architecture)应用开发系统,如CRM、ERP等大型应用,随着新需求的不断增加,企业更新和修复大型整体式应用变得越来越困难;

随着移动互联网的发展,企业被迫将其应用迁移至现代化UI界面架构以便能兼容移动设备,这要求企业能实现应用功能的快速上线;

许多企业在SOA投资中得到的回报有限,SOA可以通过标准化服务接口实现能力的重用,但对于快速变化的需求,受到整体式应用的限制,有时候显得力不从心;

随着应用云化的日益普及,生于云端的应用具有与传统IT不同的技术基因和开发运维模式。

此外,从技术方面看,云计算及互联网公司大量开源轻量级技术不停涌现并日渐成熟:

互联网/内联网/网络更加成熟;

轻量级运行时技术的出现(node.js, WAS Liberty等);

新的方法与工具(Agile, DevOps, TDD, CI, XP, Puppet, Chef…);

新的轻量级协议(RESTful API接口, 轻量级消息机制);

简化的基础设施:操作系统虚拟化(hypervisors), 容器化(e.g. Docker), 基础设施即服务 (IaaS), 工作负载虚拟化(Kubernetes,Spark…)等;

服务平台化(PaaS): 云服务平台上具有自动缩放、工作负载管理、SLA 管理、消息机制、缓存、构建管理等各种按需使用的服务;

新的可替代数据持久化模型:如NoSQL, MapReduce, BASE, CQRS等;

标准化代码管理:如Github等。

这一切都催生了新的架构设计风格 – 微服务架构的出现。

什么是微服务

微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。

步骤一:以终为始,先构建一个独立的敏捷微服务团队

我们对微服务的期待就是:可以独立开发,独立部署,独立发布,并且去中心化管理。那么,我们就先构造一只“可以独立开发,独立部署,并且去中心化管理”的团队。

这个团队为了达到这个目标,会采取各种方法(例如:DevOps,全功能团队)解决阻碍”独立开发,独立部署,独立发布 和 去中心化的问题。而根据康威定理,系统的架构会慢慢向去中心化方向发展。

一定要意识到,这个过程会打破大型系统自上而下的既有流程并采用更有生产力的方式构建新的组织结构。你索要做的就是要充分信任团队,把它看做是一个微型的技术管理创新。不要用老的方式控制团队的运作,这会打击团队的士气。

管理建议:

让微服务团队完全脱离之前的工作,专心于微服务的工作中。如果分心同时做几件事,每件事都不会做到最好。

给微服务团队一些特权,为了满足“全功能微服务团队的”诉求,特事特办。

如果团队在执行的过程出现了依赖从而阻碍了进度。则需要把依赖标明出来。代码中的依赖容易看见,但组织中的流程依赖很难发现。

为了避免团队对外部的“依赖惯性”,让团队自己想办法在内部解决依赖。

组织流程的改变也是很重要的微服务架构产物,而不仅仅是微服务代码或基础设施。

技术建议:

为微服务建立一个全新的代码库,而不要从原先的代码库上克隆或者复制,避免和原团队的开发依赖。

建设一个独立的持续交付流水线,最好是通过“流水线即代码技术”(例如 Jenkinsfile)来自动生成流水线。

步骤二:构建微服务的“电梯演讲”

成立了微服务团队之后,接下来就是要选择第一个实现的微服务。但是这个微服务应该多大,边界在哪是个问题。这不需要进行严格的设计和反复的论证,只要发现当前的痛点或者想要完成一个假设就足够上路了。让整个过程变轻,而不是变重。

我的建议是通过“微服务电梯演讲”的方式来定义微服务。格式可以是:

(XX微服务)用来

在(出现痛点的场景)的情况下

解决了(解决现有的某个问题)

从而(达到什么样的效果)

提升了(微服务的价值)

例如:

(订单查询微服务)用来

在(订单查询数量快速)的情况下

解决了(访问数量迅速升高导致整体应用性能下降的问题)

从而(分离了订单查询请求)

提升了(提升了其他功能的性能)

当构造了微服务的电梯演讲,团队就可以以此为原则启动了。当碰到和现有系统冲突的问题,替换几个词比较有帮助你做决策。(语言一定程度上也是具有魔力的)

把“拆分”换成“移除”。例如:“从现有系统中拆分出订单查询功能” 转变为 ”从现有系统中移除订单查询功能“。思维方式就从一个团队负责两个系统变成了两个团队负责两个系统。

把“集成”换成“调用”。例如:”用户注册和用户登录需要集成”转变为“用户登录服务需要调用用户注册服务的信息”。思维方式就把两个系统的关系更精确了,从而明确了微服务之间的关系和沟通方式。

管理建议:

把微服务的电梯演讲打印出来挂到墙上,让团队成员铭记于心。这会强化组织对微服务的边界认识。

随着团队的反思和学习,电梯演讲有可能会变更,但一定要让团队形成共识好和一致的意见。

不要期望一次就能划分正确。划分是一个持续权衡取舍的过程。

技术建议:

明确了微服务的职责和边界之后再去看代码,否则会被代码的复杂度影响。

领域驱动设计(DDD)可以帮助你更好的划分微服务。领域驱动设计很好的遵循了“关注点分离”(Separation of concerns,SOC)的原则,提出了更成熟、清晰的分层架构。

不会领域驱动设计(DDD)也没有关系。简单的使用“关注点分离原则”也可以帮你达到这一点。例如:从接口中分离出流量较大的接口独立部署,把读数据库和写数据库的 API 分开独立部署,把静态和动态访问分离……等等。

步骤三:以最小的代价发布出第一个微服务

要注意两个关键点:一个是“最小的代价”,另一个是“发布”(Release)。

正如前文所述,微服务架构本身就觉了微服务一定是低成本低风险的渐进式演进。而最大的浪费在于:

  1. 级别/职责分工明确的组织沟通结构。
  2. “长时间,慢反馈”的行动习惯。
  3. 先进且学习成本较高的技术栈。

因此,“最小的代价”包含了以下三个方面:

  1. 最精简的独立敏捷全功能团队。
  2. 最快的时间。
  3. 代价最小的技术栈。

此外,很多微服务的“爱好者”由于害怕失败,因此将微服务技术始终放在“实验室”里。要勇于面对失败,在生产环境中面对真实的问题,但要采取一些规避风险的措施。

管理建议:

尽量让现有微服务团队自己学习解决问题,成为全功能团队。如无必要,绝不增添新的人手。

“扯破嗓子不如甩开膀子”,先动起来,在前进中解决问题。

先考虑最后如何发布,根据发布流程倒推。

技术建议:

根据当前技术采用的情况选择代价较小的技术栈。

采用动态特性开关(Feature Toggle),在发布后可以在生产环境动态的控制微服务的启用,降低失败风险。

如果采用了特性开关,一定要设立删除特性开关和对应旧代码的时间,一般不超过两个月。否则后面大量的特性开关会带来管理成本的提升和代码的凌乱。

由于团队比较小,功能比较单一,不建议采用分支来构建微服务,而应该采用单主干方式开发。

步骤四:取得快速胜利(Quick wins),演示(Showcase)驱动开发

刚开始进行微服务改造的时候一定会是一个试错的过程。如果目标定得太大,会让团队倍感压力,从而士气低落。而制定每日的短期目标,赢得快速胜利则会不断激励团队的士气。通过设定当天结束的产出来确定今天需要做什么是一个非常有效的办法。

每日演示(Daily Showcase)就是一种推进产出的做法。每天向团队分享今天的工作内容,使小组能够共同学习。并且以当天或者明天的 showcase 作为目标。每个人showcase 的内容一般不超过20分钟,一天的 showcase 时间不超过一小时。可以早上 showcase,也可以下班后 showcase。

常见的快速胜利目标如下:

构造第一条微服务流水线。

上线第一个微服务 HelloWorld

构造出第一个微服务自动化测试。

而 以下的目标不适合作为快速胜利的目标:

构造出微服务 DevOps 平台。

完成整个产品的微服务架构拆分。

构造微服务自动化运维体系。

管理建议:

要防止团队画大饼,完成好每日和每周的工作目标即可。微服务开发本身就没有很长周期。

强迫团队有所产出,这样才能用关键产出驱动开发。产出不一定是代码或者基础设施,一篇总结,或者学习的文章分享,甚至是踩过的坑和遇到的问题都可以展示,目的是要打造自治学习的团队。

贵在坚持,不要计划太远。超过一个月,就要对目标是不是范围过大进行反思。

以天为单位拆分任务,超过一天的必须要拆分。无法在一天完成的工作需要拆分出阶段性产出。

如果能结对,并且能够每天交换结对,showcase 不必要。

可视化所有任务,用敏捷看板来管理任务是了解现状的最好方式。

技术建议:

除了让第一个 HelloWord 微服务尽快发布到生产环境,其它的不要想太多。

完成了 HelloWord 的发布,然后要考虑如何对发布流程进行改进。而不是上线业务。

步骤五:代码未动,DevOps 先行

微服务解耦的本质是把代码内部的复杂性通过一些工具转化外部复杂性。把代码内部的复杂性分散到各个微服务中以降低整体复杂性和架构风险。在这个过程中会大量采用了 DevOps 技术和工具。也可以说,微服务是 DevOps 文化和技术在走到极致的必然结果。

以 J2EE 的应用为例,以前Web Server + App Server + MiddleWare + Database 的传统架构被代码更少,更多的基础设施工具所取代。因为基础设施相对于代码来说更加稳定,更加利于扩展。

我把微服务的技术架构问题比作“搭台唱戏”:首先需要建立好微服务交付和运行的平台,然后让微服务上台“唱戏”。

这个平台一开始不需要很完善,只需要满足生产上线的必要要求即可。而在很多企业里,这个部分是由 Ops 团队在交付流程的末尾把关的。因此,把最后一道关卡的确认工作放到最前面考虑可以减少后期的返工以及不必要的浪费。

以前,软件的开发和测试过程是分开的。然而,随着 DevOps 运动的兴起和各种自动化运维工具的兴起,这之间的必要性不如从前,只要有足够的自动化测试做质量保证,就可以很快的将微服务快速部署和发布到生产环境上。

最开始的时候,哪怕是发布一个 Hello World 程序,都表明微服务的持续交付和运行的平台已经搭建好,微服务交付流程已经打通,这一点是重中之重。

从技术交付产物来说,DevOps 主要交付两点:

持续交付流水线。

微服务运行平台。

为了保证微服务交付的高效,需要把这二者通过自动化的方式有机的结合起来,而不是各为其主。让开发和运维的矛盾变成“自动化的开发运维矛盾”

此外,DevOps 指的不光是一系列技术,更是一种工作方式。从团队工作方式来说,DevOps 要做到:

要让 Dev 和 Ops 共同参与决策,设计,实现和维护。

团队完全独立自主,打破对现有流程的依赖。

不断的追求改进,让团队行程改进的团队文化。

管理建议:

给团队继续前进最大的动力就是新程序快速投入生产。

如果你的组织是 Dev 和 Ops 分离的组织,先咨询一下 Ops 工程师的意见。最好是能够给微服务团队里面配备一名 Ops 工程师。

如果不具备实施 DevOps 的条件,微服务架构就要从运维侧,而不是开发侧开始进行。

技术建议:

微服务的平台一开始可以很简单,可以以后慢慢增强和扩展。但是一定要部署到生产环境里使用。

如果想使用现成的微服务平台可以参考 Spring Cloud。

微服务运行平台可以通过反向代理和生产环境并行运行。

采用灰度发布技术在生产环境中逐步提升微服务的使用占比。

基础设施即代码是 DevOps 核心实践,可以帮助开发人员迅速在本机构建生产环境相似的开发环境,减少环境的不一致性。可以采用 Docker,Ansible,Vagrant 等工具来完成。

基础设施对微服务应该是透明的。微服务不应该也没必要知道运行环境的细节。只要能够正常启动并执行业务就完成了它的任务。因此,基础设施代码要和微服务业务代码分开,且微服务不应该告诉平台自己如何部署。

Java架构师教程免费试听地址:https://vip.tulingxueyuan.cn/page/1690373