2020 年底公司和阿里健康合作了一个检验项目,由我司提供检验项目(商品)、采样点(商户)、库存等底层数据,与阿里健康开发对接后在支付宝平台进行线上预售,开发流程其中也包括订单数据的交互。
项目开发期间踩了比较多的坑,做了很多优化,其中也包含一些有意思的技术实现方案。
一、时间轮实践
某些业务场景下,我们需要频繁调用阿里健康接口,项目第一个版本上线后,发现有部分请求触发阿里健康接口流控告警,原因是他们提供的接口在一定的时间内只允许 N 次接口调用。针对这个问题,想到了以下几种实现方式:
- sleep 同步调用:对批量数据进行拆分,每条数据都 sleep 一段时间
- ScheduledExecutorService 异步调用:延迟任务,通过线程池调度
- HashedWheelTimer(Netty) 异步调用:将批量数据按照一定延迟时间添加到时间轮队列中,等待调度
第 1 种方案如果同步批量数据过多,sleep 后客户端一直得不到响应,直接 pass。第 2 种方案需要频繁的创建和销毁线程池,考虑到客户端交互频繁,选择了时间轮方案。
当有任务添加到队列中后,Netty 时间轮会开启一个工作线程,后续所有任务的执行都依赖这个线程,因此不会频繁创建与销毁线程资源。但是有一个缺陷是当没有任务时,这个线程会一直空转,只要不同时存在多个时间轮,这个空转是可以接受的。
Netty 时间轮原理如下: