写点什么

近万服务实例稳定运行 0 故障,携程微服务框架实践及思考

2020 年 9 月 27 日

近万服务实例稳定运行0故障,携程微服务框架实践及思考

携程从.Net 技术栈的时代就已经开始微服务领域的探索,转入 Java 技术栈之后,先是自研微服务框架,然后是高性能的 Dubbo。目前我们正在 Service Mesh 的道路上探索,希望接下来能够实现微服务框架的全面标准化以及云原生。


一、过去(自研服务框架)


携程在.Net 技术栈时代,开始是基于 ESB 总线,虽然解决了内网服务调用的治理问题,但是集中式的服务架构,经常会出现单个服务把整个总线拖垮,进而导致全网瘫痪的现象。基于注册中心的 SOA 服务架构,通过分布式的服务调用,解决了单点故障带来的巨大影响。


目前,携程主要是以 Java 技术栈为主,考虑到兼容历史.Net 技术栈,现在的框架以自研为主,但是对比开源的高性能服务框架,自研的框架可能又存在下述提到的几个问题。



二、现在(CDubbo 服务框架)


CDubbo 名字里的 C 代表携程的治理,Dubbo 代表阿里开源的 Dubbo SDK。纵观过去两年的实践和探索,从 2018 年 4 月的第一个版本落地,到现在的近万服务实例,我们大致可以总结为下面的几个主要里程碑。



2.1 注册发现


注册发现是分布式服务框架的核心要素,为了支持现有的服务互通,所以需要接入携程的注册中心。


服务注册支持健康检测扩展机制,业务可以根据业务场景自定义健康检测扩展,例如当依赖的数据库不可用时不再对外提供服务。服务端通过 5s 一次的心跳保持服务的可用性,当连续 N 次没有发送心跳时就会自动通知客户端。


客户端发起对服务的订阅,通过推拉结合的模式,保证节点在客户端的最终一致性。通过 Dubbo 的扩展机制,实现了自定义的路由策略,比如根据方法名指定路由策略,以及根据请求参数决定不同的路由策略,同时也能够支持就近访问,优先访问本机房的服务。



2.2 监控-CAT


对微服务来说,没有了监控就好比瞎子一样,什么也不清楚。CAT 提供了分布式链路追踪的能力,可以提供很好的报表,以及场景化的问题分析。


有时,需要了解服务总的请求量以及单机的请求分布和 QPS,或者还要知道服务的执行耗时及 99 线。CAT 的聚合报表可以帮助我们更好的了解服务的健康状况。



对于超时,可能需要知道哪个阶段变慢,客户端还是服务端,序列化阶段还是服务执行过程太慢。对于异常报错,可以看到哪个过程出现的异常,同时会打印异常堆栈信息,帮助问题的定位。



2.3 监控-Metrics


框架人员需要了解公司服务的宏观情况,比如各机房都有哪些服务,哪些服务使用了 protobuf 序列化格式,哪些服务使用了 SOA 协议等,以及平均执行耗时等情况。业务同事可能也想知道自己服务具体情况,比如有哪些调用方,线程池是否已经跑满了。


通过接入携程的 Dashboard,可以提供全局的总量、错误量、线程池统计信息,也可以根据机房、协议、序列化格式等聚合数据。还能够自定义告警规则,在问题发生时能够尽早的介入。



2.4 动态配置


对业务同事来说,有可能会存在依赖的服务突然变慢导致客户端超时的情况。框架人员可能需要在机房故障时,需要全局调整 check 为 false,以解决 A B 服务循环依赖谁都无法启动的问题。动态配置提供了配置热生效的能力,不需要为了一个配置重新发布,成本很高。


服务端的多个方法,可能执行耗时也会有所不同,通过多级别的参数配置,可以设置服务默认超时为 1s,单独为执行较慢的方法设置独立的超时时间为 5s。


服务 Owner 可能更清楚自己服务的耗时,通过服务端对客户端的参数设置,不需要每个调用方都设置一次超时,设置的时间也会更合理一些。为了避免配置出错带来的损失,我们提供了友好的可视化界面。



2.5 SOA 协议及互通


为了支持现有客户端迁移到 CDubbo,需要考虑支持现有的 SOA 协议。除了要确保兼容 HTTP 1.1 协议不变,其次要保证跟客户端的序列化器一致。


CDubbo 会通过 Tomcat 端口接收 SOA 协议的请求,利用现有的序列化器执行请求对象的转换,并保证 Dubbo 内部调用和 Filter 链路的一致性,确保业务逻辑的统一,也就是业务代码不需要改动,就可以启动两个协议。



2.6 测试平台


对于私有的二进制协议来说,没有现成的 Postman 等工具可以使用。有时,开发人员需要在本地验证测试环境的服务,也可能要验证本地启动的服务端,每个开发人员都构造一个客户端显得成本比较高。


通过 VI(github 开源叫 coreStone),以及利用 Dubbo 2.7.3 提供的元数据中心和泛化调用能力,我们实现了类似 postman 的调用工具。不但可以支持直连,也能够支持本地测试,同时还可以支持 protobuf 序列化格式。关于 protobuf 序列化的测试方案,已经贡献到 dubbo 社区,感兴趣的同学可以自行了解。



2.7 升级 Dubbo 2.7.3


关于 Dubbo 2.7.3 的详细升级历程,可以参考https://www.infoq.cn/article/kOxdaV3y9fMZ0Bzs0jb2


现在回顾下升级的最终结果如何。目前,携程 99%的服务已经跑在 dubbo 2.7.3 之上,迄今为止 0 故障,只有一些不兼容的小问题,对于不兼容的问题也是确保了编译时提前暴露,运行时没有任何问题。


在发布后,也陆续的出现了一些小的问题,比如预热能力不生效,异常情况下不会回调 onError 等问题,支持服务端异步的 Trace 埋点等,这些问题已经在开源版本彻底修复了。


2.8 Threadless


业务同事反馈,需要把线程控制在理想的范围之内。但是,dubbo 的线程数量太多,一方面是服务级独享线程池,当调用方依赖了 10 个服务,每个服务的 QPS 为 1,lantency 可能只有 10ms 的情况下,由于每个服务独立线程池,至少也需要 10 个线程了。如果多服务共享一个线程池,由于客户端默认是 Cached 的线程池模式,那么在这个场景下可能只要 1 个线程就足够了。另一方面,对同步服务来说,dubbo 2.7.5 的 threadless 可以省去 DubboClientHandler 线程,Netty IO 线程直接把响应交给业务线程,从而节省了一次线程切换。


通过实践,业务线程数量有了很大程度的下降,在高 QPS 以及依赖服务数量较多的情况下,甚至可以下降 60-70%。



2.9 CDubbo 服务体系


现有 CDubbo 的服务体系,同时支持 Dubbo 和 SOA 协议,对于 Dubbo 客户端能够支持 TCP 协议的传输,对于现有的 SOA 客户端,能够兼容现有的 SOA 协议。


同时,也能够支持内网和外网 gateway 的请求,保证了多协议的配置统一,以及兼容了 SOA 的序列化格式。



2.10 性能表现


从协议层面来看,Dubbo 协议的响应较 SOA 协议有所提升,平均耗时从之前的 1ms 降低到了 0.3ms 左右,当然具体提升也要根据服务的报文及请求量有所差异。



可能有些人会觉得几毫秒的性能提升不足以挂齿,但是性能的稳定性对服务来说会很重要。我们观察了服务流量突增 3-4 倍的情况下,客户端还能保持 0 异常。长连接的多路复用,提供了很好的抗冲击能力。



2.11 扩展性


微服务框架跟业务代码耦合比较重,框架人员主要是用 20%的时间解决业务 80%的需求,另外 20%的需求却需要 80%时间的问题,更适合留给业务自己去解决,能够提供这个能力的唯有扩展性,dubbo 无论横向和纵向的扩展能力都很好。


