网易考拉海购Dubbok框架优化详解(学习笔记)
博客专区 > ND小龙 的博客 > 博客详情
网易考拉海购Dubbok框架优化详解(学习笔记)
ND小龙 发表于10个月前
网易考拉海购Dubbok框架优化详解(学习笔记)
  • 发表于 10个月前
  • 阅读 48
  • 收藏 0
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

微服务化是当前电商产品演化的必然趋势,网易考拉海购通过微服务化打破了业务爆发增长的架构瓶颈。

微服务选型要评估以下几点:

  1. 内部是否存在异构系统集成的问题;
  2. 备选框架功能特性是否满足需求;
  3. http协议的通信对于应用的负载量会否真正成为瓶颈;

 

跨进程的远程调用(RPC)

考拉当前使用的Dubbok框架,Dubbok由阿里开源Dubbo框架的优化和功能改进而来。Spring Cloud的一些优秀特性也是Dubbok改进的参考点。

Dubbo作为一个分布式通信框架,最基本的职责就是完成跨进程的远程调用(RPC)。

 

 

1.协议栈:

Dubbo支持自定义RPC协议,冗余字段少、通信性能高;

序列化协议支持hessian2、Dubbo自定义序列化等高性能协议;

Dubbo支持序列化协议解码在业务线程(Netty3编码自动在业务线程执行);

2.线程模型:

依赖Netty3的非阻塞线程模型,支持I/O、业务逻辑线程分离,通过Handler链处理请求。

Dubbo默认是所有服务共享单一的TCP长连接的(这也是为什么服务接口不适合传输大负载值,即容易阻塞其他服务的调用)。为响应慢或重要的服务接口考虑,Dubbo支持设置多TCP连接,此时连接数和线程池数默认是绑定的,即每连接对应一个线池,consumer、provider都执行这个策略,从线程隔离的角度讲是合理的,但不注意也容易造成线程占用资源过多,尤其是对于消费端基本无线程阻塞的情况下可能是一个设计缺陷。

3.缓冲区:

Dubbo默认使用的全部是heap缓冲区,因此Socket通信不可避免会存在内核缓冲区和堆缓冲区复制消耗;除此之外在RPC协议解析(包括粘包/半包处理)、序列化协议解析等处理上也存在heap区内的复制,因此性能上是存在优化点的(当然要确有必要)。

 

依赖隔离(服务降级)

当应用被设计依赖外部服务时,要始终保持警惕状态:外部依赖是不稳定的,为此对接外部依赖做好解耦是关键,避免外部接口发生异常拖垮自身系统。Dubbo提供了超时timeout机制作为最基本的解耦措施,同时在接口报错时支持提供降级的容错逻辑;除了容错降级,Dubbo进一步支持强制的短路降级。

 

然而在容错降级与短路降级之间,Dubbo缺乏一种在容错与短路间切换的机制,即自动熔断。自动熔断要达到的效果是:当接口偶然报错时执行容错返回备用数据,而当接口持续大量报错时能自动在消费端对接口调用短路直接返回备用数据,之后持续监测接口可用性,接口恢复后自动恢复调用。这样能最大限度减少接口异常对消费方的影响,同时也减轻本就处于异常状态的提供端负载。

 

Dubbok通过标准SPI的的形式,实现了熔断功能。目前支持两套方案:一套是自己实现的熔断逻辑;一套是通过集成hystrix框架实现。目前支持错误率、最低请求量、熔断时间窗等基本配置,支持将业务异常纳入统计范畴;以上参数均可通过SOA治理平台运行期动态调整;支持外部Dubbo依赖调用的准实时监控。

 

讲真这段看得不是太懂,后面需要找朋友咨询一下。

 

启动与停机

这里主要关注Dubbo工程启动初始化阶段和停机销毁阶段的一些特性和改进点:

1.延迟暴露。

默认Dubbo服务会随着Spring框架的加载逐一完成服务到注册中心的注册(暴露),如果某些服务需要等待资源就位才能暴露,那就需要延时注册。增加Spring context初始化完成后继续延时等待的配置项。

 

2.启动预热

一些应用在运行期会通过本地缓存中间结果提升性能,而当此类应用重启时本地缓存数据丢失,如果重启后的机器立即有大量请求导流过来,由于没有缓存加速会导致请求阻塞响应性能降低。通过对重启后的机器设置预热期可有效缓解重启缓存失效问题:具体做法是降低预热期内的机器权重,引导少部分流量到此机器,此机器可以在预热期内逐步建立缓存,待预热期过后恢复正常权重与其他机器平均分摊流量。

 

3.优雅停机

在集群部署的情况下,单个消费者或提供者机器上下线对整个产品的运转应该是近乎无感知的,Dubbo提供了优雅停机功机制保障在进程关闭前请求都得到妥善处理。

消费方优雅停机:控制不再有新的请求发出;等待已经发出的请求正确返回;释放连接等资源。

提供方优雅停机:通知消费端停止发送请求到当前机器;通知注册中心服务下线;等待已经接收的请求处理完成并返回;释放连接等资源。

考拉在每次服务上下线过程中,每个工程总是收到大量的消费方/提供方报出的服务调用异常,经排查是Dubbo优雅停机实现的问题,修复问题后工程上线阶段异常数明显减少。

另外停机阶段总是莫名的收到zk连接为空的异常信息。是由于在通知注册中心服务下线的过程中,Spring销毁线程和jvm hook线程并发执行,导致zk客户端被提前销毁导致抛出异常。

 

4.Provider重启

注册中心发送大量服务销毁与注册通知导致consumer工程Full GC。

历史原因,考拉内部仍存在一个提供近200个Dubbo服务的单体工程,而每次当这个工程上线时,消费它的consumer工程就会出现频繁Full GC(3-5次,非内存泄露)。

是Dubbo为保证高可用而设计的注册中心缓存导致的问题:在每次收到注册中心变更时consumer会在本地磁盘保存一份服务数据副本,由于多注册中心共享同一份缓存文件,为了避免相互覆盖,每个注册中心实例会在收到变更时重新从磁盘加载文件到缓存,和变更数据对比后重新写回磁盘,在近100提供者机器不断重启的过程中,大量的变更通知导致的频繁加载缓存文件占用大量内存导致Full GC。

 

总结

Dubbok框架、SOA服务治理平台、分布式调用链路跟踪以及其他考拉内部维护的如分布式事务、消息中间件等共同支撑了考拉微服务化的正常运转。

微服务化涉及一个产品生命周期的多个方面,架构解耦、易扩展、易部署;同时也面临新的问题,如数据一致性、分布式调用链路追踪、异常定位、日志采集等。

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 10
博文 45
码字总数 2295
×
ND小龙
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: