美文网首页
spring-reactor 框架的使用不当导致线上大量商品无法

spring-reactor 框架的使用不当导致线上大量商品无法

作者: 天草二十六_简村人 | 来源:发表于2018-09-28 17:07 被阅读0次

    技术选型:

    使用的是reactor和spring-reactor,本意是替代了多线程之线程池技术。

    1、定时任务(3分钟轮询一次)发货失败的记录 ----》 trade服务

    2、实时接口,第三方支付回调成功,异步发货 ----》trade服务

    这里说下当时的线上错误现象:

    用户在平台下单, 等待用户在第三方支付方支付成功, 第三方回调平台trade服务。

    如果支付成功,异步开始调用发货方去发货,将订单状态由已支付变更为已发货。由于防止发货出现超时等失败情况,需要定时轮询发货失败的记录进行重试发货。

    当时出现发货问题:

    部分发货失败,检查发货的URL,能ping通,排除是网络问题。由于是部分成功,部分失败,怀疑是DNS解析不稳定导致。因为这一点猜到,错误地导向了去检查DNS域名解析。

    (备注:发生问题的前后, 程序和数模都没发布变更)

    排除了不是运维方面的问题后, 逐步检查程序写法是否出问题:

    1、多个实时发货和任务调度,虽然是共用java发货代码,但是是不同的reactor事件,固化地认为是多线程机制,每个发货事件之间是无不干扰的才对。

    2、由于发货失败是部分的现象,而我们是有任务调度补偿发货机制。怀疑是任务调度没执行。因为在线上不能断点调试,只能在预发环境,对发货任务进行断点调试。任务调度是执行了,只是执行的周期太长。发现了一个特殊的发货URL地址,一直卡着,无法继续断点执行下去。

    3、由于发货是去调用第三方发货系统,怀疑是okhttp框架的连接池的可用连接数满了,从而阻塞了后面的请求发货。发现我们并没有手动去设置连接池大小,而框架的连接池大小为2147483647,可以说足够大了,我们的单量远不足于撑爆连接池。

    static {

    executor =new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue(), Util.threadFactory("OkHttp ConnectionPool", true));

    }

    4、回到第二点,发货卡太久的问题,我们刚开始想的是3秒就会超时,不至于卡住后面的发货。看了下okhttp的配置

    http.connectTimeout=100000

    http.readTimeout=100000

    http.writeTimeout=100000

    http.maxIdleConnections=5

    http.keepAliveDurationNs=5

    超时时间为100秒,而我们发货在失败后,会再重试两次。每笔订单就耗费了3分钟。而当时不通的发货地址有4条。加起来就至少12分钟的阻塞,只有在12分钟后,才会执行后面的实时发货。

    但是怎么也解释不了:这4笔订单发货超时,而导致其他的订单也无法去尝试发货,都没有能调用发货请求。

    5、当时紧急的解决方案,把4笔订单删掉,后面的任务调度和实时发货就顺畅了。

    6、后面在开发环境调试,确定reactor的各个事件是单线程的,默认的dispatcher是SynchronousDispatcher。

    这里简单归类下有哪些dispatcher:

    public static final String DISPATCHER_GROUP ="dispatcherGroup";

    public static final String SHARED ="shared";

    public static final String MPSC ="mpsc";

    public static final String THREAD_POOL ="threadPoolExecutor";

    public static final String WORK_QUEUE ="workQueue";

    相关文章

      网友评论

          本文标题:spring-reactor 框架的使用不当导致线上大量商品无法

          本文链接:https://www.haomeiwen.com/subject/wnarcftx.html