通过实践,发现业务的确在各个层级都有自己的扩展。例如:业务扩展了 Router 层,支持自己的路由规则,扩展了负载均衡策略,机票同事甚至扩展了 Transport 层换成了适合自己的传输协议。



2.12 生态


好的生态,可以降低开发成本,例如利用现有的开源 dubbo admin,dubbo go 等组件。另外,也可以降低业务的学习成本,在其他公司学习的 dubbo 框架,到了携程还可以接着用,不需要重新学习私有的服务框架。技术支持也比较少,很多业务同事对 dubbo 框架非常熟悉。



2.13 Dubbo 协议存在的问题


除了前面提到的各种优点,经过实践发现现有的协议也存在着各种不足。除了对网关不太友好,没有移动端的 SDK 等问题。现有的扩展机制,在 A 和 B 服务都扩展了 cluster AOP 的情况下,可能会导致扩展的相互影响,如何能够保持扩展性又降低相互影响是值得探讨和解决的问题。



三、未来(Service Mesh)


网上关于 Service Mesh 的意义讲了很多,众说纷纭,个人认为可能最主要还是以下几点。


  • 标准化意味着更低的成本,比如研发成本低,学习成本也比较低,其他公司学习的微服务框架,到携程还可以继续用,省去了学习和踩坑的成本。

  • 进程解耦,框架同学可能比较感兴趣,中间件无法独立升级的问题一直困扰着框架研发同学,在这个问题上,envoy 可以独立升级也是值得期待的。

  • 通过下沉,复用了云基础设施的一些能力,一方面,能够更好的支持多语言,业务根据自己的场景选择合适的语言,另一方面,通过下沉也能够让 SDK 更简单,减少 Jar 依赖的兼容性问题。

  • 因为更加标准以及下沉,能够带来更好的云部署能力,业务出海时可以根据实际情况部署需要的组件,不再依赖框架全家桶了。



3.1 Service Mesh SDK


下图是 Istio 官网提供的 ServiceMesh 架构图,如果说 istio 解决了控制平面的标准化,envoy 或者 sofa-mosn 解决了数据平面的标准化,那么对于 SDK 来说,是否需要有个标准化的组件,或者是否存在适合我们的标准的 SDK 呢?


对于部分中小公司,没有自己的中间件团队,可能会选择付费版的 sofa。但是,对于携程这样的规模,对扩展性要求很强,同时已经存在上千 dubbo 服务的公司来说,我们可能更期待 3.0 的标准化能力。



3.2 现有协议不适合下沉


现有的 SOA 协议可能不太适合作为标准协议,基于 Http 1.1 的文本协议,跟 TCP 协议相比,建连带来的成本,很大程度上会导致长尾,影响服务的稳定性。



Dubbo 协议由于对网关不太友好,同时存在着跨语言和协议穿透性等问题,envoy 本身也可以理解为单机网关代理,所以也不太适合作为标准协议。


其次,存在的跨语言和协议穿透性问题,阿里刘军同学有过分享,感兴趣的同学可以参考:https://www.infoq.cn/article/y5HC2JjtAvMWYILmVILU


3.3 新协议


既然现有的协议都不太适合,是否可以考虑云原生的标准协议 gRPC。没错,从协议层面来看,这个选择没有问题,但是 gRPC 跟 proto 强绑定的问题,需要携程现有的几千个服务重写业务逻辑代码,这个成本可是无法被接受的。


我们对于新的协议的期待,应该是能够基于 POJO 对象,同时还要符合 gRPC 协议规范。一方面,能够很好的利用云原生的基础能力。另一方面,对于小众语言,也可以利用现有的 gRPC 框架实现与主流 SDK 的互通。



对于新的 SDK,不但要有标准的传输协议,同时考虑到服务框架与业务的紧密耦合,扩展性也是要保留的主要的特性,还需要考虑 API 的标准化,利用统一的监控组件。


3.4 总结


