作者 | 朱仕智

修正 | 贾亚宁

本文由极客时刻收拾自去哪儿游览根底架构部高档技能总监朱仕智在 QCon+ 事例研习社的讲演《去哪儿游览微服务架构实践》。

——————————————————

你好,我是朱仕智,在去哪儿网担任根底架构,首要包括后端架构、大前端架构、质量确保、根底云渠道等作业,近期首要在公司落地云原生和数字化管理。

今日我带来的主题是去哪儿游览微服务架构实践。我将从以下几个方面进行介绍:

  1. 布景介绍
  2. 微服务架构方法的最佳实践
  3. 微服务开发功率的提高实践
  4. 微服务管理的实践
  5. ServiceMesh 测验

一、布景介绍

首要介绍一下去哪儿网的事务。去哪儿网是一个典型的在线旅行渠道,它上面的事务繁复,有机票、酒店、度假、火车票、汽车票等等。

去哪儿旅行微服务架构实践

这些事务都有不同的事务流程,其中机票的标准化和线上化是最高的,可是像酒店这样的事务,在线化和标准化就比较低,相同的名字或许是不相同的酒店。这些事务在从产品、库存到整个买卖进程其实都是不相同的,所以这些事务从背后来看仍是相对比较复杂的。

咱们为什么要挑选微服务,其实有以下几个方面的原因。第一个便是事务逐步复杂,最早去哪儿网其实只需机票的比价,并且是一个查找比价,是没有买卖环节的。后来事务扩展就慢慢地发展出来了包括机票、酒店、火车票、度假、汽车票等等其他的事务。

去哪儿旅行微服务架构实践

所以事务是逐步复杂的一个进程,那依照康威定律咱们都知道,事务变化了之后,组织结构要进行相应的调整,组织架构其实也会跟着相应的膨胀,膨胀也会带来协作上和分工上的必定损耗,这也是咱们要挑选微服务的原因之一。

去哪儿旅行微服务架构实践

第三个便是开发功率的低下,咱们之前开发的时分大部分都是以最早的方法,也便是经过 HTTP 协议,加上 JSON 这样的数据结构,然后运用 Nginx 作为网关,把服务管理的这些动作悉数耦合在事务代码里边,比方重试的逻辑等等。这样的话就会导致咱们每一个服务做对应开发的时分,都需求重复性地去考虑这些问题,开发功率相对就会比较低下。

去哪儿旅行微服务架构实践

第四个便是服务质量是比较失控的,由于这些服务质量很难能在一致的一个地方去得到比较有用、及时地处理,就像方才说的管理的逻辑其实是放在了事务代码里边,有一些管理逻辑或许会放在 Nginx 里边,可是 Nginx 是一个大一致的网关,这就意味着当咱们想要去对它进行修正的时分,其实是需求十分谨慎的,这就面对了一个运维和开发诉求不对等的问题。运用微服务咱们以为是可以比较有用地处理这些问题的。

去哪儿旅行微服务架构实践

接着介绍一下咱们去哪儿网的在线数据。咱们现在的运用数据是这样的:活泼的、在线跑着的运用大概有 3000 多个;供给了 18,000 多个 Dubbo 的 RPC 服务接口;有超过 3500 个 HTTP 域名;13,000 多个 MQ 的主题;公司内部大概有 5 种言语的技能栈,当然首要是以 Java 和 Node 为主。

二、微服务架构方法的最佳实践

接下来介绍一下架构方法,架构方法里边有几个方面不同的范畴。

1. 服务发现方法

第一个便是服务发现的方法,服务发现里边其实有三种方法,这三种方法对应不同的适用场景会有不同的效果。

去哪儿旅行微服务架构实践

直联方法,客户端从注册中心发现服务端的列表并缓存在本地,这种方法适宜于言语一致的这种内网通讯,为什么呢?由于直连方法里边大部分 RPC 选用的这样的方法,首要是比较简略、高效,并且在一致言语的内网通讯里边,这种服务端的实例的改变告诉是比较简略的。

去哪儿旅行微服务架构实践

署理方法,服务端注册到网关上,客户端对一个服务端其实是无感知的,这种方法比较适宜于外网服务,为什么呢?是由于当你的服务端改变的时分,客户端其实是不需求去感知,也不需求对此进行任何改变,这样对外网来说,其实用户侧的设备是不需求去关注信息的,这样告诉起来就比较简略。可是它也会面对一个问题,它会多一跳的通讯,从功用或许功率上来说,肯定是不如直连方法的。

去哪儿旅行微服务架构实践

最终一个便是边车方法,Sidecar 去担任注册和发现,运用程序是无感知的,这种比较适宜于多言语、多协议的这种内网通讯,它其实跟直连方法相对来说是比较相似的,可是它其实是由边车的方法代替了事务程序里边混入的这种根底功用,所以简略来看其实便是直连方法里边把公共的根底设施的逻辑下沉到了边车里边。这样的话边车就可以一致地合作咱们的灰度发布或许是其他的热更新的机制,可以做到比较容易地去对这些边车进行升级。

2. 服务通讯方法

接下来咱们说一下服务通讯的方法,服务通讯方法里边首要有两种,咱们其实日常里边比较常常会碰到便是同步的编程方法,这种方法比较简略易懂,十分契合人类的思考习气,它比较适用于时刻比较敏感的、吞吐量也比较小的这种场景。可是这种通讯的方法在吞吐量比较大、QPS 比较高的场景里边就会有一系列的问题,比方说或许会把你的资源耗尽,但其实这些资源都处于等待中。比方咱们在 Java 里边或许会有线程池的资源,运用起来其实是比较低效的。然后在异步的这种场景里边,它其实比较适用于高吞吐、削峰填谷的效果。

其实这儿边会有几种,从咱们的实践上来看的话,比方说查找体系它其实是一个十分高并发的场景,其实关于这种高吞吐的场景下是有必要要用异步的,不然的话其实资源的损耗是十分高的,咱们在某些体系上做过改造,由本来的同步改为异步的话,基本上可以节省掉 80% 左右的机器的资源。除此之外,买卖体系的事情驱动也是比较适宜异步的一个场景,由于买卖体系的事情其实是十分要害的,可是它又不能每个人都去告诉,由于许多人都需求关注这个事情,这个时分利用 MQ 等方法去做这种事情的驱动是比较适宜的。

去哪儿旅行微服务架构实践

封装异步 HttpClient

然后在异步的这个场景里边,去哪儿网其实做了一些自己内部的一些支撑,比方说咱们封装了异步的 HttpClient,把公司内部其他的组件相似于 QTrace,还有一些其他根底的监控、日志等等之类的组件都做了一致的封装埋点。

去哪儿旅行微服务架构实践

改善 Dubbo 异步通讯

第二个咱们对 Dubbo 的异步通讯进行了改善,Dubbo 里边原有的几种通讯方法,其实是调用端和被调用端,是会存在必定的耦合逻辑的。比方说像参数回调这样的方法,其实是调用端需求进行异步,可是被调用端不得不合作这个方法进行改造,所以在这种布景下,咱们对 Dubbo 的异步通讯进行了魔改,其完成在的最新版的 Dubbo 的方法里边,跟这个是比较相似的。

去哪儿旅行微服务架构实践

自研可靠事务音讯行列 QMQ

第三个便是咱们其实内部做了一个自研的音讯行列叫 QMQ,它其实支撑可靠的事务音讯,广泛地运用在咱们去哪儿网的买卖体系里边。

3. 协议

去哪儿旅行微服务架构实践

第三个首要提一下协议这部分,咱们在公司里边首要有三种协议。第一种私有协议,首要担任 App 和外网网关之间的通讯协议;第二个 HTTP 协议,首要是外网网关到 Node、Node 到 Java 之间,乃至有一些 Java 到 Java 之间也会有自己运用的这种 HTTP 协议,不过这种量其实是比较少的;第三个 Dubbo 协议,后端的 Java 服务之间的通讯基本上都是用 Dubbo 为主,只需少数的运用 HTTP。

4. 规划方法

从规划方法上来说的话,咱们其实可以知道在互联网的架构里边,特别是在高并发的方法里边,咱们有许多折中,这些折中里边其实会有不同的方法和它的沉淀。比方说像 BASE 这样的方法,它其实不寻求强一致性,它是有这种基本的可用和软状况这样的长处,进而去防止由于强一致导致的其他的不可用性。

