https://mp.weixin.qq.com/s/ipXPMtPawDdESMJYrYthcQ

一)线上事故:

催收系统每日自动分配案件时一直正常,突然某一天(2018-3-27)以后 案件分配不均匀,一系列追踪下查到原因是责任链 有一环 未被执行(kibana上当天2018-3-27 以后 未查看相应的日志记录) ,很奇怪 ,重启服务后 第二天 结果恢复正常

(二)分析问题:

分析 具体的催收分案业务 , 有手动分案(责任链模式)和每日自动分案(责任链模式)两种情形,未被执行的一环正好是 手动分案 相比 自动分案 缺少的一环

(三)问题猜想 :

查看 日志发现 当天 确实 存在手动分案的操作记录 ,猜想是手动分案 影响了 自动分案的功能

(四)查看代码,分析问题

@Servicepublic class DistributionHandlerHolder implements IDistributionHandlerHolder {
    /**     * 自动分案,逻辑最完备     */    private AbstractHandler autoDistribution;
    /**     * 手动分案,不记录上次催收人以及下次催收人等     */    private AbstractHandler manualDistribution;
    @Override    public AbstractHandler getAutoExecuteHandler() {        if(autoDistribution == null) {            synchronized(this) {                if(autoDistribution == null) {                    createAutoExecuteHandler();                }            }        }        return autoDistribution;    }
    @Override    public AbstractHandler getManualExecuteHandler() {        if(manualDistribution == null) {            synchronized(this) {                if(manualDistribution == null) {                    createManualExecuteHandler();                }            }        }        return manualDistribution;    }    private void createAutoExecuteHandler() {        AbstractHandler autoStart = null;        AbstractHandler autoPre = null;        for(AutoDistributionEnum distributionEnum : AutoDistributionEnum.values()) {            AbstractHandler handler = ApplicationContextHolder.getBean(distributionEnum.getBeanName(), AbstractHandler.class);            if(autoPre != null) {                autoPre.setNextHandler(handler);            }            if(autoStart == null) {                autoStart = handler;            }            autoPre = handler;        }        autoDistribution = autoStart;    }
    private void createManualExecuteHandler() {        AbstractHandler manualStart = null;        AbstractHandler manualPre = null;        for(ManualDistributionEnum distributionEnum : ManualDistributionEnum.values()) {            AbstractHandler handler = ApplicationContextHolder.getBean(distributionEnum.getBeanName(), AbstractHandler.class);            if(manualPre != null) {                manualPre.setNextHandler(handler);            }            if(manualStart == null) {                manualStart = handler;            }            manualPre = handler;        }        manualDistribution = manualStart;    }}
@Slf4jpublic abstract class AbstractHandler {
    
    protected AbstractHandler nextHandler;
       public void setNextHandler(AbstractHandler nextHandler) {        this.nextHandler = nextHandler;    }}
@Component("distributionUserSortHandler")@Slf4jpublic class UserSortHandler extends AbstractHandler {
    @Autowired    private IOrderService orderService;
    @Override    public void execute(DistributionRequest request, DistributionResponse response) {                nextHandler.execute(request, response);    }}
 
 

1、大体上看没有问题,

手动分案和自动分案是两条完全不同的

责任链创建过程

2、仔细观察是每个责任链 是单例模式 ,没有标记@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 注解 ,和大脑印象中代码不符合

3、仔细分析 : (1)自动分案 走 1-》2-》3-》4

(2)手动分案走 1-》2-》4

(3)先自动分案 ,后手动分案,造成 自动分案

被替换成   1-》2-》4,造成 3链缺失

(四) 解决方案:

每个责任链上加上@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)注解,造成

AbstractHandler handler =

ApplicationContextHolder.getBean(distributionEnum.getBeanName(), AbstractHandler.class);获取时获取到不同的对象 ,而不是spring单例对象

(五) 归纳总结:

spring 单例 最好无状态,责任链 的每一环必有状态(指向下一环),因为存在多条链路(多种业务情况)

