• 一个典型的后台软件系统的设计复盘——(三)打通任督二脉-context


    武侠小说练功讲究打通任督二脉。程序设计练到一定程度也讲究打通任督二脉。好奇心强的同学可以搜搜“打通任督二脉有什么感觉”。

    spring的任督二脉ApplicationContext

    最经典的任督二脉莫过于java中spring中的ApplicationContext。用惯spring的都会觉得,这里是这个各种实例的起源。概念解释就不搬砖了,见官网 http://spring.io/understanding/application-context
    于是乎,以前创建个jdbc需要 Class.forname() 一大堆反射出工厂类再 getConn() 得到个连接,现在只需要 context.getBean("配置名") 就能得到,还能有datasource各种实现以及高级的事务封装。而实际使用时更方便只需要个 @Autowired 。spring兴起之时大家都是在热议其实现了IoC控制反转原则,现在看来不仅如此,更重要的是,构造了整个bean管理体系BeanFactory,并用ApplicationContext打通了应用的任督二脉。

    曾见过一个稍微复杂的应用,Oracle一主一从一物理从,可是稍微用起来就数据库连接数不足。排查原因竟是ApplicationContext新建了三处,也就是说相应的连接池创建了三个。这里延伸出另一个概念,叫容器。官方的说法是,BeanFactory就是一个容器,ApplicationContext则是前者的扩展,也是个容器。在这个容器里,任督二脉是打通的,bean是创建好的、管理好的、相应依赖关系是清晰的。但现在的应用服务器多种多样,比如spring容器、spring boot容器、tomcat容器、dubbo容器,想清楚它们之间是否打通,可以避免一些很幽灵的坑。

    scoping和lifecycle-作用范围和生命周期

    应用1能不能通过ApplicationContext访问到应用2的类或对象?正常情况下不可以,这就是作用范围。而生命周期,则是指对象什么时候创建什么时候销毁什么时候变换状态。

    对这两个概念更好的理解是数据库事务。比如某用户账上有10元,操作1给他存入20元还没提交,操作2查询他当前账户余额,若两个操作在同个事务则查到结果为30元,若两个操作是不同事务则查到结果为10元,事务隔开了两者的作用范围。而操作1什么时候生效则是生命周期:开启事务-更新余额-提交数据库-成功关闭或失败回滚。

    复盘业务场景的任督二脉

    这里的场景是商品-订单-调度任务的打通。首先订单分汇总order和商品项detail,detail记录商品快照和批次也是很常识的。然后detail触发个调度任务job去执行。
    然而job开始结束成功失败都应该回来通知订单啊。job-detail有关联,没毛病。
    然后需求变更了,有的job是单个detail,有的job是若干detail。依然可以detail指向job,没毛病。

    又需求变更了,完成一个detail会有若干个job。。。第一反应当然是多对多。可是要按订单列出哪批detail做完了,order-detail-job并group by job未免太绕,于是建了一层订单拆分detailGroup。然而,真实的需求是,商品按货架归集,货架1的是若干个detail一起做,货架2的是单个detail,又引入一层实体为detailByShelf。

    场景是:对于货架1,detailByShelf近似于detailGroup。对于货架2,detailByShelf用于呈现,按货架列出详情;detailGroup仅有单个detail且用于job。
    job要回来更新订单状态,通过detailGroup即可。查询要按货架列出,则查询detailByShelf即可。用detailGroup把job和detail串起来放进job execution context,任督二脉算是打通了。

    然而需求并没有就这样停止。job会拆解成多个step,某些step会更新对应的detail。也就是说,step要和detail挂钩。然而特定的step是要更新整个detailGroup的状态的。。。

    所以,更精细的设计是:step-step context根据不同类型挂钩不同的订单项-detail或detailGroup。而状态更新通知是:

    step状态汇总到job
    step状态更新到detailGroup或detail,都汇总到detailGroup
    detail汇总到detailByShelf再汇总到order

    如何验证这个任督二脉是否完整打通了呢?可以套三个场景。
    1.step的状态(比job更精细)能更新到detail的所有层级。
    2.某一步step正在执行,可以追踪到整个订单以及其中的哪一项,比如 step - detail/detailGroup - order。
    3.按货架列出可以找到当前正在执行的是那一步以后,比如detailByShelf-detail-step-job
    再者,哪些job是服务于同个detailGroup,也要能串起来。

    所以,整个完整的打通是:
    job-detailGroup,若干个调度任务来完成一批商品
    step-detail和step-detailGroup,一个步骤操作对应的整批或这批中的一个商品项
    至此,整个任督二脉算是打通了,任务可以找到对应订单或商品,订单商品可以找到对应任务和步骤。

    整个场景非常混淆的两个点是:
    1.detailByShelf只是查询场景要用,不能混入context。因为对于货架2,一个job只做一个detail项,detailByShelf根本不能表达相应的关系。
    2.step什么时候关联detailGroup?不是整批或单个商品项的区别,而是这个step本身的不同。

    如果问我,程序打通任督二脉是什么感觉?我会回答,应该是,程序中想要的关联信息都能取到,数据库中想要的信息用几个简单查询就能捞出来 的感觉吧。

  • 相关阅读:
    项目工作总结 (转)
    mysql-笔记 操作语句
    QTP自动化测试-excel sheet页数量过多--但是不能在qtp里被识别
    mysql-笔记 定义语句
    HDU
    CodeForces
    CodeForces
    CodeForces
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/syjkfind/p/6538266.html
Copyright © 2020-2023  润新知