最近在项目中用Sentinel做限流熔断,踩了不少坑,熬了好几个夜,今天分享一下这些踩坑经验和解决方案。

最近,我们,项目,要,做,微服务,的,限流,和,熔断,保护,选型,的,时候,选,了,阿里,开源,的,Sentinel,因为,它,功能,比较,完善,支持,限流,熔断,系统,负载,保护,等等,而且,和,Spring Cloud,集成,也,比较,方便,文档,也,还,可以,本来,以为,接入,应该,比较,顺利,结果,真正,用,起来,才,发现,踩,了,不少,坑,有些,坑,还,挺,隐蔽,的,熬,了,好几个,夜,才,一个个,解决,今天,这篇,文章,就,来,记录,和,分享,一下,这些,踩坑,经验,以及,对应的,解决方案,希望,能,给,也,在,用,Sentinel,的,朋友,一些,参考,避免,踩,同样,的,坑。

一、背景和接入过程

先,简单,说,说,项目,背景,和,接入,过程,我们,项目,是,一个,微服务,架构,的,系统,有,十几个,服务,用户量,和,访问量,都,比较,大,之前,没有,做,限流,和,熔断,保护,有,一次,某个,服务,出,了,问题,导致,整个,系统,雪崩,影响,很,大,所以,领导,决定,要,加,限流,和,熔断,保护,我,就,负责,这个,事情,调研,了,几个,方案,包括,Hystrix,Resilience4j,Sentinel,等等,最后,选,了,Sentinel,主要,是,因为,它,功能,全面,支持,限流,熔断,系统,保护,热点,参数,限流,等等,而且,有,控制台,方便,管理,和,监控,和,Spring Cloud Alibaba,集成,也,很,方便,我们,项目,本来,就,用,了,一些,Spring Cloud Alibaba,的,组件,所以,接入,Sentinel,应该,比较,顺。

接入,的,过程,整体,还,算,顺利,按照,文档,加,依赖,加,配置,启动,控制台,配置,规则,基本,就,能,跑,起来,了,但是,真正,用到,生产,环境,或者,做,一些,复杂,场景,的,时候,就,开始,踩坑,了,下面,一个个,说,我,遇到,的,坑,和,解决,方法。

二、坑一:限流规则不生效,排查了半天

第一个,坑,是,限流,规则,配置,了,但是,不,生效,这个,坑,让,我,排查,了,半天,当时,我,在,控制台,配置,了,一个,QPS,限流,规则,限制,某个,接口,每秒,最多,10次,请求,但是,实际,测试,的,时候,发现,完全,不,起作用,请求,还是,能,正常,通过,没有,被,限流,我,一开始,以为,是,规则,配置,错,了,反复,检查,规则,配置,资源名,限流,阈值,等等,都,没,问题,又,以为,是,客户端,没,连接,上,控制台,检查,了,控制台,的,机器,列表,看到,客户端,确实,注册,上来,了,而且,心跳,也,正常,但是,规则,就是,不,生效,很,奇怪。

后来,经过,仔细,排查,才,发现,问题,出在,资源名,上,Sentinel,的,限流,规则,是,按,资源名,来,匹配,的,我,在,控制台,配置,规则,的,时候,资源名,写,的,是,接口,的,URL,路径,比如,/api/user/list,但是,实际,代码,里,这个,接口,的,资源名,不是,URL,路径,而是,方法,的,全限定名,因为,我们,用,的,是,@SentinelResource,注解,来,定义,资源,注解,的,value,属性,写,的,是,方法名,而,不是,URL,所以,控制台,配置,的,资源名,和,实际,的,资源名,不,匹配,规则,自然,就,不,生效,找到,原因,之后,解决,就,简单,了,把,控制台,规则,里,的,资源名,改成,和,代码,里,一致,的,资源名,规则,就,生效,了。