去哪儿旅行微服务架构实践

第二个便是 CQRS,这个方法其实十分有用,至少我发现许多场景是可以用上它的,换句话说其实只需是数据异构的这种场景,都是比较适宜去运用它的,当然这取决于你的查询方法。咱们都知道查询方法其实有许多种的,比方说像 KV 的查询方法、复杂条件的 Query,除此之外,还有 Scan 这种扫描方法,不同的查询方法会对应着不同的存储结构是比较适宜的。可是咱们在对这些数据进行操作的时分,其实它的数据载体是仅有的,那这个数据载体怎样样才干支撑多种的查询方法呢?其实这儿边就需求对这些数据进行异构,比方说像咱们的订单、装备等等这些方法都需求去进行必定的异构。

比方说像去哪儿网内部的话,署理商在去哪儿网上就可以进行必定的调价,调价的装备其实便是一个比较适宜去做数据异构的场景。署理商去录入的时分是比较复杂的,但其实是从航空公司拿到的一个装备,当它放到渠道上来的时分,也是用相同的方法去放,可是关于检索来说的话,用户其实关怀的是这个城市,到这个城市的时分,你的调价规矩是什么姿态,他并不需求一个大一统的调价规矩。所以这儿边就会面对一个数据异构的进程,咱们在这个进程里边其实也运用了 CQRS 这个方法来处理问题。

三、微服务开发功率提高实践

然后我来说一下功率提高的这部分,咱们都知道业界 Spring Cloud 在近期或许是近几年来说是一个最佳实践,特别是在微服务比较火之后,咱们亟需一套成型的处理计划。这个里边包括不同的功用,比方说像散布式的装备、服务的注册、发现、通讯,还有服务的熔断、服务调用、负载均衡、散布式音讯等等。其实咱们可以看到官方的一个完成,当然完成基本上都是来历于 Netflix 的,这儿边会有不同的这些组件,但这些组件其实许多时分或许有一些已经不再维护了。

去哪儿旅行微服务架构实践

对应地可以看到 Spring Cloud Alibaba 也有自己的完成,像 Nacos、Sentinel、Dubbo、RocketMQ 等等。咱们其实就在思考着去哪儿网自己有这么多自研的组件,是否可以适配 Spring Cloud 这样的一套标准,进而去达到开发提效、相互串通组件的目的?

1.Spring Cloud Qunar

去哪儿旅行微服务架构实践

咱们做了一个测验,根据 Spring Cloud 做了装备中心、注册中心、服务管理等等之类的组件的串通,这样的话可以做到比较好的开发方法。然后值得一提的是咱们在 Spring Cloud Qunar 里边,其实供给了两种通讯的方法,一种是前面说到的直联方法,便是由运用本身包括的 SDK 来担任注册、发现和通讯。除此之外,咱们还有一个方法是根据 Sidecar 的这种 Mesh 方法,咱们也可以由 Mesh 的 Sidecar 去担任注册、发现和通讯,这两者之间的敞开其实是比较简略的,只需求有一些特定的注解就可以敞开 Mesh 方法。

去哪儿旅行微服务架构实践

去哪儿旅行微服务架构实践

咱们可以看到这儿边,比方上面的代码,有 Dubbo Service 这样的一个服务的供给,下面就会有 Dubbo Reference 这样的一个服务的引用,并且在注解里咱们可以看到 Qunar Mesh 这样的一个注解,这个注解便是用于敞开咱们的 Mesh 功用的,是关于 Dubbo 这个协议的。关于 HTTP 协议的话,其实跟官方的也是十分相似,咱们也是运用了 OpenFeign 这样的一个组件来进行通讯,下面也相同会有 Qunar Mesh 组件进行 Mesh 化。

2. 开发插件

下面说一下开发插件,咱们为什么要做开发插件,以及开发插件为什么可以做到功率上的提高呢?其实这儿边的话,咱们剖析了许多的事务研制的开发方法,可以发现存在一些重复性或许是低效的环节,比方说像手动编写许多的调用代码,乃至或许会呈现要手写这些反序列化类等等。

第二个便是在交互的进程中许多地去运用相似于文档,或许是内部的 IM,乃至比方说咱们做的比较好的场景下是有 apiDoc 这样的方法去交流这些接口的语义和细节。

第三个便是服务上线之后才去考虑管理,这个里边就会面对开发和运维的不对等。你的服务上线了后,它不出问题时,其实你是很少会去考虑管理的,只需在你开发的时分或许会有必定的考虑,可是这个考虑其实不是根据真实数据的。比方说你设置一个超时时刻,咱们常常可以在代码里边看到 1 秒、30 秒、60 秒等等之类的数字,这些数据真的有意义吗?不必定,只是咱们习气性地这么写,然后还有成百上千个 HttpClient Wrapper,便是自己不停地去完成这些 HttpClient,这些都是一些开发比较低效的场景,咱们怎样处理这个问题呢?

去哪儿旅行微服务架构实践

咱们其实做了一个根据 idea 的 IDE 的开发插件。开发插件它可以满意以下的几个功用,比方像服务调用的代码自动生成,这个是一个什么样的场景?是说当你在 IDE 里边翻开我这个插件,你就可以挑选对方的运用、对方供给的服务,直接就一键生成调用的代码,乃至包括一些其他 jar 包的引进,比方假设它是 Dubbo 协议的,它会自动引进这些 Dubbo 的 SDK 和对方供给的这些 API 的 jar 包等等。

第二它可以快速地发现这些运用接口方法,集成对应的文档服务,这个便是方才说到的咱们其实翻开了这个插件,就能快速地去检索它对应的运用和供给的服务,是比个人交流要高效许多的。

第三它打通了服务管理。在编码生成的进程中,你需求去装备这些管理的参数,然后这些管理的参数经过上报的方法,把它一致地注册到咱们的服务管理渠道,然后跟 Mesh 的方法去进行打通。这样的话有一个十分有用的方法,在你去生成这些调用代码的时分,你就可以参阅一些对应的方针、参数,比方对方供给的接口的监控是什么姿态的,以及其他人设置的方针是什么样的,做必定的智能化引荐,这样可以确保咱们的这些方针相对来说是装备的比较合理的。

第四个便是代码标准的最佳实践是可以比较好去落地的。咱们都知道,许多时分这些代码标准是需求靠文档,比方咱们出一个什么样的标准,什么样的标准去确保,或许是相似利用这些代码查看工具,比方 Sonar 等等之类的方法去确保咱们的代码标准的落地。可是其实经过这种生成代码的方法,咱们直接就可以把最佳实践嵌入到生成的进程里边,来确保它生成的代码必定是契合最佳实践的。

除了上面这四个方面之外,咱们其实还在插件上做了许多的作业,比方说像 CI/CD 的左移,这个左移包括了咱们可以在本地去跟长途的环境打通,以及它还供给了对应的 CI/CD 流水线的功用,还有代码覆盖率的功用等等。经过这样的一个开发插件,咱们可以把日常的一些重复性的、低效性的作业就可以被完成掉,是一个比较好的提效方法,引荐咱们去运用。

四、服务管理实践

然后在服务管理这儿边,咱们其实也做了一些自己的思考。首要咱们来看一下,惯例的这些服务管理的四板斧是什么姿态。

1. 惯例四板斧

去哪儿旅行微服务架构实践

不可防止地,第一,咱们必定要设置超时;第二,要在一些场景里边去考虑重试的逻辑;第三,考虑熔断的逻辑,不要被下流拖死;第四,必定要有限流的逻辑,不要被上游打死。

2. 终究方针

这些都是十分遍及,也是十分有用的一些办法,可是有用树立在于你的装备,或许是你的这个动作是有用的场景,但实际上咱们很大程度上其实是在滥用这四种技能。我以为服务管理的一个终究的方针便是安稳可用、可观测、防堕落,这是什么意思呢?

去哪儿旅行微服务架构实践

安稳可用指的便是咱们经过各类的防控手段去达到在可用的容量场景下,供给有用的服务,这样才干叫安稳可用。第二个可观测,便是咱们从多个维度,比方说像联系、功用、异常、资源等维度对它进行衡量并且剖析。第三个防堕落,咱们的代码和架构其实不可防止地都是在堕落的一个进程之中,咱们不停地往里边去增加东西的进程中,其实也会短少必定的管理。咱们服务管理的方针,其中一点便是要做到如何去对它进行防腐,这个里边有一些考虑的维度,比方服务的层级,你的服务并不是越微越好,也不是层级越多越好,所以服务的层级必定要有所操控。

