已经存在的解决方案
- springcloud已经提供sleuth,搭建Zipkin
- logback提供了MDC,可以再日志里面打印
其实不管啥方法,都是aop或者Filter 拦截里面加个标识
在spring boot各个组件之间调用的时候,要表标识带过去,也都是用的ThreadLocal
为啥不自己实现一把
我希望啥呢,打印日志更规范,更加自动化,轻量级一点
- 啥规范呢,{开始时间,结束时间,并发量,哪里来的,入参是啥,出参是啥},讲清楚
- 请求Controller进来的,自动打日志,不需要额外说明
- 内部方法级日志加上@loger 就能打印日志
- 如果traceId不存在(外部来的),给他加上traceId,如果内部纯在,一直透传
- 包括rest和mq两种处理
- 外部请求进来,zuul要做鉴权的事情
- 内部组件互相调用,@FeignClient,要加traceId,对方收到之后,要将traceId放到ThreadLocal里面
- mq发送者,如果是自动发射,要生成uuid作为traceId,如果是线程内发射,需要透传uuid,如果是消费者,要透传traceId
- 要配置总的限流量,和各个接口的限流量,如果超过了,要降级
- 请求的接收者,如果request里面有traceId,就放到ThreadLocal里面
关于限流
https://my.oschina.net/loubobooo/blog/1796752 这篇讲了好几个算法
- 计数器法
- 滑动窗口
- 漏桶算法
- 令牌桶算法(对于令牌桶的代码实现,可以直接使用Guava包中的RateLimiter)
- alibaba-sentinel 也提供限流的方法
- spring-boot-starter-current-limiting 这个包也归纳的挺好
但是有个问题,限流针对时间段,1秒钟限流100个请求,那么1秒钟的第1ms一起进来,还是每20ms进来,其实是有区别的,
有的请求50ms就结束了,有的400ms,有的数据库卡住了,原来50ms的现在卡了1s也没释放掉。
所以我的想法是对于限流,限制的额是当前100个活跃,而不是每秒放100个进来
网关限流
第三方接入,或者遇到爬虫的
要针对第三方接入,ip限流,user进行限流,需要在nginx、zuul那边做限制
我觉得不应该到微服务这一层再限制
以前nginx做鉴权和限流,把redis拖垮了,所以正儿八经的并发,还是慎重,该静态文件的还是静态文件
限流也不单单技术的事儿,业务上也得配合,比如一些接口就应该单用户3-5s只能调一次,不应该无限制的让他调,就应该直接降级,让他稍后再试
比如单用户打赏,就算乐观锁余额,并发过来(经纪人团队对自己旗下的主播直接for循环打赏),一下子几千个请求进来,要扣款,要加款,可能都不在一个模块,特么要是不拒绝,全放进去,与其等到锁表事务回退,还不如一开始就拒绝,3秒钟一次否则直接降级,让他稍后再试,这样他下次执行的时候,自然就会改速度,对账也方便
关于降级
降级要有个默认的降级方法,也要针对各个Controller配置可以自定义降级方法