这个,坑,给,我,的,教训,是,Sentinel,的,资源名,一定,要,搞,清楚,不同,的,接入,方式,资源名,的,默认,值,不一样,比如,用,Spring MVC,集成,的话,默认,资源名,是,URL,路径,用,@SentinelResource,注解,的话,资源名,是,注解,的,value,值,用,手动,埋点,的话,资源名,是,你,自己,传,的,名字,所以,配置,规则,的,时候,一定,要,确认,资源名,是,正确,的,和,实际,代码,里,的,资源名,一致,不然,规则,不,生效,还,很难,排查,另外,建议,在,代码,里,统一,资源名,的,命名,规范,不要,有的,用,URL,有的,用,方法名,容易,搞混,也,方便,管理。

三、坑二:熔断规则触发后,恢复很慢

第二个,坑,是,熔断,规则,触发,后,服务,恢复,很,慢,当时,我们,配置,了,一个,慢调用,比例,熔断,规则,当,某个,接口,的,慢调用,比例,超过,阈值,就,触发,熔断,熔断,时长,配置,的,是,10秒,本来,以为,10秒,后,就,会,自动,恢复,但是,实际,测试,的,时候,发现,熔断,触发,后,过,了,很久,才,恢复,有时候,甚至,要,好几分钟,远远,超过,了,配置,的,10秒,很,奇怪,一开始,以为,是,配置,错,了,检查,了,熔断,时长,配置,确实,是,10秒,又,看,了,文档,说,熔断,时长,到,了,之后,会,进入,半开,状态,放,一个,请求,过去,试探,如果,成功,就,关闭,熔断,如果,失败,就,继续,熔断,理论上,应该,10秒,后,就,能,试探,恢复,但是,实际,为什么,恢复,这么,慢,呢。

后来,经过,排查,和,看,源码,才,发现,问题,出在,半开,状态,的,试探,请求,上,Sentinel,熔断,到,时间,后,进入,半开,状态,这时候,会,放,一个,请求,过去,试探,但是,如果,这个,试探,的,请求,本身,就是,慢调用,或者,失败,了,就,会,重新,进入,熔断,状态,再,等,一个,熔断,时长,才能,再,试探,我们,的,场景,是,下游,服务,出,了,问题,响应,很慢,所以,熔断,触发,后,即使,过,了,10秒,放,过去,的,试探,请求,还是,慢调用,又,会,触发,熔断,这样,反复,试探,反复,失败,就,导致,恢复,很,慢,而且,我们,的,熔断,时长,配置,的,是,10秒,每次,失败,都,要,再,等,10秒,才能,再,试探,所以,如果,下游,一直,没,恢复,就,会,一直,反复,试探,每次,间隔,10秒,看起来,就,像,恢复,很,慢。

找到,原因,后,我们,做,了,几个,调整,第一,把,熔断,时长,调,长,了,一些,从,10秒,改,成,了,30秒,这样,减少,试探,的,频率,避免,频繁,试探,给,下游,造成,压力,也,避免,反复,熔断,看起来,恢复,慢,第二,调整,了,慢调用,的,阈值,和,最小,请求,数,让,熔断,的,触发,更,准确,一些,不要,太,敏感,第三,在,半开,状态,的,时候,我们,加,了,一些,日志,和,监控,能,看到,试探,请求,的,情况,方便,排查,问题,另外,我们,也,认识,到,熔断,的,恢复,本来,就,不是,到,时间,就,一定,恢复,而是,要,看,下游,是否,真的,恢复,了,如果,下游,一直,没,恢复,熔断,一直,不,恢复,是,正常,的,这,也是,熔断,保护,的,意义,所在,不用,太,纠结,恢复,时间,只要,下游,恢复,了,熔断,能,正常,恢复,就,行。

四、坑三:热点参数限流,参数索引搞错了