3. 维护机制

第二便是链路的剖析,链路里边上下流的超时、串行、并行的调用等等之类的这些东西在编码的进程中或许会被疏忽掉的,这些咱们其实可以经过偏后置一点的方法对它进行一个剖析和预警,这儿边提一下咱们在维护机制上做的一些作业,咱们都知道在 RPC 的结构里边,其实特别是在直连的方法下,调用端 Consumer 端和 Provider 端其实是直连通讯的。

关于注册中心来说,它只担任一个注册和改变告诉的效果,可是在有一些特定的场景里边并不是这姿态的。举个例子来说,当一个注册中心由于本身的原因处于一个半死不活的状况,它一瞬间能服务、一瞬间不能服务的时分,就会发生一个比较恐怖的事情,Provider 端由于它要跟注册中心去坚持心跳判活的状况,所以需求和注册中心坚持长期有用的连接。假设是失效的状况,作业中心就会判断这个 Provider 是不存活了。不存活的时分,注册中心就会把这个音讯告诉给 Consumer 端,Consumer 端只需接收过一次下线告诉,Consumer 就会从它的列表里边把这个 Provider 从本地的缓存里边去移除去。

去哪儿旅行微服务架构实践

假设注册中心处于一个半死不活的状况,最终会处于一个什么状况呢?Consumer 端慢慢地会把一切的 Provider 都移除去,这样就会导致咱们的 Consumer 端到 Provider 端其实是不可通讯的。关于这个问题,咱们其实根据 Dubbo 做了必定的改造,做了一个维护机制。这个维护机制便是当 Provider,特别是注册中心上的 Provider 数少于必定的阈值的时分,咱们的维护机制就会自动地启用,它的生效是在 Consumer 端的,也就意味着 Consumer 端需求缓存这段时刻内一切前史的 Provider 的列表。

咱们或许在这儿会有一点忧虑,你缓存的 Provider 假设失效了怎样办?它是真的失效了,比方说它被下线了,或许是它本身经过迁移,像咱们在容器场景里边,经过了必定的发布,其实它对应的信息都变化了,这个时分你再去通讯不就有问题吗?其实咱们在维护机制里边也考虑了这个问题,咱们在通讯之前仍是会做一个直连的查看,Consumer 到 Provider 的连接存活是否是真实存在,假设不存在,咱们会把这一个连接给丢掉,确保通讯的时分运用的是一个可用的连接。

当这个信息机制启用了之后,注册中心恢复到必定的状况的,这个 Provider 又能从头注册到注册中心里边了,接着咱们又会把维护机制自动封闭掉,这样的话 Consumer 就只会调用注册中心上存活的这些 Provider,就可以防止掉由于注册中心半死不活,导致一切的这些散布式的运用里边的 RPC 调用是不可用的。

这其实是一个比较有用的方法,由于假设呈现了这种场景,其实你内网里边的大部分运用通讯其实是处于一个不可用的状况,乃至你想让它恢复都是十分困难的事情。比方你想发动的时分,其实 Consumer 发现 Provider 都不存活了,这也会导致发动失败等等各方面的问题。

4. 动态限流

接着我来介绍一下限流里边咱们做的一些作业,这儿边咱们做的方法我把它叫做动态限流。普通的一个限流里边,一般来说是这样的一个方法,咱们有 A、B、C 的服务都对 X 这个服务进行了调用,它的来历或许是不相同的,X 为了维护本身的状况是可用的,它不可防止就要对上游 A、B、C 的这些拜访分配固定的一些配额,谁超过了配额就不可用了。

去哪儿旅行微服务架构实践

比方说像 A 分配了 100、B 也分配 100、C 分配给了 50。当 A 超过了 100 的时分,其实它的一些请求是会被拒绝掉的,这个是根据容量的考虑,X 不或许具有无限的容量,这时它需求必定的维护办法。可是这地方就会有一个问题,假设 A、B、C 里边,比方说 B 服务,它其实是从 App 过来的,它的价值不可防止来说的话,要更高一点。比方说第三个服务 C,它是从 Web 里边来,它的价值相对来说比较低一点。这个价值是根据你的事务形状来的,比方说你的 App 的成单、转化更高,那就意味着它的请求更宝贵。

