考拉推荐系统在大促中的高并发高可靠性实现


数据平台分析部 推荐技术组 袁博 傅凌进


需求

在大中型分布式系统中,通常系统很多依赖接口的相互调用(HTTP,Dubbo),在高并发访问的情况下,这些接口的稳定性对系统的影响较大,然后事实是有很多不可控问题:如网络连接缓慢、资源繁忙、服务宕机等情况也有一定概率发送。当依赖阻塞时,大多数服务器的线程池就出现阻塞,影响整个线上服务的性能,高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险。

1

  对于考拉推荐系统,对接着目前线上近数十个推荐场景的接口,大促期间流量很大的情况下(人就上图1,尖峰表示大促整点),一些接口会出现超时。当这些超时堆积起来,会使调用方超时,从而导致整个链路超时,拖垮整个服务。对于推荐系统内部而言,这些调用量大的超时接口会占用大量Tomcat线程,消耗宝贵的CPU资源,进一步导致别的接口出现问题。因此我们急需一个提供资源隔离、超时降级、实时监控、实时预警的降级框架(图2),来保证考拉推荐在大促中的高并发和高可用。

2

·功能

 我们需要实现的是能满足一下功能的模块

a接口维度的资源隔离:      每个接口堆积不允许影响其他接口

b失败、  超时接口降级:失败时候走备份策略

c熔断机制:  频繁失败超时的时候,直接降级快速返回可以接受的数据

d备份结果自动生成: 根据不同接口自动缓存可以接受的数据

e实时监控:  能实时监控当前该模块的信息

f实时报警:   出现异常时候报警给相关人员

 

·实现

 我们引入了Hystrix,中文可以称呼为豪猪,是netflix开源的一个容灾框架,解决当外部依赖故障时拖垮业务系统、甚至引起雪崩的问题。

思路:推荐系统接口众多,双十一高并发场景下一个接口的延迟对外会导致调用链超时,对内会占用大部分Tomcat线程,导致其他推荐接口延迟从而影响整个推荐服务。使用Hystrix在推荐内部进行资源隔离和超时降级,每个接口分配固定线程数,对内保证了接口维度的资源隔离。对外通过降级机制,防止了超时的发生,保证了推荐服务对外的可用性。

3hystrix实现和配置

  每次调用分为超时、异常、线程池满拒绝、正常4种情况,超时、异常、线程池满会直接走备份方案,这四种情况都会记录到时间窗口中的对应桶中

实时统计时间窗口中调用失败次数占总的调用比例,超时、异常、线程池满拒绝都属于失败,当失败比例达到阈值打开熔断开关

熔断开关打开时,所有调用直接走备份方案

从熔断开关打开起经过一段睡眠时间,熔断开关会变成半开状态,放入一个请求,如果这个请求正常就关闭熔断开关,重新开始统计

 

为了方便Java使用者开发,通过注解的方式配置降级的参数

4

关键词释义

timeoutInMilliseconds:           超时时间

errorThresholdPercentage:   错误阈值(百分比)

requestVolumeThreshold:     调用阈值,只有在时间窗口内调用次数超过调用阈值才会根据错误阈值触发熔断

sleepWindowInMilliseconds: 熔断后的睡眠窗口,睡眠窗口后开关变成半开状态,允许少部分流量进入,如果少部分流量调用成功开关关闭,不继续熔断

coreSize                                 为接口分配的核心线程数,等于最大线程数

maxQueueSize                      最大线程队列长度,达到核心线程后请求线程放入线程队列

queueSizeRejectionThreshold:线程队列阈值,当队列中线程达到阈值请求将被拒绝,走降级并记录错误次数到时间窗口中

numBuckets:时间窗口内桶的数量

timeInMilliseconds:统计时间窗口长度,配置时timeInMilliseconds%桶数 要等于0

fallbackMethod:备份的方法名

 

建议配置

timeoutInMilliseconds =全链路压测最大并发时间or50并发预发压测时间*105%

errorThresholdPercentage=降级比例按照业务,默认50%

requestVolumeThreshold =哨兵10秒内该接口流量

requestVolumeThreshold=60000

coreSize =全链路压测最大并发下并发数*105%

maxQueueSize =线程池大小

queueSizeRejectionThreshold =50%队列数

timeInMilliseconds =10000

numBuckets =10

 

  备份结果自动生成的实现是通过记录每个用户调用接口返回的结果到队列中,走备份时返回队列头部某用户的返回结果,队列采用线程安全的FIFO队列,取数据时采用随机策略返回。总体框架如图

5

 

  图5中,简单地说DegradingService提供了备份结果自动生成的服务1在接口成功调用返回后将正常结果提交至备份池submitResult(key, result)2 在走备份时调用获取生成的备份结果 result=fetchResult(key)3 返回result替换正常返回,通常这个流程的时耗低于正常返回一个数量级.l

Hystrix支持实时的数据查看,累加的记录所有关于HystrixCommand的执行信息,包括执行了每秒执行了多少请求,多少成功,多少失败等等。我们使用netflix的开源项目dashboard可视化这些数据,帮助我们实现实时监控的功能。

6

 

  实时预警实现:每个接口熔断之后我们会在日志中打印报警信息,通过在哨兵上增加监控项来检测到接口的熔断,在哨兵上增加报警项将熔断行为通过stone、短信和邮件实时告知对应的开发人员,以此实现实时预警功能。

7

 

·效果

  上线前后某一接口超时情况变化:

8

 上线前后某一台服务器负载情况变化:

9

关键成果:压测50万并发下保障了系统的稳定性和可用性,超时和cpu性能有明显提高,顺利扛过大促!


网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者付凌进授权发布。