)
写在前头大家曾经有没有遇过日常技术交流的时候会讨论某某技术之间的关系是什么某些技术是否应该用到微服务。我相信热爱技术交流的您就算不是在微服务这里领域或多或少都会跟其他同行会做一些争议话题的探讨而且我敢肯定这些讨论绝对热火朝天。今天我想从微服务的4个比较火热的话题进行出发与大家分享我对微服务的一些个人见解这4个话题分别是微服务来带的新问题、微服务与SOA、微服务与DDD、是否有必要引入聚合层。这里部分话题在业界会存在一定的争议性例如DDD的引入、微服务与SOA的关系。一千个人眼中有一千个哈姆雷特不同的人以不同的视角去看待这些问题都会拥有不同观点与答案。观点上咱们求同存异不盲目遵从别人的想法也不自以为是的把自己当成标准。当然了我并不会为了个人见解而故意制造观点与话题更不会把我所有的观点当成一个“所谓的”标准。因此在该篇文章我会把多处理收集的资料梳理好放到文内有理有据地结合自己的见解与大家分享一二。这些内容可能是大家日常容易混淆的也可能是大家多次纠结不知道如何做出选择因此我希望通过我该篇文章的分享能给大家带来新的观点上的碰撞或是见解上的共鸣。微服务带来的新问题做技术选型就如网上购物一样即使知道了它的优点还得看看它的差评。我们得多方面评估事先知道团队与业务是否能抵御与承受“坑”的风险。既然任何一样技术都无法成为软件工程的银弹那么必然解决了某种问题的同时也会带来一些新问题微服务也不例外。我回顾了下当时我实施时的难点确实有不少。不过我个人认为微服务给我们带来最核心的问题主要有三点两文化与一思维自动化文化可观测性文化分布式系统思维上面这三个问题每个的内容单独拿来出讲的篇幅都足以出一篇完整的文章甚至是书基于此我会挑一些重点和大家分享。当然几乎每部分的文末我会放入相关内容的文章外链如果大家有兴趣可以自行扩展阅读。自动化避免重复的人力劳动任何的架构模式也是需要同等的开发模式与之配合的随着应用的拆分后服务的数量由量变引起质变因而需要接受自动化来代替从前的“人工处理”包括服务的部署、服务注册发现等等。自动化是软件工程的其中一种处理手段允许团队采用主流的工具、流程形成一套自动化机制从而减少重复性工作、减少人力干预的不确定性因素。这里说说我对软件工程的理解通过多人协作、有目标、有步骤、有计划的并使用科学方法论指导开发与维护程序的这个过程也可以换成一条公式表达软件工程 工具 流程 模式。无论是我们讨论的这些“事”、技术工具还是流程制度都是需要人团队组织的参与人的延申就是团队与文化就如上述所说的软件工程是多人协作的工作只有当然团队目标一致共同负责承担团队的项目共同接受同一种文化才能很好的实施自动化。我简单举个例子如同多匹马拉车一样只有它们都有共同的目标的时候才能快速拉车到目的如果它们一匹向东一匹西只会让马车无法前行甚至四分五裂。说到这里有些人觉得疑惑自动化这种能给团队省时省力、减少重复工作量、增加幸福度的技术难道还有人或者团队会抗拒的是的还真的有。我曾经就接触过几个团队的Leader他们的团队都是推行自动化失败了失败的原因就在于成员不配合成员拒绝配合的理由是没有自己亲手去做总觉得机器不靠谱。我们先忽略他们的想法是对是错回到团队与文化从上面可知统一团队的目标一致性是有必要的作为技术领导者推行优良的方案是我们的职责之一。如果团队成员无法配合导致推行受阻我们一共有三种应对策略激励、考核和逐步试行。如果有条件的公司可以设置奖金激励如果有绩效考核的可以将自动化的实施纳入考核目标如果这俩都没有那就选取团队里愿意改变的同事牵头试行假如使用过后都说好那么会更有说服力。这部分就说到这里吧基于此话题的内容比较多广而泛篇幅有限这里分享一篇我自己曾分享过的内容《.Net微服务实战之DevOps篇》如有感兴趣的朋友可看完整篇文章后自行有选择性、针对性地扩展阅读。可观测性提高团队对系统运作的信息量如果说自动化是给团队带来稳定性减轻工作量的那么可观测性就是提高团队对系统运作的信息量。建立可观测性的这项工作虽然无法直接给系统带来健壮性但能够使我们通过这些信息充分地了解到系统正在运作的情况以至于最大程度地做出最合适的定位、判断与决策。在单体应用的场景下我们也是需要可观测性的但是单体的架构相对简单项目调试也更加便捷无论是从复杂度和规模的角度来看单体跟微服务相比都要低不少也因此单体对可观测性的需要相比于微服务显得没那么重要。而我们只要进行了微服务实施后因为应用被拆分成了细粒度从而导致了架构从量变引起质变这个时候可观测性的作用在微服务场景下被“无限放大”也因此我们利用可观测性给与我们提供应用与服务器的监控、快速跟踪与问题定位的功能。可观测性——可以由系统的外部输出推断其内部状态的程度在软件系统中可观察性是指能够收集有关程序执行、模块内部状态以及组件之间通信的数据而可观测性三个维度组成日志logging、跟踪 tracing、指标Metrics。日志logging的定义特征是它记录离散事件目的是通过这些记录后分析出程序的行为。跟踪 tracing的定义特征是它处理请求范围内的信息目的是排查故障。指标Metrics的定义特征是它们是可聚合的目的是监控和预警。可观测性类型名称跟踪 tracing分布式链路跟踪SkyWalking日志logging日志系统ESFilebeatkibana指标Metrics系统监控Prometheus因此基于上述总结有日志记录才能清楚知道当前系统的运行状况和具体问题指标是给与后续做优化和定位偶发性问题的一些参考没指标参考就没标准我们平常做得多的调试、查看调用栈也是跟踪的一种但是在分布式时代更多考量的是跨进程通信的调用链路。日常有小伙伴曾问过我如果出了那些很奇怪的问题应该怎么定位、排查本质上其实还是得提高我们对这个问题或系统的信息量。例如是哪个模块、接口出问题具体服务器表现的情况是怎样CPU还是IOPS高具体报错是什么你看说白了还是可观测性的三个要素日志、跟踪、指标。我们在工作中只有灵活结合这三者才能提高我们对系统运行情况的信息量信息量越高思考的越是更加全面才能尽可能地减少“不知道问题出在哪”的状况所以当我们不清楚具体发生问题的原因时建议你侧重做一件事就是尽可能想办法提高我们对问题与系统的信息量。新思维不可避免的分布式系统问题上文的自动化和可观测性主要偏向于运维层面而作为后端开发人员更加关注的是数据与应用服务的层面特别是服务的拆分后数据的一致性该如何处理。我相信这问题困扰着不少的后端开发接下来我将从幂等性、数据的一致性的读与写三个方向跟大家分享一二。幂等性幂等性的定义——相同的参数在同一个方法里无论执行一次还是多次都会响应相同的结果对于查询和删除的场景都有天然的幂等性那么我们考虑幂等性的处理更多是关注于新增数据与更新数据。新增数据缺乏幂等性则会因为网络抖动导致请求重试或者是客户端重复点击而引发的数据写入重复其解决方案也相对简单只要从客户端生成主键传给后端API 就可以解决在这里得注意一点只有请求成功或者主动刷新才会重新生成主键。更新数据缺乏幂等性主要会造成两种情况数值错误自增和ABA问题。首先数值错误自增可以结合事务凭据与新增幂等性的方式解决。而ABA问题解决方案相对简单可以在更新操作时带上版本号判断进行解决。ABA问题对某条记录先更新了A数据紧接着又更新了B数据理应是B是最新的但是因为其他客观原因使接口Retry或者别的问题导致A数据再次请求覆盖了B。幂等性处理方案场景问题方案新建数据重复创建由调用端预生成订单号唯一键约束更新数据ABA覆盖问题添加版本号判断金额自增使用流水凭据数据一致性读数据一致性读其实说白了就是做数据关联从我过往用的解决方案来看共有三种应用层的接口聚合数据、把更新频率低的字段冗余存储、把数据库同步到一台服务器进行SQL联表处理每种方式各有优缺点我结合切身体会和过往经验以表格方式整理呈现出来你可以根据业务场景自行选择解决方案。数据关联方案方案名称方案描述优点缺点应用层数据聚合分别调用查询API在业务逻辑层组装适用于简单的关联。实现简单该方案只能适合简单的查询过滤以主表为驱动的关联冗余设计反范式在目标表添加冗余字段适用于记录递增的不适用于冗余字段更新频繁实现起来简单有扩展性问题实现简单以应用层数据聚合方案有更多的过滤条件冗余的字段如果更新存在同步问题该方案适用于更新频繁少的递增日志类数据数据库从库集成通过主从同步把相关表同步到一台服务器做跨库查询适用于复杂查询、报表类的有技术复杂度从长远收益来看能应对多种场景通过强大的SQL解决复杂的报表类查询拥有技术复杂度需要数据库主从处理数据一致性写写的数据一致性其实就是分布式事务主流的方案有TCC、本地消息表基于消息可靠的最终一致性、异步请求/回调。其他的多数是基于以上几种方法的变种例如RocketMQ的消息事务就是TCC本地消息表的变种。篇幅有限这里分享一篇我曾经编写的文章《.Net微服务实战之必须得面对的分布式问题》。分布式事务方案用文字描述起来相对比较吃力因此我通过流程图代替文字描述展示给大家。下方表格是我对这三种方案的优缺点与使用场景的总结。分布式事务方案名称场景优点缺点异步请求/回调跨网络环境、同网络环境实现简单强业务TCC跨网络环境、同网络环境有现成的框架、实现简单强业务基于消息可靠的最终一致性同网络环境有现成的框架、通用性强中间件依赖小结从拆的层面来看微服务的思想与优势给与开发人员带来了更多的便捷性如技术细节的隐藏与认知负担的降低使得开发人员更加关注自己负责业务代码的迭代。但是拆了后还得重新整合如果拆了无法整合那么这样的设计是没有意义的。从整合的层面微服务大大提高了对架构师技能的要求从通信交互到分布式问题从自动化工程到可观测性每一项对于架构师都是一种新的挑战。聊到微服务总绕不过SOA无论是过去还是现在只要聊到微服务总有个绕不过去的坎那就是SOA。接下来我会结合《Microservices》原文Microservices的[Smart endpoints and dumb pipes]模块简单聊聊微服务与SOA的之间的关系有助于大家更好地了解为何微服务比SOA更容易实施与盛行。在《Microservices》原文里有一个模块的标题是Smart endpoints and dumb pipes如果用翻译直译成中文是[智能端点和哑管道]我结合了自己的经验并查阅了多种资料最终认为[强服务和弱通信]作为它的翻译才更加合适。微服务的[强服务和弱通信]与SOA的[弱服务和强通信]是与之对应的而SOA架构的核心是ESBESB主要功能有消息路由、协议转换、消息转换和应用业务规则的复杂。仔细观察下来ESB基本上把微服务的基础设施该做的都做了如此高的技术复杂度也是导致SOA在过去那些年无法普及跟实施的根本原因。ESB的大而全的特点在文中描述到SOA的通信是“聪明的”smart pipes而我也因为ESB的特点给SOA的翻译是“强通信”。此外我翻译的微服务的“弱通信”并不代表通信的功能有限而真正的意义是弱化协议差异使用统一、轻量级的通信协议减少差异化、降低技术难度。总地来说基于两者在通信层面的对比我们因此能总结出它们本质上的差异SOA基于配置微服务则基于约定。关系的分类既然上面已经谈到了微服务与SOA之间的对比接下来又不得不提SOA与微服务的关系了。我从多个方面的资料梳理后总结出有这样两种看法微服务是SOA的最佳实践出自维基百科—— 微服务是SOA的演进版粒度更细基础设施去中心化。微服务拒绝SOA的标签出自马丁福勒的《Microservices》原文——微服务与SOA是两个完全不同的架构风格只不过刚好长得像。场景与目的我相信不少朋友看到SOA与微服务关系方面的话题时肯定第一时间在想无论是维基百科还是百度都是写着微服务是SOA的演化这还要说是的人云亦云的大家听多了看多了不妨从新的观点与角度看待一下问题这样或许会有新的碰撞与共鸣。大家认为微服务是SOA的演进版的理由也比较简单因为微服务基础设施只不过是把SOA的ESB拆了而微服务粒度更细SOA更粗。从表面看起来的确是这么一回事但是我认为要看清楚它们关系的本质就得从两者各自的处理场景目的出发。首先从微服务角度出发因为单体应用的大而全的高耦合与臃肿随着业务的发展迭代的时间越久就会有各种各样的问题因此通过把应用拆成了多个小的服务这里使用到了化繁为简、分而治之的思想解决原有单体的“痛点”和“难点”。接着从SOA的角度出发在当时那个年代希望把各种异构的系统给整合起来这些异构的系统有可能是从其他地方买的也有可能是研发的也有可能是找外包做的因缘由存在各种不确定性所以希望通过一个聪明的ESB解决所有的愚蠢的问题也是因此ESB的高复杂度导致当年SOA那会只是炒得火热却无法普遍落实。总地来说微服务以拆与约定作为出发点而SOA是以整合与配置作为出发点所以我个人认为从它们的出发点与目的的角度出发直接决定了它们在本质上是完全不同的架构风格。所以我更加倾向于《Microservices》原文提到的看法微服务的倡导者拒绝SOA这个标签的。微服务与DDD的争议要是说SOA是微服务理不清的过去那么DDD更是微服务的一块拦路石。拦住的不是技术人员对它们的热情而是它们之间扯不清的“捆绑销售”。《Microservices》原文、《微服务设计》、《领域驱动设计精粹》都有涉及到DDD对微服务划分的参考。DDD战略上的化繁为简与微服务的分而治之这两者的思想可以说是不谋而合。成就了彼此但是它们是否必须密不可分又或者说无DDD就无微服务的说法呢我是这么认为的。DDD领域驱动设计的过去2004年埃里克•埃文斯Eric Evans发表了《领域驱动设计》一书简称DDDdomain-driven design 自DDD提出后在软件开发领域一直处于SOA相似的尴尬地位——宣传得火热真正用的少。随着微服务架构的兴起DDD才迎来了自己的时代。在上文提到三本书《Microservices》原文、《微服务设计》、《领域驱动设计精粹》都有涉及到使用DDD战略来识别边界上下文从而划分服务。总地来说DDD并不是什么新颖的技术当年许多布道者也没有把它带火如今却靠着微服务流行起来而加速了DDD的盛行。但是DDD的盛行并非它所有的一切我总结了DDD的一些核心概念希望在我详细叙述前可以帮助到你快速了解DDD以便于对后续内容有个更好的理解