第三个,坑,是,热点,参数,限流,的,参数,索引,搞,错,了,导致,规则,不,生效,或者,限流,错,了,参数,当时,我们,有,一个,场景,需要,对,某个,接口,的,某个,参数,做,热点,限流,比如,对,用户ID,参数,做,限流,每个,用户,每秒,最多,调用,几次,防止,某个,用户,恶意,刷,接口,Sentinel,支持,热点,参数,限流,功能,正好,能,满足,这个,需求,我,就,配置,了,热点,参数,限流,规则,但是,配置,完,测试,的,时候,发现,要么,不,生效,要么,限流,的,不是,我,想,限流,的,那个,参数,很,奇怪,排查,了,很久,才,发现,是,参数,索引,搞,错,了。

Sentinel,的,热点,参数,限流,是,按,参数,索引,来,指定,对,哪个,参数,做,限流,的,参数,索引,是,从,0,开始,的,第一个,参数,索引,是,0,第二个,是,1,以此类推,我,当时,配置,的,时候,以为,索引,是,从,1,开始,的,把,第一个,参数,的,索引,写,成,了,1,结果,实际,限流,的,是,第二个,参数,而,不是,第一个,参数,所以,就,不对,了,后来,把,索引,改,成,从,0,开始,正确,的,索引,值,就,正常,了,另外,还有,一个,需要,注意,的,点,是,热点,参数,限流,只,支持,基本,类型,和,String,类型,的,参数,如果,参数,是,复杂,对象,是,不,支持,的,需要,把,要,限流,的,字段,单独,作为,参数,传,进来,或者,自己,做,处理,我,当时,也,遇到,了,这个,问题,一开始,参数,是,一个,对象,里面,有,用户ID,字段,结果,热点,限流,不,生效,后来,才,知道,不,支持,复杂,对象,就,把,用户ID,单独,提,出来,作为,一个,参数,就,正常,了。

这个,坑,给,我,的,教训,是,用,热点,参数,限流,的,时候,一定,要,注意,参数,索引,是,从,0,开始,的,不要,搞,错,了,而且,要,确认,参数,类型,是,支持,的,基本,类型,或者,String,复杂,对象,不,支持,另外,热点,参数,限流,还,支持,参数,例外,的,配置,就是,对,某个,参数,的,特定,值,可以,单独,配置,限流,阈值,这个,功能,也,挺,实用,的,比如,对,某个,特殊,用户,可以,给,更,高,的,限流,阈值,大家,有,需要,可以,研究,一下。

五、坑四:控制台规则丢失,重启后没了

第四个,坑,是,Sentinel,控制台,配置,的,规则,重启,后,丢失,了,这个,坑,也,让,我,头疼,了,一阵,当时,我们,在,控制台,配置,了,很多,限流,和,熔断,规则,测试,都,正常,但是,有,一次,控制台,重启,了,之后,发现,所有,规则,都,没,了,要,重新,配置,很,麻烦,而且,如果,是,生产,环境,控制台,重启,规则,丢失,就,会,导致,限流,熔断,保护,失效,很,危险,后来,查,了,文档,才,知道,Sentinel,控制台,默认,是,把,规则,存在,内存,里,的,控制台,重启,后,内存,里,的,规则,就,没,了,所以,会,丢失,而且,客户端,的,规则,也是,存在,内存,里,的,客户端,重启,后,规则,也,会,丢失,需要,控制台,重新,推送,这,是,Sentinel,的,默认,行为,生产,环境,用,的话,需要,自己,做,规则,的,持久化。

知道,原因,后,我们,就,做,了,规则,持久化,Sentinel,支持,多种,规则,持久化,的,方式,比如,用,Nacos,Apollo,ZooKeeper,等等,配置,中心,来,存储,规则,我们,项目,本来,就,用,了,Nacos,做,配置,中心,所以,就,选,了,用,Nacos,来,持久化,Sentinel,规则,配置,的,方式,也,不,复杂,加,对应的,依赖,加,配置,把,规则,数据源,指向,Nacos,就,行,了,配置,好,之后,在,控制台,配置,规则,会,同步,到,Nacos,客户端,也,从,Nacos,读取,规则,这样,即使,控制台,或者,客户端,重启,规则,也,不会,丢失,了,因为,规则,存在,Nacos,里,持久化,了,而且,还,能,通过,Nacos,的,配置,管理,功能,来,管理,规则,很,方便。