这个里边就会呈现一个问题,服务 B 和服务 C 自己都得到了必定数量的配额,可是假设 App 的流量上涨了,Web 的流量没有上涨,这时就会面对一个问题,服务 C 的配额没用完,可是服务 B 的配额又不够用,这个场景下怎样处理呢?就需求靠人工来不停地去调整它,并且这个调整需求适当实时才干够,咱们有没有方法可以相对一致地处理这个问题呢,其实咱们做了一个探究,这个探究从实践成果来看的话是比较有用的。

去哪儿旅行微服务架构实践

咱们对这些服务进行配额分配的时分,其实不是一个固定的配额,而是一个动态的分配。动态的分配意思便是,我只需一个总的容量,并不给每一个服务进行分配,总的容量我分配给一切人。可是我要对一切的调用方进行一个排序,也便是说谁的价值高谁就排在前面,这样的话就能得到一个比较有用的成果。你的限流模型是根据你的事务逻辑来的,也是根据你的事务价值来的,当你发生限流的时分,优先丢掉的必定是最没有价值的那部分的事务请求。

当然这儿边也会有一个前提,你的请求来历是需求有差异化的。还有第二个点,你的这些 trace 连通性必定要高,也就意味着,你的这些标志要可以一路畅通地带着下去,假设只是根据某一层去做限流逻辑,其实是没有意义的。

5. 防堕落

接着便是防堕落,这儿边其实咱们需求对架构、运用的散布、运用的联系去做许多的剖析,得出改善的办法,咱们在这上面改善的办法其实有许多。比方咱们会剖析哪些运用是频频修正的,这些频频修正的意思是不是一切的需求,这些运用都相关地需求去做修正,那就意味着说它的事务域是相同的。假设这些事务域相同的状况下,你把它的微服务划分得很细,实际上它是逐个绑定的话,其实并不契合微服务化的准则。

去哪儿旅行微服务架构实践

第二个是否存在重复的调用,这条链路里边,这些重复的调用是否可以去缓存化,或许是防止它重复调用。

第三个许多的串行调用是不是可以把它异步化,比方常见的,从数据库里边拿出一批记载,这一批记载经过循环的方法,挨个去对它发起长途调用,这些进程里边其实比较有用的方法便是经过异步化、并行化的方法去把速度给提上来。

第四个异步的整个链路的这些超时装备里边,其实会有必定的相关的联系。比方上游的超时是不应该比下流短的,假设下流的超时比上游的还长,那意味着说下流还在核算,上游或许已经超时了,这个核算的成果其实有或许回来不了上游,这些便是无用的装备。除了这之外其实整个链路里边许多的超时或许是不合理的,比方方才说到的许多重复的调用,这些重复的调用或许循环的调用,再乘以相同的超时时刻,或许就会比整个终端的操作时刻要长许多,这些都需求去做必定的剖析和考虑,才干达到它防堕落的目的。

五、ServiceMesh 测验

最终一个介绍一下咱们在 ServiceMesh 上的测验。

1. 布景

先简略介绍一下布景,咱们公司内部其实仍是存在多言语、多协议的这样一个场景。

第二个它在多言语、多协议的场景里边不可防止地就会呈现管理渠道比较分散,比方像 Dubbo 的话,咱们其实会有一个 RPC 的服务管理渠道;HTTP 的话咱们其实有相似于网关 Nginx 或许是 OpenResty 去对它进行管理;其他的也会相应的管理,乃至或许是在装备中心去对它进行管理等等。

去哪儿旅行微服务架构实践

第三个组件的新功用迭代是相对比较慢的,由于这些组件都是嵌入在运用代码里边,因此它的迭代就需求跟随着事务代码去迭代,才干够去比较好地迭代,并且这些迭代里边其实需求支付必定的人工成本,其实事务的开发是不太乐意去主动地做这种组件的迭代的,在 ServiceMesh 的选型里边,咱们也考量了一下当时业界里的挑选。

