一、应用架构的演进
应用服务架构一直处于不断演进的过程中,上图通过对比5种比较主流的架构模式,展示了应用架构的演进历程和变化。
1、单体架构
在业务发展初期,为了快速落地应用、满足客户需求,一般会使用All in One的单体架构。
单体架构的特点是:在每个节点服务器中,包换应用的全部功能模块代码等所有模块都耦合在一个进程里,系统完全封闭且很复杂,牵一发动全局;应用系统很臃肿,维护和版本升级开销非常大。使用负载均衡分散访问会话,提高并发处理能力。
单体架构是围绕web容器打包及部署的架构模式,随着业务的快速发展,要求实现服务的快速迭代和快速交付,应用架构也演进为以服务为中心的架构模式。
2、RPC架构
RPC架构在现在应用系统的早期还是比较常见的架构模式,就是增加服务层,把冗余的代码和可以复用的业务应用进行拆分提取,封装成服务。系统架构更加清晰,代码质量提高,利于升级和维护,稳定性高。应用层可以更专注于与前端用户交互。业务处理放在服务层来进行,服务和应用的管理不是自动化,服务层能够实现HA的功能,适用中小型WEB系统的场景和高并发场景,性能比较好。RPC就是一个典型的RPC架构。
RPC架构也存在一些问题,通过共享分布式对象实现远程方法调用,如果在其中一个对象中添加一个属性,就会对共享对象的生产者与消费者产生影响,所以RPC架构也是紧耦合的模式。系统交互采用RPC私有TCP协议,服务生产者和消费者存在强代码依赖,对异构系统集成不友好。
3、SOA架构
个人认为SOA架构经历了两个阶段,一是以ESB中心化的架构,二是以注册服务为中心的服务注册发现架构(上图)。
1)ESB中心化架构
ESB中心化架构实现了松耦合,依赖于ESB消息总线技术实现异构系统的信息交互和集成集中式架构管理,因此它虽然是面向服务的,但它本质上依旧是一个中心化的架构。
其优势在于:基于WebService技术,拥有重量级的消息通讯机制。当团队规模比较大、要实现异构系统集成时,它可以提供统一的解决方案和技术实现方式,快速集成异构系统对外服务。
2)以注册服务为中心的服务注册发现架构
- 注册中心负责服务地址的注册与查找,相当于目录服务;
- 服务提供者和消费者只在启动和订阅后发生变化时与注册中心交互,注册中心不转发请求,压力较小;
- 应用层和服务层可以根据需求进行动态水平扩展,应用与服务实现负载均衡;
- 通过随机、轮询、权重等策略与开放式、标准化的框架,满足接口调用的服务都可以接入服务框架(RPC)监控服务调用情况,可进一步对服务层再分层,根据业务需求和服务运行情况对服务进行编排、梳理以及服务治理。
以注册服务为中心的服务注册发现架构适用大型及超大型网站应用架构。所以ESB中心化架构的问题也比较明显:中心化架构难以满足灵活性的服务迭代和需求交付。
4、微服务架构
微服务架构实现了系统解耦和持续集成,有清晰的服务边界,相对ESB架构和传统SOA架构来说粒度更小,使用轻量级的通讯机制(HTTP+REST)交互,具备更强的扩展性和弹性,能够更灵活、更快响应业务变化。
5、服务网格架构
服务网格架构是容器化的产物,引入了类似代理的Sidecar,在微服务SDK里面保留协议编解码能力,把服务注册与发现、负载均衡、熔断、限流、降级等服务治理能力下沉到Sidecar。当该 sidecar 在微服务中大量部署时,这些 sidecar 节点自然就形成了一个网格。
服务网格架构的优势:支持用多语言开发业务、省去或轻量化SDK,为异构服务框架/平台创造了融合和发展的机会,让服务框架/平台的演进更自主、更敏捷,让业务开发聚焦业务本身,无需关心安全、灰度、熔断、限流、降级等普遍服务,治理能力更敏捷、更好管控,加速业务探索。
Service Mesh的终局:Mesh所有协议或框架。目前货拉拉已经实现了Redis Mesh。
通过上述对比,我们不难发现,应用服务架构是在不断演进的,而且其演进背后存在一定的逻辑,服务架构的演进主要取决于以下2个维度:
- 业务维度,技术架构是由业务发展所处的时期和阶段决定的,要能够解决业务发展过程中的痛点。在进行架构选型时,需要考虑这个架构是否能满足当前业务的需求,业务需求能否随着架构的演进实现增量式的迭代。
- 技术维度,要满足非功能需求,使业务快速跟上技术生态的发展。
综上所述,应用架构演进的底层逻辑就是: 一切为了敏捷(低投入,快速满足业务需求)。
二、货拉拉的All In One Web到微服务治理
货拉拉应用架构到现在为止经历了All In One Web的单体架构,RPC架构,与现在的微服务架构。
- 单体架构阶段:2014年发布的第一个版本就是PHP的All In One Web,一直延续到2016年。
- RPC架构阶段:从2016年开始,业务量不断上升,单体架构难以满足业务需求,从单体应用里面拆出几十个dcore,ucore等核心服务。虽然服务之间采用HTTP+REST的调用方式,不是RPC的调用方式,但这阶段和RPC架构一样,都不具备服务治理能力。
- 微服务阶段:从2020年开始微服务化改造,一直到目前都还处于微服务阶段。
1、货拉拉微服务治理的背景
1)微服务化碰到的问题
从2020年开始微服务化改造,当时阶段属于类似的RPC架构,是基于域名+HTTP的服务交互方式(图上)。痛点在于:
- 基于域名的管理方式成本非常高:服务调用都还用域名的方式,内部新服务上线都必须申请内部域名,当时已接近500个域名,域名维护成本非常高。
- 协议不统一:PHP和Java服务调用、采用HTTP+JSON的协议方式,但业务请求方式不统一,导致研发效率低,插入管理切面异常困难。当时内部业务协议请求方式有GET请求方式、JSON数据以HTTP BODY的POST方式、还有HTTP FORM表单方式。
- 没服务治理能力:没有服务注册中心,没有熔断、降级等保障性能力。服务之间强关联,调用链脆弱。若某旁支服务不可用,可能导致整条关键链路不可用,稳定性无法保证。
- 技术转型:公司业务快速发展,大部分业务还是PHP开发,需要向Java转型或者使用Java来重构。内部500+的应用/服务不能同时转型或者重构,需逐步推进。
2)微服务化需要解决的问题
- 跨语言:支持内部PHP和JAVA服务相互调用。
- 时间窗口:开发周期3个月左右。
- 服务治理能力:具备熔断、限流、降级等服务治理能力以及全链路灰度发布能力。
- 协议兼容要求: 具有泛化调用能力(需要类似FeignClient的调用方式,兼容老的PHP和Java服务)。
- 协议规范要求:提供标准化RPC的能力。
- 服务注册发现:基于APPID的方式,考虑到后续容器化Service Mesh方式的服务治理要求。
2、货拉拉微服务治理的框架选型
综合上述需要解决的问题,技术选型和参考的框架:
- SOA架构:Dubbo
- 微服务架构:Spring Cloud
- 服务网格架构:Istio
公司内部基础设施还未全面容器化,所以服务网格架构方式Istio先淘汰,剩下就是Dubbo和Spring Cloud。我们选型思考的出发点:框架上的缺点或者不足点是不是我们能接受或者克服的。
1)Dubbo2.X的缺点
2020年Dubbo 3.0还未Release,所以我们研究了Dubbo 2.X。
- Dubbo 2.X协议对云原生支持不友好;
- Dubbo 2.X不支持熔断、限流、降级等服务治理能力,需要另外的Sentinel等框架支撑;
- Dubbo 3.X Release时间和版本稳定时间未知;
- 很强的RPC契约,没有泛化调用能力,达不到兼容老的Java和PHP服务要求;
- Dubbo 2.X基于接口/服务(Inteface/Service)的服务注册发现方式,对未来Service Mesh方向即基于APPID的服务注册发现方式支持不友好。
2)Spring Cloud的缺点
- 臃肿、体系过于复杂、不够轻量,虽然使用门槛低,但深入和改造成本较高;
- 打包的包过大,一般都大于100M,启动后占用的内存也比较大;
- 服务调用协议采用HTTP+REST方式,协议管控能力较弱。
3)自研微服务框架
我们对比后的结论是自研微服务框架,具体微服务体系中组件选型和设计思考如下:
- 标准服务调用协议:JSON-RPC(支持Java和PHP服务相互调用);
- 注册中心:Consul;
- 服务治理:熔断Hystrix(Hystrix有PHP版本支持);
- 泛化调用:参考FeignClient的客户端和jsonrpc4j服务定义机制;
- 框架设计:参考Dubbo的分层机制和优秀设计。
3、货拉拉微服务治理的实现思路
框架设计参考Dubbo代码的分层架构和优秀设计:
- dubbo-common
- dubbo-config
- dubbo-filter
- dubbo-metadata
- dubbo-monitor
- dubbo-registry
- dubbo-remoting
- dubbo-rpc
- dubbo-serialization
- dubbo-springboot
1)泛化调用的实现方式
① 参考FeignClient定义接口方式
@FeignClient(value= “XC-SERVICE-MANAGE-CMS”)
其中XC-SERVICE-MANAGE-CMS为下游应用的APPID,FeignClient在Spring Cloud体系中以APPID的方式发现服务。
② 参考jsonrpc4j接口的定义方式
@JsonRpcService("/path/to/MyService")
interface MyService {
service methods
}
③ 泛化调用的接口定义方式
④ 标准JSONRPC接口的定义方式
2)服务治理能力整体实现方式
- 熔断能力:集成Hystix框架。
- 治理配置:集成公司内部的配置中心。
- 监控能力:集成公司内部的监控中心。
- 治理控制台:开发治理管控平台soa-admin。
服务治理管控平台:soa-admin控制台
3)Java Agent版本服务治理能力实现方式
- 服务治理能力下沉到Java Agent;
- Java Agent模块化、插件化,目前插件有Metric、Trace、SOA;
- Java Agent插件支持动态升级和灰度升级。
4、货拉拉微服务治理的未来规划
未来往Service Mesh演进,但生产落地仍有挑战。
1)增加的复杂性
在一个已经很复杂的环境中引入代理、sidecar等组件会极大地增加运维的复杂性。
2)需要的专业知识
在容器编排器(如Kubernetes)之上添加Istio之类的服务网格,通常需要运维人员成为这两种技术的专家。
3)延迟
服务网格是一种入侵的、复杂的技术,它能向服务架构中添加显著的延迟。
4)平台的依赖性
服务网格的侵入性迫使开发人员和运维人员适应一个高度自治的平台,并遵守其规则。