这个,坑,给,我,的,教训,是,Sentinel,默认,的,规则,存储,是,内存,模式,只,适合,测试,和,开发,环境,用,生产,环境,一定,要,做,规则,持久化,不然,重启,后,规则,丢失,会,出,大,问题,而且,规则,持久化,也,方便,规则,的,管理,和,版本,控制,建议,大家,生产,环境,用,Sentinel,的话,一定,要,配置,规则,持久化,不要,用,默认,的,内存,模式,另外,配置,规则,持久化,的,时候,要,注意,控制台,和,客户端,的,规则,数据源,要,一致,都,从,同一个,配置,中心,读取,不然,可能,会,出现,规则,不一致,的,问题。

六、坑五:限流异常没有正确处理,返回了奇怪的错误

第五个,坑,是,限流,触发,后,异常,没有,正确,处理,返回,了,奇怪,的,错误,给,用户,体验,很,不好,当时,我们,配置,了,限流,规则,测试,的,时候,触发,限流,后,接口,返回,的,不是,我们,预期,的,错误,信息,而是,一个,很,奇怪,的,错误,页面,或者,500错误,用户,看,了,完全,不知道,是,怎么,回事,体验,很,差,一开始,以为,是,代码,里,有,bug,排查,了,很久,才,发现,是,Sentinel,限流,触发,后,抛出,的,异常,没有,被,正确,捕获,和,处理,导致,返回,了,默认,的,错误,页面。

Sentinel,限流,触发,后,会,抛出,一个,FlowException,异常,这个,异常,如果,没有,被,捕获,处理,就,会,往上抛,最后,被,框架,的,全局,异常,处理器,处理,或者,返回,默认,的,错误,页面,我们,项目,里,虽然,有,全局,异常,处理器,但是,没有,专门,处理,Sentinel,的,异常,所以,就,返回,了,通用,的,500错误,用户,体验,不好,找到,原因,后,我们,做,了,几个,处理,第一,在,全局,异常,处理器,里,加,了,对,Sentinel,相关,异常,的,处理,包括,FlowException,DegradeException,等等,捕获,到,这些,异常,后,返回,统一,的,错误,码,和,友好,的,错误,信息,比如,“系统繁忙,请稍后再试”,让,用户,能,明白,是,怎么,回事,第二,对于,用,@SentinelResource,注解,的,方法,配置,了,blockHandler,和,fallback,方法,在,限流,或者,熔断,触发,的,时候,调用,对应,的,方法,返回,友好,的,结果,第三,对于,一些,重要,的,接口,还,做,了,降级,处理,限流,触发,后,返回,默认,数据,或者,缓存,数据,而不是,直接,报错,提升,用户,体验。

这个,坑,给,我,的,教训,是,接入,Sentinel,的,时候,一定,要,处理,好,限流,和,熔断,触发,后,的,异常,和,返回,结果,不要,让,用户,看到,奇怪,的,错误,页面,或者,看不懂,的,错误,信息,要,返回,友好,的,提示,或者,降级,结果,提升,用户,体验,而且,不同,的,接入,方式,异常,处理,的,方式,也,不一样,用,注解,的话,可以,用,blockHandler,和,fallback,用,默认,埋点,的话,需要,在,全局,异常,处理器,里,处理,大家,要,根据,自己,的,接入,方式,做好,异常,处理,另外,建议,对,限流,和,熔断,的,触发,做,监控,和,告警,触发,的,时候,能,通知,到,开发,人员,及时,了解,系统,的,运行,状态,必要,时,做,处理。

七、其他一些小坑和注意事项

除了,上面,几个,比较,大,的,坑,还有,一些,小,坑,和,注意,事项,也,简单,说,一下。