现在,我们实现了 SDK 的部分标准化。未来,我们一定会在云原生的道路上走的更快,更稳,更标准。



作者介绍


海洋,携程技术专家。对微服务和并发编程,以及应用性能调优等领域有较浓厚兴趣。


本文转载自公众号携程技术(ID:ctriptech)。


原文链接


近万服务实例稳定运行0故障,携程微服务框架实践及思考


2020 年 9 月 27 日 14:001623

评论 2 条评论

发布
用户头像
希望可以看到携程关于 service mesh 领域探索的分享
2020 年 12 月 23 日 16:08
回复
用户头像
携程、jd 都是早期.net 现在都是在慢慢转到Java的怀抱了
2020 年 10 月 13 日 08:49
回复
没有更多了
发现更多内容

从湖南“软硬兼施”,管窥三湘水畔的智能浪潮

脑极体

读后感之《任正非:以客户为中心》

王新涵

Spring 5 中文解析测试篇-Spring测试

青年IT男

Spring5 JUnit

3. 站在使用层面,Bean Validation这些标准接口你需要烂熟于胸

YourBatman

Hibernate-Validator Bean Validation 数据校验

实战解读丨Linux下实现高并发socket最大连接数的配置方法

华为云开发者社区

Linux TCP socket 高并发

区块链交易所搭建技术方案|去中心化交易所开发

WX13823153201

区块链交易所搭建

[翻译] Go Concurrency Patterns: Pipelines and cancellation[Go并发模式]

卓丁

channel pipeline

usdt跨境入金支付系统搭建|区块链跑分系统开发

WX13823153201

给大家介绍下,这是我的流程图软件 —— draw.io

程序员小航

工具 流程图 draw.io drawio-desktop 画图软件

LeetCode题解:239. 滑动窗口最大值,单调队列,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

ARTS打卡 第15周

引花眠

微服务 ARTS 打卡计划

给DevOps加点料——融入安全性的DevSecOps

陈琦

DevOps 运维 测试 开发 安全性

usdt支付系统开发|承兑商支付跑分系统搭建

WX13823153201

usdt支付系统开发

数字货币交易所开发方案|去中心化交易所搭建

WX13823153201

数字货币交易所开发

你问我答:容器平台改造后的安全是如何解决的?

博云技术社区

云计算 容器 微服务 PaaS 博云

ARTS Week15

时之虫

ARTS 打卡计划

用函数式写法精简Java代码的一个例子

Sean

Java 函数式编程

Go: gops如何与Go运行时交互?

陈思敏捷

go golang gops

程序的机器级表示-数组的分配和访问

引花眠

计算机基础

学习 Java,有什么书籍推荐?学习的方法和过程是怎样的?

沉默王二

Java 学习 程序员 书单

甲方日常 8

句子

工作 随笔杂谈 日常

一点思考|工作十几年了,竟从未用过do-while!

王磊

Java

Golang Package sync 透析

卓丁

golang sync

有奖征文重磅来袭,来!一起玩把大的!

小红豆

翻转链表,机器学习视觉训练,对数据的人工标注,使信息丢失,John 易筋 ARTS 打卡 Week 16

John(易筋)

学习 ARTS 打卡计划 翻转链表 Google论文评判人工预处理 大数据架构Spark

握草,你竟然在代码里下毒!

小傅哥

Java 程序员 小傅哥 bug 有毒代码

不支持原子性的 Redis 事务也叫事务吗?

海星

Java redis 事务

深入理解JVM垃圾回收机制 - GC Roots枚举

NORTH

GC Roots枚举 安全点 安全区域 OopMap

阿里巴巴发布国内首个公益区块链标准 用技术让公益公开透明

CECBC区块链专委会

区块链 公益

架构师训练营第十三周总结

张明森

oeasy教您玩转linux010206 蒸汽机车 sl

o

NLP领域的2020年大事记及2021展望

NLP领域的2020年大事记及2021展望

近万服务实例稳定运行0故障,携程微服务框架实践及思考-InfoQ