2. 技能选型

去哪儿旅行微服务架构实践

其实从数据面上来看,envoy 仍是占大头的,可是咱们终究其实没有挑选 envoy,首要是由于咱们在 C++ 技能栈里边储藏的人才是不够多的。第二个在操控面上,咱们基本上都是根据 Istio 方法去做的,当然也大部分都做了二次的开源,咱们终究也是挑选这样的一个方法。

3. 整体架构

去哪儿旅行微服务架构实践

咱们终究的挑选是,数据面上咱们挑选了 MOSN,而不是 envoy,MOSN 是根据 Go 开发的一个阿里巴巴官方出品的组件,这个组件其实是一个偏网关署理型的一个组件,可是在上面去完成 Mesh 的逻辑,其实是比较便利的,特别是针对根据 Dubbo 这个协议的 Mesh,MOSN 支撑得是比较好的;在操控面上,咱们也是根据 Istio 去做了二次开发,也有必定的自研组件,比方说 mcpServer、装备中心、注册中心这些都是咱们自研的。在运维面的话,咱们也是自研了一套运维相关的组件,比方 Sidecar 的布置、灰度的升级等等,还有一些规矩管理、监控报警等。

4. 注册模型:

去哪儿旅行微服务架构实践

ServiceMesh 里边我首要介绍一下几个要害点:第一个便是注册模型,由于它是一个多协议、多言语的方法,其实比方 Dubbo 或许 HTTP,它在服务层面其实是不一致的,在注册中心咱们想要以一个一致的注册中心去服务发现的时分,不可防止地就需求把它的维度一致掉,咱们是怎样做到的呢?咱们其实是参阅了业界现在比较火的,或许基本上应该是事实上的标准,经过服务 – 实例这样的维度去抹除去了相似 RPC 这种 Dubbo,这种接口的维度,与本来的注册中心去进行双写,来确保 Mesh 化的和非 Mesh 化的都能支撑。

5. 装备模型

去哪儿旅行微服务架构实践

然后第二个便是装备的模型,这儿边便是服务管理渠道,咱们其实自定义了一些存储的格局,然后经过 MCP 的方法,Server 的组件去转化 Istio 需求的数据格局。Istio 拿到了之后,经过标准的 XDS 的数据格局下发到 MOSN 里边,这一段咱们基本上便是依靠原有的一个功用,首要是在左侧这部分,咱们自定义的这部分组件的数据格局是比较要害的。

6. 路由模型

第三个说一下路由的模型,路由模型里边,咱们其实见过十分多,可是我对这些管理的功用或许路由的功用,其实偏保存一点的观念。由于在我看来越灵活越或许会用错,这儿边就需求咱们去抽象必定的事务方法,把事务方法落地到或许固化到组件里边来。经过这个方法,咱们其实发现只需求以运用和环境集群为主体,并且在这个场景上支撑 trace 匹配的操控,就可以确保满意咱们绝大部分的事务场景。

去哪儿旅行微服务架构实践

去哪儿旅行微服务架构实践

由于咱们线上常常会呈现运用不同的环境集群,其实是为了不同的诉求去用的,比方像查找集群和买卖集群,它们需求进行物理隔离,然后比方上线的时分,或许需求做必定的灰度验证等等。这样的话咱们就可以根据 trace 的参数匹配去操控它,只需以这样两种方法作为路由模型的支撑,是满意绝大部分的事务诉求的。

7. 操控面和运维面

在操控面与运维面上,咱们做了什么样的方法呢?其实咱们当时也并不想要在这上面做自研,而咱们参阅了业界许多的处理计划,其实发现在装备中心和 MCP 的 Server 里边,是短少开源计划的,特别是装备中心,咱们发现基本上很少有可用的装备,基本上便是一个查看可观测的方法罢了,但其实你想要对它进行一些服务的管理是不够用的。

第二个 Sidecar 运维,这儿边无损的升级和切换十分要害,会涉及到不同组件之间的依靠联系和它的检测,比方 Consumer 对 MOSN Sidecar 的检测,和 MOSN 逆过来对 Consumer 的检测,这些逻辑都是不相同的,并且细节会比较多,有爱好的话咱们可以线下交流一下。