第一,Sentinel,的,客户端,和,控制台,版本,要,兼容,我们,一开始,客户端,用,的,版本,和,控制台,版本,不,一致,导致,有些,功能,不,正常,或者,规则,推送,失败,后来,把,版本,统一,了,就,正常,了,所以,建议,客户端,和,控制台,用,兼容,的,版本,最好,是,同一个,大版本,下,的,版本。

第二,限流,的,QPS,阈值,要,根据,实际,情况,配置,不要,拍脑袋,配置,我们,一开始,有些,接口,限流,阈值,配置,得,太,低,导致,正常,请求,也,被,限流,了,影响,用户,使用,后来,通过,压测,和,监控,了解,了,接口,的,实际,QPS,和,承载,能力,再,配置,合理,的,阈值,就,正常,了,所以,限流,阈值,要,根据,实际,情况,来,配置,最好,是,先,压测,了解,系统,的,承载,能力,再,配置,而且,配置,后,要,观察,监控,根据,实际,情况,调整。

第三,Sentinel,的,心跳,和,规则,推送,有,延迟,不是,实时,的,我们,有时候,在,控制台,改,了,规则,发现,客户端,不是,立刻,生效,要,等,几秒,才,生效,一开始,以为,是,有,问题,后来,才,知道,是,正常,的,因为,规则,推送,和,客户端,拉取,有,一定,的,间隔,不是,实时,的,所以,改,了,规则,后,不要,急,等,几秒,再,测试,就,正常,了,如果,是,生产,环境,紧急,调整,规则,要,考虑,这个,延迟。

第四,注意,Sentinel,对,系统,资源,的,消耗,Sentinel,本身,也,会,消耗,一些,CPU,和,内存,虽然,不多,但是,如果,规则,很多,或者,流量,很大,还是,会,有,一定,的,消耗,我们,上线,后,观察,了,一下,Sentinel,对,系统,资源,的,消耗,在,可,接受,范围,内,影响,不,大,但是,大家,上线,前,最好,也,做,一下,压测,看看,Sentinel,对,系统,性能,的,影响,确保,在,可,接受,范围,内。

八、总结和建议

以上,就是,我,在,使用,Sentinel,过程,中,踩,的,一些,坑,和,解决,方法,虽然,踩,了,不少,坑,熬,了,几个,夜,但是,整体,来说,Sentinel,还是,一个,很,优秀,的,限流,熔断,组件,功能,全面,性能,也,不错,和,Spring Cloud,集成,方便,社区,也,比较,活跃,遇到,问题,基本,都,能,找到,解决方案,只要,注意,避开,这些,坑,用,起来,还是,很,顺手,的。

最后,给,也,想,用,或者,正在,用,Sentinel,的,朋友,一些,建议,第一,接入,前,认真,看,文档,了解,基本,概念,和,原理,比如,资源名,规则,类型,限流,熔断,的,原理,等等,理解,了,原理,很多,坑,就,能,避免,第二,先在测试环境验证,再上生产,不要,直接,上,生产,配置,规则,后,要,充分,测试,确保,规则,生效,异常,处理,正常,第三,做好规则持久化,生产环境,一定,不要,用,默认,的,内存,模式,要,配置,规则,持久化,避免,重启,后,规则,丢失,第四,做好监控和告警,对,限流,熔断,的,触发,情况,做,监控,和,告警,及时,了解,系统,状态,第五,根据实际情况配置规则,限流,阈值,熔断,参数,等等,要,根据,实际,情况,配置,不要,拍脑袋,而且,要,根据,监控,数据,持续,调整,优化。

希望,这篇,文章,能,给,大家,一些,参考,帮助,大家,避开,这些,坑,更,好,地,使用,Sentinel,也,欢迎,大家,在,评论,区,分享,你们,使用,Sentinel,的,经验,和,踩过,的,坑,一起,交流,一起,进步,谢谢,大家,的,阅读。