微服务架构是什么?
栏目:行业动态 发布时间:2023-05-17
 完美体育本文将介绍微服务架构和相关的组件,介绍他们是什么以及为什么要使用微服务架构和这些组件。本文侧重于简明地表达微服务架构的全局图景,因此不会涉及具体如何使用组件等细节。  要理解微服务,首先要先理解不是微服务的那些。通常跟微服务相对的是单体应用,即将所有功能都打包成在一个独立单元的应用程序。从单体应用到微服务并不是一蹴而就的,这是一个逐渐演变的过程。本文将以一个网上超市应用为例来说明这一过

  完美体育本文将介绍微服务架构和相关的组件,介绍他们是什么以及为什么要使用微服务架构和这些组件。本文侧重于简明地表达微服务架构的全局图景,因此不会涉及具体如何使用组件等细节。

  要理解微服务,首先要先理解不是微服务的那些。通常跟微服务相对的是单体应用,即将所有功能都打包成在一个独立单元的应用程序。从单体应用到微服务并不是一蹴而就的,这是一个逐渐演变的过程。本文将以一个网上超市应用为例来说明这一过程。

  几年前,小明和小皮一起创业做网上超市。小明负责程序开发,小皮负责其他事宜。当时互联网还不发达,网上超市还是蓝海。只要功能实现了就能随便赚钱。所以他们的需求很简单,只需要一个网站挂在公网,用户能够在这个网站上浏览商品、购买商品;另外还需一个管理后台,可以管理商品、用户、以及订单数据。

  由于需求简单,小明左手右手一个慢动作,网站就做好了。管理后台出于安全考虑,不和网站做在一起,小明右手左手慢动作重播,管理网站也做好了。总体架构图如下:

  小明挥一挥手,找了家云服务部署上去,网站就上线了。上线后好评如潮,深受各类肥宅喜爱。小明小皮美滋滋地开始躺着收钱。

  好景不长,没过几天,各类网上超市紧跟着拔地而起,对小明小皮造成了强烈的冲击。

  这些活动都需要程序开发的支持。小明拉了同学小红加入团队。小红负责数据分析以及移动端相关开发。小明负责促销活动相关功能的开发。

  因为开发任务比较紧迫,小明小红没有好好规划整个系统的架构,随便拍了拍脑袋,决定把促销管理和数据分析放在管理后台里,微信和移动端APP另外搭建。通宵了几天后,新功能和新应用基本完工。这时架构图如下:

  单个应用为了给其他应用提供接口,渐渐地越改越大,包含了很多本来就不属于它的逻辑。应用边界模糊,功能归属混乱。

  管理后台在一开始的设计中保障级别较低。加入数据分析和促销管理相关功能后出现性能瓶颈,影响了其他应用。

  所有应用都在一个数据库上操作,数据库出现性能瓶颈。特别是数据分析跑起来的时候,数据库性能急剧下降。

  开发、测试、部署、维护愈发困难。即使只改动一个小功能,也需要整个应用一起发布。有时候发布会不小心带上了一些未经测试的代码,或者修改了一个功能后,另一个意想不到的地方出错了。为了减轻发布可能产生的问题的影响和线上业务停顿的影响,所有应用都要在凌晨三四点执行发布。发布后为了验证应用正常运行,还得盯到第二天白天的用户高峰期……

  团队出现推诿扯皮现象。关于一些公用的功能应该建设在哪个应用上的问题常常要争论很久,最后要么干脆各做各的,或者随便放个地方但是都不维护。

  尽管有着诸多问题,但也不能否认这一阶段的成果:快速地根据业务变化建设了系统。不过紧迫且繁重的任务容易使人陷入局部、短浅的思维方式,从而做出妥协式的决策。在这种架构中,每个人都只关注在自己的一亩三分地,缺乏全局的、长远的设计。长此以往,系统建设将会越来越困难,甚至陷入不断推翻、重建的循环。

  幸好小明和小红是有追求有理想的好青年。意识到问题后,小明和小红从琐碎的业务需求中腾出了一部分精力,开始梳理整体架构,针对问题准备着手改造。

  在编程的世界中,最重要的便是抽象能力。微服务改造的过程实际上也是个抽象的过程。小明和小红整理了网上超市的业务逻辑,抽象出公用的业务能力,做成几个公共服务:

  各个应用后台只需从这些服务获取所需的数据,从而删去了大量冗余的代码,就剩个轻薄的控制层和前端。这一阶段的架构如下:

  这个阶段只是将服务分开了,数据库依然是共用的,所以一些烟囱式系统的缺点仍然存在:

  如果一直保持共用数据库的模式,则整个架构会越来越僵化,失去了微服务架构的意义。因此小明和小红一鼓作气,把数据库也拆分了。所有持久化层相互隔离,由各个服务自己负责。另外,为了提高系统的实时性,加入了消息队列机制。架构如下:

  完全拆分后各个服务可以采用异构的技术。比如数据分析服务可以使用数据仓库作为持久化层,以便于高效地做一些统计计算;商品服务和促销服务访问频率比较大,因此加入了缓存机制等。

  还有一种抽象出公共逻辑的方法是把这些公共逻辑做成公共的框架库。这种方法可以减少服务调用的性能损耗。但是这种方法的管理成本非常高昂,很难保证所有应用版本的一致性。

  数据库拆分也有一些问题和挑战:比如说跨库级联的需求,通过服务查询数据颗粒度的粗细问题等。但是这些问题可以通过合理的设计来解决。总体来说,数据库拆分是一个利大于弊的。

  微服务架构还有一个技术外的好处,它使整个系统的分工更加明确,责任更加清晰,每个人专心负责为其他人提供更好的服务。在单体应用的时代,公共的业务功能经常没有明确的归属。最后要么各做各的,每个人都重新实现了一遍;要么是随机一个人(一般是能力比较强或者比较热心的人)做到他负责的应用里面。在后者的情况下,这个人在负责自己应用之外,还要额外负责给别人提供这些公共的功能——而这个功能本来是无人负责的,仅仅因为他能力较强/比较热心,就莫名地背锅(这种情况还被美其名曰能者多劳)。结果最后大家都不愿意提供公共的功能。长此以往,团队里的人渐渐变得各自为政,不再关心全局的架构设计。

  从这个角度上看,使用微服务架构同时也需要组织结构做相应的调整。所以说做微服务改造需要管理者的支持。

  改造完成后,小明和小红分清楚各自的锅。两人十分满意,一切就像是麦克斯韦方程组一样漂亮完美。

  春天来了,万物复苏,又到了一年一度的购物狂欢节。眼看着日订单数量蹭蹭地上涨,小皮小明小红喜笑颜开。可惜好景不长,乐极生悲,突然嘣的一下,系统挂了。

  以往单体应用,排查问题通常是看一下日志,研究错误信息和调用堆栈。而微服务架构整个应用分散成多个服务,定位故障点非常困难。小明一个台机器一台机器地查看日志,一个服务一个服务地手工调用。经过十几分钟的查找,小明终于定位到故障点:促销服务由于接收的请求量太大而停止响应了。其他服务都直接或间接地会调用促销服务,于是也跟着宕机了。在微服务架构中,一个服务故障可能会产生雪崩效用,导致整个系统故障。其实在节前,小明和小红是有做过请求量评估的。按照预计,服务器资源是足以支持节日的请求量的,所以肯定是哪里出了问题。不过形势紧急,随着每一分每一秒流逝的都是白花花的银子,因此小明也没时间排查问题,当机立断在云上新建了几台虚拟机,然后一台一台地部署新的促销服务节点。几分钟的操作后,系统总算是勉强恢复正常了。整个故障时间内估计损失了几十万的销售额,三人的心在滴血……

  事后,小明简单写了个日志分析工具(量太大了,文本编辑器几乎打不开,打开了肉眼也看不过来),统计了促销服务的访问日志,发现在故障期间,商品服务由于代码问题,在某些场景下会对促销服务发起大量请求。这个问题并不复杂,小明手指抖一抖,修复了这个价值几十万的Bug。

  问题是解决了,但谁也无法保证不会再发生类似的其他问题。微服务架构虽然逻辑设计上看是完美的,但就像积木搭建的华丽宫殿一样,经不起风吹草动。微服务架构虽然解决了旧问题,也引入了新的问题:

  小明小红痛定思痛,决心好好解决这些问题。对故障的处理一般从两方面入手,一方面尽量减少故障发生的概率,另一方面降低故障造成的影响。

  在高并发分布式的场景下,故障经常是突然间就雪崩式爆发。所以必须建立完善的监控体系,尽可能发现故障的征兆。

  微服务架构中组件繁多,各个组件所需要监控的指标不同。比如Redis缓存一般监控占用内存值、网络流量,数据库监控连接数、磁盘空间,业务服务监控并发数、响应延迟、错误率等。因此如果做一个大而全的监控系统来监控各个组件是不大现实的,而且扩展性会很差。一般的做法是让各个组件提供报告自己当前状态的接口(metrics接口),这个接口输出的数据格式应该是一致的。然后部署一个指标采集器组件,定时从这些接口获取并保持组件状态,同时提供查询服务。最后还需要一个UI,从指标采集器查询各项指标,绘制监控界面或者根据阈值发出告警。

  大部分组件都不需要自己动手开发,网络上有开源组件。小明下载了RedisExporter和MySQLExporter,这两个组件分别提供了Redis缓存和MySQL数据库的指标接口。微服务则根据各个服务的业务逻辑实现自定义的指标接口。然后小明采用Prometheus作为指标采集器,Grafana配置监控界面和邮件告警。这样一套微服务监控系统就搭建起来了:

  在微服务架构下,一个用户的请求往往涉及多个内部服务调用。为了方便定位问题,需要能够记录每个用户请求时,微服务内部产生了多少服务调用,及其调用关系。这个叫做链路跟踪。

  从图中可以看到,这是一个用户访问productpage页面的请求。在请求过程中,productpage服务顺序调用了details和reviews服务的接口。而reviews服务在响应过程中又调用了ratings的接口。整个链路跟踪的记录是一棵树:

  要实现链路跟踪,每次服务调用会在HTTP的HEADERS中记录至少记录四项数据:

  以上只是一个极简的说明,关于链路跟踪的理论依据可详见Google的Dapper

  了解了理论基础后,小明选用了Dapper的一个开源实现Zipkin。然后手指一抖,写了个HTTP请求的,在每次HTTP请求时生成这些数据注入到HEADERS,同时异步发送调用日志到Zipkin的日志收集器中。这里额外提一下,HTTP请求的,可以在微服务的代码中实现,也可以使用一个网络代理组件来实现(不过这样子每个微服务都需要加一层代理)。

  链路跟踪只能定位到哪个服务出现问题,不能提供具体的错误信息。查找具体的错误信息的能力则需要由日志分析组件来提供。

  日志分析组件应该在微服务兴起之前就被广泛使用了。即使单体应用架构,当访问数变大、或服务器规模增多时,日志文件的大小会膨胀到难以用文本编辑器进行访问,更糟的是它们分散在多台服务器上面。排查一个问题,需要登录到各台服务器去获取日志文件,一个一个地查找(而且打开、查找都很慢)想要的日志信息。

  因此,在应用规模变大时,我们需要一个日志的“搜索引擎”。以便于能准确的找到想要的日志。另外,数据源一侧还需要收集日志的组件和展示结果的UI组件:

  小明调查了一下,使用了大名鼎鼎地ELK日志分析组件。ELK是Elasticsearch、Logstash和Kibana三个组件的缩写。

  最后还有一个小问题是如何将日志发送到Logstash。一种方案是在日志输出的时候直接调用Logstash接口将日志发送过去。这样一来又(咦,为啥要用“又”)要修改代码……于是小明选用了另一种方案:日志仍然输出到文件,每个服务里再部署个Agent扫描日志文件然后输出给Logstash。

  拆分成微服务后,出现大量的服务,大量的接口,使得整个调用关系乱糟糟的。经常在开发过程中,写着写着,忽然想不起某个数据应该调用哪个服务。或者写歪了,调用了不该调用的服务,本来一个只读的功能结果修改了数据……

  为了应对这些情况,微服务的调用需要一个把关的东西,也就是网关。在调用者和被调用者中间加一层网关,每次调用时进行权限校验。另外,网关也可以作为一个提供服务接口文档的平台。

  使用网关有一个问题就是要决定在多大粒度上使用:最粗粒度的方案是整个微服务一个网关,微服务外部通过网关访问微服务,微服务内部则直接调用;最细粒度则是所有调用,不管是微服务内部调用或者来自外部的调用,都必须通过网关。折中的方案是按照业务领域将微服务分成几个区,区内直接调用,区间通过网关调用。

  前面的组件,都是旨在降低故障发生的可能性。然而故障总是会发生的,所以另一个需要研究的是如何降低故障产生的影响。

  最粗暴的(也是最常用的)故障处理策略就是冗余。一般来说,一个服务都会部署多个实例,这样一来能够分担压力提高性能,二来即使一个实例挂了其他实例还能响应。

  冗余的一个问题是使用几个冗余?这个问题在时间轴上并没有一个切确的答案。根据服务功能、时间段的不同,需要不同数量的实例。比如在平日里,可能4个实例已经够用;而在促销活动时,流量大增,可能需要40个实例。因此冗余数量并不是一个固定的值,而是根据需要实时调整的。

  操作只有两步,但如果注册到负载均衡或DNS的操作为人工操作的话,那事情就不简单了。想想新增40个实例后,要手工输入40个IP的感觉……

  解决这个问题的方案是服务自动注册与发现。首先,需要部署一个服务发现服务,它提供所有已注册服务的地址信息的服务。DNS也算是一种服务发现服务。然后各个应用服务在启动时自动将自己注册到服务发现服务上。并且应用服务启动后会实时(定期)从服务发现服务同步各个应用服务的地址列表到本地。服务发现服务也会定期检查应用服务的健康状态,去掉不健康的实例地址。这样新增实例时只需要部署新实例,实例下线时直接关停服务即可,服务发现会自动检查服务实例的增减。

  服务发现还会跟客户端负载均衡配合使用。由于应用服务已经同步服务地址列表在本地了,所以访问微服务时,可以自己决定负载策略。甚至可以在服务注册时加入一些元数据(服务版本等信息),客户端负载则根据这些元数据进行流量控制,实现A/B测试、蓝绿发布等功能。

  服务发现有很多组件可以选择,比如说Zookeeper 、Eureka、Consul、Etcd等。不过小明觉得自己水平不错,想炫技,于是基于Redis自己写了一个……

  当一个服务因为各种原因停止响应时,调用方通常会等待一段时间,然后超时或者收到错误返回。如果调用链路比较长,可能会导致请求堆积,整条链路占用大量资源一直在等待下游响应。所以当多次访问一个服务失败时,应熔断,标记该服务已停止工作,直接返回错误。直至该服务恢复正常后再重新建立连接。

  当下游服务停止工作后,如果该服务并非核心业务,则上游服务应该降级,以保证核心业务不中断。比如网上超市下单界面有一个推荐商品凑单的功能,当推荐模块挂了后,下单功能不能一起挂掉,只需要暂时关闭推荐功能即可。

  一个服务挂掉后,上游服务或者用户一般会习惯性地重试访问。这导致一旦服务恢复正常,很可能因为瞬间网络流量过大又立刻挂掉,在棺材里重复着仰卧起坐。因此服务需要能够自我保护——限流。限流策略有很多,最简单的比如当单位时间内请求数过多时,丢弃多余的请求。另外,也可以考虑分区限流。仅拒绝来自产生大量请求的服务的请求。例如商品服务和订单服务都需要访问促销服务,商品服务由于代码问题发起了大量请求,促销服务则只限制来自商品服务的请求,来自订单服务的请求则正常响应。

  三种测试从上到下实施的容易程度递增,但是测试效果递减。端到端测试最费时费力,但是通过测试后我们对系统最有信心。单元测试最容易实施,效率也最高,但是测试后不能保证整个系统没有问题。

  由于端到端测试实施难度较大,一般只对核心功能做端到端测试。一旦端到端测试失败,则需要将其分解到单元测试:则分析失败原因,然后编写单元测试来重现这个问题,这样未来我们便可以更快地捕获同样的错误。

  服务测试的难度在于服务会经常依赖一些其他服务。这个问题可以通过Mock Server解决:

  单元测试大家都很熟悉了。我们一般会编写大量的单元测试(包括回归测试)尽量覆盖所有代码。

  指标接口、链路跟踪注入、日志引流、服务注册发现、路由规则等组件以及熔断、限流等功能都需要在应用服务上添加一些对接代码。如果让每个应用服务自己实现是非常耗时耗力的。基于DRY的原则,小明开发了一套微服务框架,将与各个组件对接的代码和另外一些公共代码抽离到框架中,所有的应用服务都统一使用这套框架进行开发。

  使用微服务框架可以实现很多自定义的功能。甚至可以将程序调用堆栈信息注入到链路跟踪,实现代码级别的链路跟踪。或者输出线程池、连接池的状态信息,实时监控服务底层状态。

  使用统一的微服务框架有一个比较严重的问题:框架更新成本很高。每次框架升级,都需要所有应用服务配合升级。当然,一般会使用兼容方案,留出一段并行时间等待所有应用服务升级。但是如果应用服务非常多时,升级时间可能会非常漫长。并且有一些很稳定几乎不更新的应用服务,其负责人可能会拒绝升级……因此,使用统一微服务框架需要完善的版本管理方法和开发管理规范。

  另一种抽象公共代码的方法是直接将这些代码抽象到一个反向代理组件。每个服务都额外部署这个代理组件,所有出站入站的流量都通过该组件进行处理和转发。这个组件被称为Sidecar。

  Sidecar只负责网络通信。还需要有个组件来统一管理所有sidecar的配置。在Service Mesh中,负责网络通信的部分叫数据平面(data plane),负责配置管理的部分叫控制平面(control plane)。数据平面和控制平面构成了Service Mesh的基本架构。

  Sevice Mesh相比于微服务框架的优点在于它不侵入代码,升级和维护更方便。它经常被诟病的则是性能问题。即使回环网络不会产生实际的网络请求,但仍然有内存拷贝的额外成本。另外有一些集中式的流量处理也会影响性能。

  微服务不是架构演变的终点。往细走还有Serverless、FaaS等方向。另一方面也有人在唱合久必分分久必合,重新发现单体架构……

  不管怎样,微服务架构的改造暂时告一段落了。小明满足地摸了摸日益光滑的脑袋,打算这个周末休息一下约小红喝杯咖啡。

  微服务的核心是服务治理,而服务治理的关键是服务划分。故微服务架构的本质就是对码农的分化和治理。微服务对于互联网产业的意义就像流水线标准化生产模式对于制造业一样具有革命性。福特汽车发明流水线标准化生产模式改变了制造业工程师和工人的治理模式及责任划分,使组织大规模成批量工业生产更为简单。而微服务架构也可以使大型互联网公司更容易建设面对海量用户的互联网服务系统。因此微服务架构是让互联网产业模式逐渐靠向传统制造业的标志。

  在早期互联网发展中,一般采用单体开发模式。例如开发一个在线购物商城,单体开发模式最多把整个项目分为前端后端两部分(前后分离),后端开发则是由一批程序员从数据库设计开始再到业务层如用户注册,店铺管理,商品管理,商品展示,订单支付,物流管理,评价系统等模块顺序延伸开发,最终所有模块开发完成的代码合并在一起统一编译部署上线。在单体开发中大部分程序员都可以全面理解整个业务构成并随着开发时间轴推进参与到各个模块的开发。这就如同早期汽车厂的生产一般是工人们先造发动机再造变速器后车身最后再组装的模式一样,所有工人工程师贯穿整个生产流程。

  单台服务器(单体程序)一旦有一处错误,经常整个网站就得停止运转,其次随着互联网发展的深入和业务量的增长,单台服务器和单个程序已很难响应巨大的访问流量,这时集群模式就登上了舞台。不过集群模式也相对容易,简单来说就是把一个单体程序同时部署在多台服务器产生一堆节点,然后再用诸如Nginx这类代理工具以一定的规则(例如对IP地址哈希)把请求分散到不同的节点,类似的还有数据库读写分离主从互备等等,总而言之就是把单体时代的单台单个镜像复制到多台,程序开发需要顺序进行无法分割的本质并没有改变。用汽车制造来举例子就是多开几家工厂,但每家工厂还是先造发动机再造变速器后造车身最后再组装得贯穿式生产模式。

  随着互联网产业的发展,一些公司的业务已经非常庞大,如果还是单体开发批量部署的模式显然很难进行有效管理。这时就有一些企业从业务层面分割原有系统,比如对电商平台可以把以前完整统一的系统分割为商品展示,用户管理和支付平台三大部分。每个部分单独开发独立部署,他们之间使用轻量的API调用进行数据交互。这样每个部分都可以由不同的团队互不干扰的独立开发,只要彼此遵守事先约定的规则。而不同的业务所耗费的资源也有差异,服务拆分之后可以根据不同业务的负载分别调整每一部分的服务器投入。这就是微服务架构的雏形。如同汽车工厂把发动机,变速器和车身交给不同工厂同时进行生产研发,然后再统一调度总装生产。

  在把完整系统根据业务拆分为几大独立系统的基础上,再进一步对各个业务进行更细粒度的拆分,比如把商品展示再分为商品图片上传,图片审核,图片处理,评价查看,评价管理,评价删除,购物车查看,购物车添加,购物车清零等等子服务就是微服务的实践。每一个服务都由独立的团队开发维护就像汽车工业进一步把发动机,车身,车轴三大工厂拆分为曲轴,活塞,缸体,轴承,轮毂,车架,车门,玻璃等等小工厂,各个工厂负责一项零部件的研发生产,然后再通过逐级流水线装配形成汽车。

  因此我们可以看出互联网的微服务架构和汽车工业的标准化流水线生产非常相似,所以微服务对于互联网工程师工作形式的改变也会如同汽车工程师一样越来越细分化。150年前的汽车工程师可能需要了解整车,100年前的汽车工程师需要掌握发动机或变速器里一个大部件,而今天的汽车工程师则可能只会了解曲轴或活塞这样的单一部件。20年前面向业务编程的程序员基本全业务都要了解,而今天的面向业务程序员则逐渐开始分化为例如支付领域,直播平台领域,电商领域等等。

  汽车产业中每个零件通常都有多个供应商,多个供应商也可能会拥有数条生产线,每个供应商或生产线虽然生产同样规格标准的零件但也可以通过不同的设备不同的工艺达成。微服务架构也类似,每个微服务实例可以同时多个节点部署,比如电商平台的评价系统可以同时部署在多台服务器上,而每个服务器上又部署多个实例。这样一两台服务器出现宕机不会影响整个电商平台集团业务的运转。而每个服务实例也可以用不同语言不同框架编写只要他们对外暴露同样的接口。

  同样的服务实例可以由不同的语言不同的框架实现并同时上线就意味着可以在整个系统运行中对服务进行无需停机的热升级,那也意味着系统升级的代价几乎可以忽略不计,而且同一个服务也可以由多个技术团队分别实现。这样新手程序员无需了解整个系统的架构和体系就可以快速参与到系统开发升级中,他们开发的服务实例也可以以渐进形式取代旧团队开发的既有实例,一旦有问题可以迅速回退补救。完全可以等新团队的实例在使用中经受住了测试再把新团队的实例负载比例提高到50%以上,然后把旧团队的薪资过高老人优化掉,在维持平稳的前提下为公司降低薪资支出优化技术人员结构。微服务架构把整业务解耦和拆分其实极大降低了大型互联网系统的开发和管理难度。每一个服务实例都可以通过多个团队的竞争选取最优,也方便进行外包,这是大型互联网公司非常希望看到的。

  微服务架构概念就是制造业的零件标准化渗透到互联网产业,当越来越多的软件工程师只能把工作范围缩小到部分服务后,这意味着他们的竞争指标细化,码农的互换性和可替代性也会快速提高,他们的流动性对整个系统的稳定性冲击也会变小,这意味着面向业务编程的互联网工程师薪资议价权会同制造业工程师一样越来越弱。

  零件标准化也会带来通用化,比如很多汽车厂都会采购同一个工厂的同一种零件,单个零件产量越大成本越低技术越成熟。那各个互联网企业的一些通用服务是不是也会在未来被整合到一起,重复造轮子的企业会越来越少?现在各个互联网巨头都在搞云计算,他们的云平台也提供了大量符合微服务概念的服务计量出售,比如现在可以在腾讯云阿里云买到短信验证,对象存储,视频点播直播等大量成熟基础服务。在微服务架构下,建一个B站这样的视频网站就可以找几个外包团队融合云平台的接口做好各个服务实例打成容器镜像,然后交给云平台自动编排弹性伸缩服务。所以目前重新建一个B站的壁垒不是技术而是市场和资本。

  总结: 微服务架构之于大型互联网公司就像流水线模式对于富士康这样的大型电子厂。每个服务就是一个工位,大部分码农只能在长期在同一个工位上干一些随时可以被取代也毫无技术含量的活。而越来越多常用业务功能也会以各种形式被互联网巨头做到白菜价以标准品出售。参照非标制造是制造业待遇相对较好的情况,那么游戏这种实时性要求高无法采用微服务架构的非标开发可能也会相对更好。

  微服务架构区别于传统的单体软件架构,是一种为了适应当前互联网后台服务的「三高需求:高并发、高性能、高可用」而产生的的软件架构。

  由于工作需要,本人曾调研过微服务相关内容,其实微服务也没什么神秘的,今天就用图解的形式了来和大家唠唠什么是微服务?

  与微服务相对的另一个概念是传统的单体式应用程序( Monolithic application ),单体式应用内部包含了所有需要的服务。而且各个服务功能模块有很强的耦合性,也就是相互依赖彼此,很难拆分和扩容。

  说在做的各位都写过单体程序,大家都没意见吧?给大家举个栗子,刚开始写代码你写的helloworld程序就是单体程序,一个程序包含所有功能,虽然 helloworld 功能很简单。

  单体程序的缺点一开始不是特别明显,项目刚开始需求少,业务逻辑简单,写代码一时爽,一直爽。噩梦从业务迭代更新,系统日益庞大开始,前期的爽没有了,取而代之的是软件维护和迭代更新的无尽痛苦。

  由于单体式应用程序就像一个大型容器一样,里面放置了许多服务,且他们都是密不可分的,这导致应用程序在扩展时必须以「应用程序」为单位。

  当里面有个业务模块负载过高时,并不能够单独扩展该服务,必须扩展整个应用程序(就是这么霸道),这可能导致额外的资源浪费。

  此外,单体式应用程序由于服务之间的紧密度、相依性过高,这将导致测试、升级有所困难,且开发曲线有可能会在后期大幅度地上升,令开发不易。相较之下「微服务架构」能够解决这个问题。

  微服务 (Microservices) 就是一些协同工作小而自治的服务。

  2014年,Martin FowlerJames Lewis共同提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通信。同时服务会使用最小的规模的集中管理 (例如Docker) 能力,服务可以用不同的编程语言与数据库等组件实现 。「」

  还是拿前面的 helloworld 程序来举栗子,想象一下你是 helloworld 公司的 CTO(老板还缺人吗?会写代码的那种),假设你们公司的 helloworld 业务遍布全球,需要编写不同语种的 helloworld 版本,分别输出英语、日语、法语、俄语...现在世界有6000多种语言(奇怪的知识又增加了)。

  有人会说这还不简单我用switch case语句就完事了,同学,不要较真我就是举个例子,现实中的业务比 helloworld 复杂多了。好了,我们姑且认为按语言输出是个庞大复杂的工作,这时候就可以用微服务架构了,架构图如下:

  面向服务的体系结构SOA (Service-Oriented Architecture)听起来和微服务很像,但SOA早期均使用了总线模式,这种总线模式是与某种技术栈强绑定的,比如:J2EE。这导致很多企业的遗留系统很难对接,切换时间太长,成本太高,新系统稳定性的收敛也需要一些时间,最终SOA看起来很美,但却成为了企业级奢侈品,中小公司都望而生畏。

  此外,实施SOA时会遇到很多问题,比如通信协议(例如SOAP)的选择、第三方中间件如何选择、服务粒度如何确定等,目前也存在一些关于如何划分系统的指导性原则,但其中有很多都是错误的。SOA并没有告诉你如何划分单体应用成微服务,所以在实施SOA时会遇到很多问题。

  这些问题再微服务框架中得到很好的解决,你可以认为微服务架构是SOA的一种特定方法。

  合久必分,鉴于「单体应用程序」有上述的缺点,单个应用程序被划分成各种小的、互相连接的微服务,一个微服务完成一个比较单一的功能,相互之间保持独立和解耦合,这就是微服务架构。

  不同服务内部的开发技术可以不一致,你可以用java来开发helloworld服务A,用golang来开发helloworld服务B,大家再也不用为哪种语言是世界上最好的语言而争论不休。

  为不同的服务选择最适合该服务的技术,系统中不同部分也可以使用不同的存储技术,比如A服务可以选择redis存储,B服务你可以选择用MySQL存储,这都是允许的,你的服务你做主。

  一个服务不可用不会导致另一个服务也瘫痪,因为各个服务是相互独立和自治的系统。这在单体应用程序中是做不到的,单体应用程序中某个模块瘫痪,必将导致整个系统不可用,当然,单体程序也可以在不同机器上部署同样的程序来实现备份,不过,同样存在上面说的资源浪费问题。

  庞大的单体服务如果出现性能瓶颈只能对软件整体进行扩展,可能真正影响性能的只是其中一个很小的模块,我们也不得不付出升级整个应用的代价。这在微服务架构中得到了改善,你可以只对那些影响性能的服务做扩展升级,这样对症下药的效果是很好的。

  如果你的服务是一个超大的单体服务,有几百万行代码,即使修改了几行代码也要重新编译整个应用,这显然是非常繁琐的,而且软件变更带来的不确定性非常高,软件部署的影响也非常大。在微服务架构中,各个服务的部署是独立的,如果真出了问题也只是影响单个服务,可以快速回滚版本解决。

  微服务架构中单个服务的代码量不会很大,这样当你需要重构或者优化这部分服务的时候,就会容易很多,毕竟,代码量越少意味着代码改动带来的影响越可控。

  我们上面一直在强调微服务的好处,但是,微服务架构不是万能的,并不能解决所有问题,其实这也是微服务把单体应用拆分成很多小的分布式服务导致的,所谓人多手杂,服务多起来管理的不好各种问题就来了。

  微服务之间相互调用完成整体业务功能,如何在众多微服务中找到正确的目标服务地址,这就是所谓「服务发现」功能。

  常用的做法是服务提供方启动的时候把自己的地址上报给「服务注册中心」,这就是「服务注册」。服务调用方「订阅」服务变更「通知」,动态的接收服务注册中心推送的服务地址列表,以后想找哪个服务直接发给他就可以。

  单体程序的监控运维还好说,大型微服务架构的服务运维是一大挑战。服务运维人员需要实时的掌握服务运行中的各种状态,最好有个控制面板能看到服务的内存使用率、调用次数、健康状况等信息。

  这就需要我们有一套完备的服务监控体系,包括拓扑关系、监控(Metrics)、日志监控(Logging)、调用追踪(Trace)、告警通知、健康检查等,防患于未然。

  任何服务都不能保证100%不出问题,生产环境复杂多变,服务运行过程中不可避免的发生各种故障(宕机、过载等等),工程师能够做的是在故障发生时尽可能降低影响范围、尽快恢复正常服务。

  程序员为此避免被祭天,需要引入「熔断、隔离、限流和降级、超时机制」等「服务容错」机制来保证服务持续可用性。

  有些服务的敏感数据存在安全问题,「服务安全」就是对敏感服务采用安全鉴权机制,对服务的访问需要进行相应的身份验证和授权,防止数据泄露的风险,安全是一个长久的话题,在微服务中也有很多工作要做。

  说到「治理」一般都是有问题才需要治理,我们平常说环境治理、污染治理一个意思,微服务架构中的微服务越来越多,上面说的那些问题就更加显现,为了解决上面微服务架构缺陷「服务治理」就出现了。

  微服务的那些问题都要公司技术团队自己解决的话,如果不是大型公司有成熟的技术团队,估计会很头大。幸好,有巨人的肩膀可以借给我们站上去,通过引入「微服务框架」来帮助我们完成服务治理。

  是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。 Apache Dubbo ˈdʌbəʊ 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现 。2011 年末对外开源,仅支持 Java 语言。

  腾讯内部使用的微服务架构 TAF(Total Application Framework)多年的实践成果总结而成的开源项目。 仅支持 C++ 语言,目前在腾讯内部应用也非常广泛。2017 年对外开源,仅支持 C++ 语言。

  是新浪微博开源的一个Java 框架。Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。于 2016 年对外开源,仅支持 Java 语言。

  是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发。本身它不是分布式的,所以要实现上面的框架的功能需要进一步的开发。2015 年对外开源的跨语言 RPC 框架,支持多种语言。

  最初是由 Facebook 开发的内部系统跨语言的高性能 RPC 框架,2007 年贡献给了 Apache 基金,成为 Apache 开源项目之一, 跟 gRPC 一样,Thrift 也有一套自己的接口定义语言 IDL,可以通过代码生成器,生成各种编程语言的 Client 端和 Server 端的 SDK 代码,支持多种语言。

  很多人对这两个概念有点混淆,微服务框架上面我们说过了,我们再来看下RPC的概念。

  RPC (Remote Procedure Call)远程过程调用是一个计算机通信协议。我们一般的程序调用是本地程序内部的调用,RPC允许你像调用本地函数一样去调用另一个程序的函数,这中间会涉及网络通信和进程间通信,但你无需知道实现细节,RPC框架为你屏蔽了底层实现。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统。

  RPC和微服务框架的关系我的理解,微服务框架一般都包含了RPC的实现和一系列「服务治理」能力,是一套软件开发框架。我们可以基于这个框架之上实现自己的微服务,方便的利用微服务框架提供的「服务治理」能力和RPC能力,所以微服务框架也被有些人称作RPC框架。

  Service Mesh(服务网格)被认为是下一代微服务架构,Service Mesh并没有给我们带来新的功能,它是用于解决其他工具已经解决过的服务网络调用、限流、熔断和监控等问题,只不过这次是在Cloud Native的kubernetes环境下的实现。

  为什么现有微服务架构已经解决的问题还要用Service Mesh呢?这个问题问的好。

  回答问题之前,先看下istio.io上对service mesh的解释,我觉得挺好的,摘抄出来:

  试着总结一下:随着微服务的增多复杂程度也增加,管理变得更加困难,微服务架构虽然解决了「网络调用、限流、熔断和监控」等问题,但大多数框架和开源软件对原有业务是侵入式的,也就是需要在业务服务程序中集成相关的「服务治理」组件。

  Service Mesh之于微服务,就像TCP/IP之于互联网,TCP/IP为网络通信提供了面向连接的、可靠的、基于字节流的基础通信功能,你不再需要关心底层的重传、校验、流量控制、拥塞控制。

  用了Service Mesh你也不必去操心「服务治理」的细节,不需要对服务做特殊的改造,所有业务之外的功能都由Service Mesh帮你去做了。它就像一个轻量级网络代理对应用程序来说是透明,所有应用程序间的流量都会通过它,所以对应用程序流量的控制都可以在serivce mesh中实现 。

  在IT世界没有什么技术是永不过时的,微服务架构的演进就是一个例子,从单体程序到微服务架构,再到service mesh架构,我不知道下一个技术迭代点是什么时候,但我知道微服务架构肯定还会更新,IT人更应该建立终身学习习惯。 当然更重要的是拥有对技术的热情,热于拥抱变化、接受新技术,当我看到新技术我是兴奋的,内心os是厉害了,还能这么玩!,希望你也有这般热情,而不仅仅是面向工资编程,生活会有趣很多。

  这个回答原文是我之前写的一篇关于微服务的科普,回答中可能有些删减,原文下面查看:

  另外,我当初在准备各大公司技术笔试的时候刷了大量的算法题,其中就是参考了一本谷歌大神的LeetCode刷题笔记,帮我整理了解题思路,归纳了出刷题方法,非常不出错,BAT刷题必备:

  最后,来分享一个看过的计算机教材,包含浙大计算机专业 4年的课件+教材+试卷+资料,应该能给你点学习方向。

  本身用的较多的是腾讯自研 TARS 框架,这个RPC框架的 23 页详细介绍 PPT 已下载,评论区已经有人给出了下载地址,感兴趣可自取~

  “微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间相互协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务和服务之间采用轻量级的通信机制相互沟通(通常是基于HTTP的Restful API).每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构---- Martin Fowler的博客

  微服务的拆分一般会带来IPC通信的问题。通信机制需要完备可靠,服务之间的通信选择应尽量单一,从两个维度对通信的模式进行划分:

  微服务架构认为,服务间通信应该就只有这几种模式。AC出于时延、编程模型等方面的考虑,提供了一套通信机制,业务之间的通信要按需选用。

  一般的微服务架构里都有两层API GetWay,一层是外部API GetWay,用于用户访问系统;一层是内部API GetWay,内部服务之间的API GetWay。内部API GetWay要解决的问题就是服务发现和服务注册。从这也能看出来,为什么通信的方式要尽量单一,API GetWay有一项工作就是协议转换。

  微服务可能是HA主备的,也可能是LB的,怎么找到一个服务?有两种思路,客户端发现(左图),客户端去注册中心查询服务实例列表,自行选择;另一种是服务端发现(右图),添加LB模块,客户端把请求发向LB,由LB根据负载均衡策略选择服务实例;

  ETCD : 是一个高可用,分布式的,一致性的,键值表,用于共享配置和服务发现。两个著名案例包括Kubernetes和Cloud Foundry。ZK: 是一个广泛使用,为分布式应用提供高性能整合的服务。Apache ZooKeeper最初是Hadoop的子项目,现在已经变成顶级项目。

  部署速率,Amazon与NetFlix都有千个服务,每个服务都有持续部署的要求,Amazon的服务每秒都会部署一次;

  部署自动化,一切都要自动化,IaaS与PaaS解决I层与P层自动化部署,微服务有自动部署与运维工具,并实现Auto-Scaling;

  部署提供基础机制,为实现分布式部署要求,部署机制一般都有资源池化、服务的生命周期来看,部署服务 与服务注册是一体的;

  VM: 部署系统管理的VM的生命周期,如当前AC的iDeploy部署,把AC部署拆分为每个VM的安装、配置与启动;这种方式粒度粗,支撑不了微服务的部署(除非一个服务占用一个VM);

  App: 管理应用的生命周期及部署形态,生命周期分为部署、配置、启动、升级等,部署形态有主备、LB、Daemon等;

  微服务:一般的微服务要么是APP,要么是Container,但AC就不是。受限于ONOS架构,我们的服务是一组feature;

  TOSCA: 云应用拓扑标准,一种描述云化部署的DSL,我司主推一个标准,PaaS的部署系统和MANO用的都是TOSCA;

  Mesosphere:DCOS,数据中心操作系统,基于mesos实现资源池化,有自身的编排工具;分布式LAB基于DCOS的思想做出了一套部署与集群管理系统(HASEN);

  微服务的划分主要是保证微服务功能内聚,职责单一。一般使用DDD(Domain Drive Design)的思想与方法对微服务进行划分,这种方法有点类似于数据库ER图的划分,不断分解数据,保证关系型数据库符合原子性、冗余性的范式要求。当然,微服务的划分比数据表划分更复杂,也没有微服务范式的概念,但思想是一致的。更多的内容,请参考《领域驱动设计》这本书。

  事件驱动,忽略了事务的概念,由每个服务在应用层面保存服务的状态,服务之间的通信使用事件机制通知;此种方法可以保证微服务间的独立性,但把问题交给了服务的设计者;具体事件驱动的案例见参考材料;

  因为微服务架构本身的复杂性,初创系统出于快速开发、快速验证的考虑,很少在一开始就使用微服务架构。加之微服务的概念在这两年才火,大型单体应用也是看到了开发与维护的成本在不断增加,才会有转型微服务的动力。因此,如何从单体到微服务是一个普遍问题。

  全部重构,带来极大的成本和风险,系统会有很长的不稳定期。而且,最终的效果也不会很好,在设计时很难想到所有问题。微服务架构的演化思路应该是一步步铺基础设施,一点点拆分微服务。

  DevOps是09年提出来的概念,但一直没有太火。直到14年,容器与微服务架构的提出,DevOps才得到了快速的发展。DevOps不单是一个实现自动化的工具链,而是组织、流程与技术的结合。组织上强调全栈团队、团队特性专一、团队自治;技术上打通开发与运维;流程上强调端到端、可视化、灰度升级、A/B测试等。

  对于DevOps,MS不是必须的,但MS为DevOps提供了最好的架构支撑,对于组织和流程的要求也是一致的。所以,也有人称MS是DevOps架构。

  2020年都快过完了,这时候再说什么是微服务,微服务有什么好处,一点新意都没有。

  架构师大刘日子最近还不错,经常午睡醒来,就继续拿着手机看小说摸鱼。大刘对当前所在的这家公司比较满意。大部分系统已经成熟稳定,用户量也中规中矩。虽然有些项目技术陈旧,但好处是没啥幺蛾子技术问题冒出来等着解决。

  只是有时候大刘心里会打鼓,公司盈利在下降,巅峰不在,也不知道这家公司能撑多久。除了偶然会冒出些对工作稳定的担忧以外,大部分时候,大刘心情都是愉快的。直到他被领导叫到办公室分派新任务的那一刻……

  大刘的领导 CTO 老李,这些日子心情不是很好。他在的这家公司原本是个以传统业务为主的公司。为了跟上互联网时代,大老板拍脑袋成立了个技术部门搞互联网。虽说公司已经号称触网了,但是公司盈利基本还是靠传统业务,技术部门只是打辅助的。没有业务主动权,没有盈利点,部门员工的工资却都不低,老李的地位就可见一般了,经常受些冷言冷语的夹板气。再加上,最近公司的效益也有所下降,眼见技术部门面临着裁员的危险。老李危机意识被极大的刺激到了。

  老李是个技术出身,但是离开一线编码已经快十年了,每天的工作其实就是管理加玩概念。这几年微服务的概念非常火爆,老李一直想着能搞点这种热门东西,然后再拿着这些做出来的新概念技术,给那个不懂技术的大老板展示下自己的两把刷子,同时也能打响在业界的名声,对自己的职业发展也大有好处。趁着构思部门前途这时当,老李认为这也是搞微服务的好时机,同时也想到了有微服务经验的大刘。于是,大刘就被召唤进了办公室……

  这些个老系统当初是按照几万用户量的目标去设计开发的,虽然现在跑着没问题,但是眼光要看长远,产品和技术们将搞一套更高级的东西,目标是这套系统会被几百万人使用。

  大刘来这家公司之前,在某电商大厂干了多年,对微服务在电商系统中的应用这块有实践、有经验。对微服务这块,大刘是吃过猪肉、也见过猪跑,还被猪咬过……嗯,对,还被咬过不止一口两口。所以,对改造微服务这个任务,大刘是硬着头皮接下来的。

  大刘虽然无奈,但是看在工资的份上活还得干。不过槽还是要吐的,于是下班后大刘用了几小时码出了下面这堆心里话。

  最近,经常有同事和我聊微服务,也屡屡期望对公司已有项目进行改造,希望能把所有项目改造成微服务方式。我对此经常很无语,也屡屡对这些人进行劝阻。

  我认为,劝我改造微服务的人之中,有一些人纯粹的对技术痴迷太深。更甚些,我甚至可以说这些人中的某些人就是纯粹的自私自利。搞微服务难道不是为了蹭热点,为自己的简历增色,为下一步跳槽涨薪做准备?何尝想过微服务为公司带来的各种坏处和因此而来的成本提升?另外有些人,则纯粹是被外面铺天盖地的微服务概念给打晕了头,被各种微服务成功故事洗了脑。这些人,把微服务当成了万能药,纯粹就是脑袋犯了糊涂,陷入了唯技术论。

  为了说明微服务不是万能药,这里我们就先要说明下微服务的概念。同时呢,我们也需要诠释清楚微服务的优缺点,看看什么时候用微服务,什么时候不用。

  什么是微服务?对于微服务的定义,网上众说纷纭,并没有一个权威的定义。但是在这些纷繁复杂,云山雾罩的各种微服务洗脑文和说明文之后,总是有一个统一的基本面在:即微服务是一种利用分治法的思想,去把一整套非常复杂的业务逻辑给切分成多个简单的业务问题,并采用模块化方法去实现组合的一种架构方法。

  这么说是不是还很抽象呢?好,咱们再更深入的解释下,并顺便把微服务的优缺点也全部一并说清楚。

  首先,微服务是采用分治法思想,需要对业务逻辑做分解。做完分解后,还需要多个对应的实现模块去实现分解后的业务问题。这些模块的开发和维护,是都需要成本的。如果我们要搞微服务,考虑过开发维护成本吗?

  上面这图表明了,从项目一开始,微服务的代码开发和维护每行平均成本就不少,随着项目规模和系统复杂度的上升,代码的开发和维护平均成本才会缓慢下降并逐渐收敛到某一个值左右恒定。

  而单体项目正好相反,一开始,单体项目的每行代码平均成本是比较低的,随着项目规模和系统复杂度的上升,代码开发和维护成本会慢慢上涨,后续可能复杂度和开发成本会越来越高,一直冲上天际。

  这时候,就不得不迫使人们去找到一种比较合适的方法,能把开发和维护成本降低到项目团队可以承受的程度。

  有很多的架构师或者技术人员,在一开始做架构和系统设计的时候,不考虑实际情况,在公司给出一项很紧迫的任务之后,不去考虑实现时间和开发成本,上来就搞高大上,起手就是微服务,这现实吗?

  我们这些技术人员看过许多鼓吹微服务的技术书籍,也看到过很多微服务的“成功学”,但是他们的前提是什么?他们对微服务的说法统统是建立在一个只有技术存在的完美世界里,把现实世界他们认为的一切杂音都摒除在外,这合适吗?

  我们在做架构师之前,第一个考虑的应该是投入和产出。固然,我们从技术角度考虑,一定会要考虑可扩展性,可维护性之类的技术指标。但是,我们也需要根据当前项目的重要程度,盈利前景,还有可用服务器资源等,作出自己的平衡来。

  第二,微服务的另一个优势是弹性化。什么意思呢?就是我们在业务逻辑改变时,那些对应业务逻辑改变的功能的增删改,开发和部署成本很低,可以像弹簧一样,自由的缩减和增加。

  并且,微服务里最佳实践是每个分出的模块应该都有自己的数据库,和别的微服务并不共享任何数据库。所以微服务本身认为,每个微服务模块的数据库都可以不一样。

  如果我们的业务逻辑做了一些调整,比如,我们想要增加一个积分功能,那么,我们只需要再增加一个叫做积分的微服务即可。

  但是,我们承认吧,并不是我们所做的每个系统都足够大,都大到需要分解成更多更小的服务。那些不是太复杂的系统,它们凭什么需要弹性化?凭什么需要切分业务,从而搞出一大堆的项目出来呢?

  另外,微服务的弹性化带来的问题就是,我们需要管理因为弹性化所切分的许多小项目,需要搞出一套易用的自动化管理系统,需要把公司的底层基础设置打造好,请问,这些成本,你准备付出了吗?

  在这个现实的世界里,并不是一切围绕着技术打转的。固然,技术欠债会让我们这些技术从业者感到分外的困扰和难受。可是,假如我们超前超度的使用了我们可能并不需要的超前概念和超前架构,同样会使我们感到痛苦。

  如果我们控制住了自己的技术欲望,我们是不是从自身也控制了一部分技术欠债呢?这是一个架构师应该要思考的地方,也是我们不应该滥用微服务的原因之一。

  第三,微服务起手就是分布式。分布式我承认有各种各样的优点,但是,分布式引发的各种问题和因此需要引入的各种技术解决方案本身也有自身的问题。

  比如,分布式事务。在引入微服务前,我们作为架构师,一定要思考后续是不是可能出现跨服务的事务。兄弟,分布式事务大家都知道有多困难的。

  按照微服务的标准,服务之间的通讯应该尽量采用简单的 RESTFUL 协议。那么,根据这种规范,如果我们采用了微服务方式架构,我们的每个项目都应该搞成 REST 服务。REST 服务本身就是无状态的,现在,如果业务里出现了严重依赖状态的跨服务事务,想想吧,你会面临什么:

  分布式锁方案你是不是要考虑下?分布式互锁后,出现了死锁,你的追踪策略是什么?如果出现了竞争资源,导致服务状态不一致了,你怎么去快速恢复?数据腐蚀你有办法吗?

  什么?你告诉我我说市面上有很多成熟的分布式事务解决方案?别自欺欺人了,咱们都是搞技术的,请问,你说的是两阶段提交(2PC)吗?好吧,大家都知道 2PC 那可怜兮兮的性能。

  搞 TCC 或者 SAGA 呢?对不起,因为最终一致性所添加的业务紧耦合的各种消息和通知,会直接犹如 24 小时的梦魇,可能会是压垮你的最后一根稻草。

  对于原来单体项目很简单的事务问题,在微服务中,是一个令人皱眉的困难问题。所有微服务的开发者,在开发微服务代码之前,都需要考虑怎么能探测到数据不一致的问题。否则,一定会万分后悔。

  那么,分布式事务会不会一定会出现在微服务中呢?从目前来看,几乎无法避免。为了搞定这些问题,微服务实现往往还需要伴随着实现一整套构建在无状态服务之上的调用链。

  对于这些额外的开发成本,我们有必要吗?是所有项目都需要的吗?不是吧。这就是我们架构师需要考虑的问题,也是我们需要谨慎和妥协的地方。

  第四,微服务互相之间是通过网络通信配合起来来对外提供服务的。这就会带来一个依赖性问题,即微服务非常依赖底层网络的健康。

  如果网络通信之间出了问题,整体对外的服务质量就会降低到极其让人难以接受的程度。

  并且,网络通信天然就一定会带来延迟。本来单体项目我们好好的,大家都是在内部互相通信,延迟基本可以忽略不计。

  现在,大家分开了,互相得远距离打招呼,延迟动不动就来个几十毫秒几百毫秒延迟。这些延迟,我们也需要考虑在内,必须经过严格的测试才可以。

  另外,网络通信出现问题后的各种容错方案,也必须考虑完善。以上说的这些,也都是一个合格的架构师必须在微服务引入之前,所要进行的综合的考量。

  微服务在上面我也说过了,会带来各种各样的成本的提升,也会引入各种各样的技术问题。这些最终就会导致整体系统复杂性进一步的提高。当复杂性提高的时候,为了保证系统的稳定,就需要整体技术团队的靠谱,就需要技术人员的靠谱,就需要整体技术设施搭建的靠谱。在引入微服务之前,各位兄台麻烦扪心自问下,这些贵公司有吗?有这些团队、这些设施、这些资源吗?

  分布式本身就需要一整套完整的技术体系和设施去支撑整体分布式的建设。比如,以前单体项目只需要一个项目,直接人工上线就好了。现在呢,可能会出现几十个上百个项目,这些项目如果全靠人工去做,会彻底让团队人员疯掉。所以,就需要把整体发布,部署自动化起来。这里还仅仅是发布部署所需要的,还没有谈维护问题,用《征服》刘华强里的一句话说:”你有这个实力吗?”

  微服务本身需要维护和监控,以确保运行的稳定和可靠。在微服务的最佳实践里,是非常推荐搞 DevOps 的。我暂且不说 DevOps 需要的对人员水平的高要求,我就说 DevOps 本身所需要的工作态度和责任心问题,自己家的运维团队搭建是个什么鸟样子,运维成天忙死了再干嘛,谁还不清楚吗?整体运维的平均水准加上开发水平的要求,这个团队搭建下来要花多少钱?公司舍得这些投入吗?

  微服务本身是很复杂的,从设计划分模块开始,就需要架构师必须对架构设计和微服务本身对应的 DDD 领域驱动设计非常有经验,能够恰到好处的划分出对应的模块。否则,一旦设计完毕,不巧把一些紧耦合的服务给硬是解耦成了不同的服务,那么,这个后果对整个技术团队甚至对整个项目团队都是灾难性的。同时,对于微服务的开发、维护、运行、保障以及运维,都需要技术团队成员要有很丰富的从业经验能迅速发现,定位,解决可能随时出现的问题才可以。如果技术问题不能及时解决,那整体系统的体验就可想而知了。但是,现在的经济环境,现在的公司技术人员构成,确定能有这些很丰富经验的人员来搞微服务吗?

  我们上面提到过,为了快速追踪定位死锁或者共享资源的问题,微服务需要靠谱的调用链实现。那么,这就引出的新的问题:我们如何搞全链路测试?我们是不是还得搞一套合适的全链路测试工具才可以?这全链路测试工具开发又需要花多长时间,需要投入多少人力?测试人员的水平是不是也需要得到一定的保证?

  微服务本身有多个节点,这些节点为了自己的安全运行和维护,需要很多自己独有的日志。这些日志随着微服务的增多,也越来越多,你如何存?如何查?如何删?这些是不是都要考虑在内?

  我只是砸给那些劝我没事儿就搞微服务的人。对于这些什么都不考虑,上来就说微服务的人,我认为都是非蠢既坏。

  写完之后,大刘感觉长出了一口胸中的闷气,过完嘴瘾,心里也痛快了。现在大刘最担心的是,这些文字千万别被领导看到……

  大刘的故事讲完了,我再啰嗦一下,微服务肯定是先进的,还是要学习一下的。给大家送上一份资料,里面包括了微服务的部分。

  希望大家看完能明白,并不是什么新科技,热概念都适合自己的团队、自己的项目的。做一个合格的架构师、技术负责人,首先应该遵循的是 KISS 和 YAGNI 原则。

  请各位技术人员永远保持理智,我们要做的是选择正确适用的技术而不是选择自己最喜爱的技术。请不要做那种把简单的事情往复杂里做的技术疯子。