第三个便是可观测性,参阅了非 Mesh 化需求的一些方针,咱们可以比较好地去把 Mesh 化的进程里边许多的可观性方针都内置地埋点进去。可是在 trace 链路里边,最好把 Mesh 的 Sidecar 的 span 给精简掉,不然你会发现一切的节点都比本来多了两跳,这样无疑会把 trace 由于中间件的逻辑,把它复杂化掉了。

第四个便是健康查看,这儿边方才说到的 Consumer 对 Sidecar 的可用性的查看,其实是一个十分要害的重点,由于取决于它需求怎样降级以及它能不能降级。

8. 功用优化

最终一个便是功用的优化,这儿边首要有两点,在业界大部分的计划里边其实都会面对一个问题,由于这些调用联系是动态化的,就意味着运行时才干知道我需求调用哪一些服务,它对应的规矩是什么,也便是说我需求把一切的服务信息都下发到 Sidecar 里边,这不可防止就会占用许多的内存,它的匹配功率都是十分低的,咱们在这上面怎样去做优化呢?

其实合作前面 Spring Cloud Qunar 可以做到比较友爱的方法,当它做了 Spring Cloud Qunar 这样的 Qunar Mesh 注解之后,咱们其实可以把这部分在编译期就收集上来,或许在发动的时分去把这些信息都给它上报上来,这样咱们就只需求订阅咱们需求的一些部分数据就好了,可以做到许多的数据减少。

第二个便是在服务通讯里边,由于多了 Sidecar 的两跳,那就意味着说 Sidecar 的通讯是带来必定时刻、功率和功用损耗的,这儿边的要害点就在于运用程序和 Sidecar 的通讯是否可以存在优化空间。咱们经过实验发现,运用 UDS 的通讯来代替原有的这种要经过网卡的通讯其实要高效不少的,把它在这两跳上带来的损耗降到足够低。

六、总结

总结来看的话,整个微服务的进程里边,咱们最佳的实践其实存在好几个方面。

去哪儿旅行微服务架构实践

第一个是在发现方法、通讯方法上的,咱们需求去因地制宜做必定的最佳实践;在架构方法里边,比方说像 BASE 方法和 CQRS 方法,咱们都可以在适宜的场景里边放心大胆,或是尽或许去启用它们的。

开发功率先行,微服务的初衷其实是提效,那问题复杂化了以后,就需求有这些有力的配套,比方开发插件等来处理咱们开发的问题,不然微服务或许只会带来一地的鸡毛。

第三个便是有用的服务管理,简略的管控手段意义是不大的,它的手段尽管有用,但真实事务的意义是不大的,相似于动态限流这样的方法才干真实处理事务问题。

第四,ServiceMesh 不可防止地,或许说现在基本上已经成为事实上的下一代微服务通讯的架构方法,这个里边模型的规划和功用优化就十分要害。

最终关于微服务里边的一些关键再进行一下简略的总结

去哪儿旅行微服务架构实践

事务的拆分便是借鉴业界老练的模型,本地化为最适宜公司现状的事务结构。比方方才说到的去哪儿网,它其实也是一个线上的电商体系结构,可是它又有旅行、民航或许酒店范畴的特殊性,就不可防止地要本地化。

还有便是架构方法里边,不同场景下的架构方法的支撑是不相同的,买卖体系的事情驱动,异构数据的 CQRS 都是比较有用的方法。然后开发方法、开发支撑里边需求对微服务进行完善的工具支撑。

在服务衡量里边,咱们联系、功用、异常、资源,还有方才说到的防腐都需求比较有用。第五个便是管理的管控,限流、熔断这种方法需求实时生效,最好是把它一致化并且进行事务有用化。最终一个便是演进式,架构的演进需求平滑有序,防止许多的运用改造。

最终送给你一句话:架构演进,以提高功率为方针。

作者介绍

朱仕智 去哪儿游览 根底架构部高档技能总监

去哪儿网高档总监。担任过公共事务、国际机票、根底技能等团队,拿手复杂实时事务的高并发、高可用、高功用的体系规划和落地。现在担任根底架构团队,包括后端架构、大前端架构、质量确保、根底云渠道等范畴。近期首要投入在公司整体技能演进和数字化技能运营方向。