所以每一环应该定义成多例(最好多例),否则就造成如上的线程间不安全的问题。

责任链模式 多条链路时 spring单例 造成的深坑相关推荐

  1. 用三国演义解读:责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀.东岭关, ...

  2. 三国演义:责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀. 东岭关 ...

  3. 设计模式 - 责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀. 东岭关 ...

  4. 责任链模式Java+Spring实现

    业务场景 一般的操作校验接口有参数校验.安全校验.黑名单校验.操作规则等等. 问题 常见同步编写code,校验失败return,代码链路较长,修改不符合开闭原则. 责任链模式定义 责任链模式为请求创建 ...

  5. Spring中如何使用责任链模式

    2019独角兽企业重金招聘Python工程师标准>>> 关于责任链模式,其有两种形式,一种是通过外部调用的方式对链的各个节点调用进行控制,从而进行链的各个节点之间的切换:另一种是链的 ...

  6. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  7. 设计模式(四)责任链模式——责任链模式结构

    定义 责任链是行为型设计模式的一种,通过前一个处理者记录下一个处理者的方式形成一条处理链.客户端在调用时只需要将请求传递到责任上即可,无需关注链路中的具体的传递过程.而链路中内部的处理,是按照前一个处 ...

  8. 【深入设计模式】责任链模式—责任链模式及责任链模式在源码中的应用

    文章目录 1. 责任链模式 1.1 责任链模式简介 1.2 责任链模式结构 1.3 责任链模式示例 2. 责任链模式在源码中的应用 2.1 Servlet 中的责任链模式 2.2 Spring 中的责 ...

  9. 设计模式-责任链模式~晚霞

    Chain of Responsibility Pattern Title Module Category Tags Chain of Responsibility chain-of-responsi ...

最新文章

  1. 互联网黄金十年的黄昏——是人工智能的黎明还是裁员的长夜
  2. vmware 利用镜像 配置yum本地源
  3. MR8M CANCEL INVOICE后为什么要手工去FI清帐
  4. Note cancel request的实现原理
  5. AngularJS控制器和过滤器学习(三)
  6. 探索Windows命令行系列(7):通过命令编译C#类和Java类
  7. XSS-Payloads集合
  8. 第 89 章 Hardware
  9. sklearn svm 调参_用 Grid Search 对 SVM 进行调参
  10. 打车日记 - 原年人念念不忘的茄汁大虾
  11. dependency标签
  12. html文件下载时的header设置
  13. 无法在驱动器0分区上安装windows解决方法
  14. wex5 导入mysql_Wex5铛铛开发环境搭建步骤
  15. http://nianjian.xiaze.com/tags.php?/%E4%B8%AD%E5%9B%BD%E7%B2%89%E4%BD%93%E5%B7%A5%E4%B8%9A%E5%B9%B4%
  16. 计算机自定义桌面设置在哪里设置,如何在windows10桌面设置自定义图片?查看方法...
  17. maven pom.xml解析、命令说明、依赖传递、继承、聚合、properties、build、依赖范围、版本仲裁、profile
  18. Axure8.0基础教程 一
  19. iOS小知识:如何使用教育商店购买Apple M1 Max
  20. 苹果 macOS 13 开发者预览版 Beta 11(内部版本号:22A5373b)发布

热门文章

  1. 结合代码看java虚拟机理解它的原理
  2. 数据结构视频教程 -《中国石油大学:数据结构》
  3. 缅怀逝去的青葱岁月, 忆“煤油灯”
  4. Matlab实验(六)
  5. 计算机连接公用网络受限,电脑网络受限怎么解决
  6. 定制软件开发:转变业务的解决方案
  7. 【JavaWeb】JDBC
  8. win7计算机sid,如何修改新萝卜家园win7系统电脑sid
  9. Windows下Neo4j下载安装以及错误解决【附安装资源】
  10. 《使命召唤》手游全球开测又没有中国区?我还是去玩台服吧!