精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

ToB復(fù)雜業(yè)務(wù)狀態(tài)的可復(fù)用的解決方案

開發(fā) 架構(gòu)
今天就介紹關(guān)于一個(gè)業(yè)務(wù):狀態(tài)變多、條件分支增多、狀態(tài)轉(zhuǎn)換規(guī)則、依賴關(guān)系變復(fù)雜,導(dǎo)致代碼難以維護(hù),代碼可重用性和可擴(kuò)展性變差這個(gè)問題,一套可復(fù)用解決方案。

年底了大家都要述職,老板都會(huì)問:你這個(gè)方案,是否沉淀形成一套可復(fù)用解決方案?

今天就介紹關(guān)于一個(gè)業(yè)務(wù):狀態(tài)變多、條件分支增多、狀態(tài)轉(zhuǎn)換規(guī)則、依賴關(guān)系變復(fù)雜,導(dǎo)致代碼難以維護(hù),代碼可重用性和可擴(kuò)展性變差這個(gè)問題,一套可復(fù)用解決方案。

1.問題背景

產(chǎn)品:來活啦,有用戶反饋我們的APP沒有線上退保證金功能,都在抖音上找到老板反饋了。

產(chǎn)品:我們商戶入駐狀態(tài)有:未入駐、待入駐、已入駐、清退中、已清退。清退中又有子狀態(tài) 商戶申請(qǐng)關(guān)戶中、統(tǒng)計(jì)商戶有責(zé)貨損中、待商戶確認(rèn)有責(zé)貨損、申訴商戶有責(zé)貨損中、提現(xiàn)失敗、提現(xiàn)成功、已清退等。

我這里簡(jiǎn)單畫一下關(guān)戶狀態(tài)流轉(zhuǎn)圖

圖片圖片

2.如何解決狀態(tài)問題

在軟件開發(fā)過程中,隨著功能的不斷迭代和添加,代碼的可維護(hù)性往往會(huì)面臨挑戰(zhàn)。

我們有一個(gè)商戶入駐的功能,功能也是由簡(jiǎn)單迭代到復(fù)雜,現(xiàn)在又要增加商戶退出、重新入駐相關(guān)狀態(tài),狀態(tài)轉(zhuǎn)換邏輯也變得復(fù)雜,在這個(gè)迭代過程中,我們?nèi)绾畏乐故荷酱a形成?

2.1 解耦重構(gòu)優(yōu)化代碼

項(xiàng)目初期,狀態(tài)比較少,我們通過如下方法重構(gòu)代碼就可以解決問題。

圖片圖片

下面是我們重構(gòu)優(yōu)化代碼的例子。

重構(gòu)前:入駐方法很長,所有業(yè)務(wù)代碼邏輯耦合在一起。

class A {
  //入駐方法
  public void join() { 
   if(未入駐過){
     // 實(shí)人認(rèn)證
     //查詢關(guān)聯(lián)賬號(hào)
   ...//其他業(yè)務(wù)邏輯
   }else if(曾入駐過){
   
    //查詢關(guān)聯(lián)賬號(hào)
   //計(jì)算售后率
   ...//其他業(yè)務(wù)邏輯
   }
}

重構(gòu)后:提取出實(shí)人認(rèn)證、計(jì)算售后率等方法。

class A {
   //入駐方法
   public void join() { 
      if(未入駐過){
       // 實(shí)人認(rèn)證
      realPersonAuthentication();
       ...//其他業(yè)務(wù)邏輯
      }else if(曾入駐過){
       //計(jì)算售后率
       calculatingAfterSalesRate();
       ...//其他業(yè)務(wù)邏輯
      }
      //查詢關(guān)聯(lián)賬號(hào)
      associatedAccount();
    }
    public void realPersonAuthentication() { 
    // 實(shí)人認(rèn)證
    }
   
    public void associatedAccount() { 
    //查詢關(guān)聯(lián)賬號(hào)
    }
    public void calculatingAfterSalesRate() {
    //計(jì)算售后率
    }
}

2.2 使用設(shè)計(jì)模式重構(gòu)優(yōu)化

使用狀態(tài)模式、策略模式等都能幫助我們的代碼清晰易讀。

下面就是個(gè)狀態(tài)模式解決不同入駐狀態(tài)下商戶擁有不同權(quán)限的例子,如果你的業(yè)務(wù)場(chǎng)景有如下特點(diǎn),那么可以嘗試使用狀態(tài)模式優(yōu)化。

1)對(duì)象行為取決于狀態(tài)。

比如商戶是否可以送檢行為取決于商戶的已入駐狀態(tài)。

2)狀態(tài)轉(zhuǎn)換邏輯復(fù)雜。

比如商戶申請(qǐng)關(guān)戶中、待確認(rèn)貨損狀態(tài)才能撤銷關(guān)戶等。

3)避免大量條件語句。

這個(gè)業(yè)務(wù)場(chǎng)景,如果使用ifelse判斷,需要寫6個(gè),代碼也不好擴(kuò)展維護(hù)。

業(yè)務(wù)規(guī)則:

圖片圖片

狀態(tài)模式類圖:

狀態(tài)模式類圖狀態(tài)模式類圖

2.3 使用狀態(tài)機(jī)

如果你的狀態(tài)很多,并且轉(zhuǎn)換邏輯很復(fù)雜的時(shí)候,我們可以使用狀態(tài)機(jī),幫助我們進(jìn)行狀態(tài)管理。

2.3.1 思考狀態(tài)機(jī)特點(diǎn)

看上面狀態(tài)圖,思考我們開發(fā)的其他場(chǎng)景的狀態(tài)流轉(zhuǎn)圖,這些場(chǎng)景是不是有以下共同特點(diǎn):1)根據(jù)不同觸發(fā)條件執(zhí)行不同處理動(dòng)作最后轉(zhuǎn)變?yōu)樾碌臓顟B(tài)(狀態(tài)也有可能不變)。

2)狀態(tài)間轉(zhuǎn)換邏輯比較復(fù)雜。如果使用ifelse進(jìn)行判斷,業(yè)務(wù)復(fù)雜之后很難維護(hù)。

3)各個(gè)狀態(tài)轉(zhuǎn)換分散在不同方法中,很難清晰知道狀態(tài)全部的流轉(zhuǎn)規(guī)則。

2.3.2 總結(jié)歸納狀態(tài)機(jī)特點(diǎn)

針對(duì)狀態(tài)流轉(zhuǎn)過程,其實(shí)是有很多相似的地方,我們可以簡(jiǎn)單總結(jié)歸納一下。

1)我們可以考慮將狀態(tài)全部從業(yè)務(wù)層抽離,統(tǒng)一進(jìn)行收口維護(hù)。

2)抽象狀態(tài)流轉(zhuǎn)規(guī)則, 比如:已入駐 狀態(tài)轉(zhuǎn)變?yōu)?清退中 狀態(tài),需要原狀態(tài)是已入駐,并要完成一些業(yè)務(wù)操作(記錄申請(qǐng)信息,通知商戶、BD等等)。

3)我們將狀態(tài)流轉(zhuǎn)規(guī)則也進(jìn)行統(tǒng)一維護(hù)(配置文件配置、代碼里寫死配置、數(shù)據(jù)庫里配置等),這樣便能清晰看到全部流轉(zhuǎn)規(guī)則,簡(jiǎn)化狀態(tài)管理。

3.狀態(tài)機(jī)介紹

狀態(tài)機(jī)其實(shí)很簡(jiǎn)單,不然也不會(huì)這么流行。由上面抽象總結(jié)出來的方法,其實(shí)就是狀態(tài)機(jī)。狀態(tài)機(jī)的概念很早就提出了,而且比Java語言本身還要早。(詳見百度百科)

3.1 狀態(tài)機(jī)的四大概念

狀態(tài)機(jī)核心概念狀態(tài)機(jī)核心概念

第一個(gè)是State,狀態(tài)。一個(gè)狀態(tài)機(jī)至少要包含兩個(gè)狀態(tài)。例如上面例子,有 未入駐、已入駐、清退中、已清退等多個(gè)狀態(tài)。

第二個(gè)是Event,事件。事件就是執(zhí)行某個(gè)操作的觸發(fā)條件。對(duì)于關(guān)戶流程,”申請(qǐng)關(guān)戶” 就是一個(gè)事件。

第三個(gè)是Action,動(dòng)作。事件發(fā)生以后要執(zhí)行的動(dòng)作。例如事件是“申請(qǐng)關(guān)戶”,動(dòng)作是“記錄申請(qǐng)信息、通知BD聯(lián)系商戶等”。編程的時(shí)候,一個(gè)Action一般就對(duì)應(yīng)一個(gè)函數(shù)或者類。

第四個(gè)是Transition,描述了一個(gè)狀態(tài)機(jī)如何從一個(gè)狀態(tài)轉(zhuǎn)換到另一個(gè)狀態(tài)相關(guān)規(guī)則、條件。當(dāng)特定的 Event事件發(fā)生時(shí),狀態(tài)機(jī)會(huì)根據(jù)Transition規(guī)則執(zhí)行狀態(tài)轉(zhuǎn)換。這個(gè)過程中,可能伴隨著動(dòng)作(Action)的執(zhí)行,這些動(dòng)作可以是狀態(tài)進(jìn)入前執(zhí)行的預(yù)處理、狀態(tài)轉(zhuǎn)換時(shí)執(zhí)行的中間操作或狀態(tài)退出后執(zhí)行的清理工作。例如 “商戶操作入駐,狀態(tài)從未入駐轉(zhuǎn)到已入駐” 就是一個(gè)變換。

3.2 狀態(tài)機(jī)的優(yōu)點(diǎn)

參考網(wǎng)上各種描述,這里就簡(jiǎn)單提一下

1)清晰的狀態(tài)管理:其實(shí)就是統(tǒng)一在一個(gè)地方配置轉(zhuǎn)態(tài)流轉(zhuǎn)規(guī)則,這有助于確保系統(tǒng)的行為符合預(yù)期(可以在配置文件配置,代碼寫死,數(shù)據(jù)庫配置流轉(zhuǎn)規(guī)則),減少錯(cuò)誤和不確定性。

2)易于維護(hù)和擴(kuò)展:狀態(tài)機(jī)的結(jié)構(gòu)使得對(duì)系統(tǒng)的修改和擴(kuò)展變得更加容易。由于狀態(tài)機(jī)的各個(gè)部分相對(duì)獨(dú)立,因此可以在不干擾其他部分的情況下添加新狀態(tài)或修改現(xiàn)有狀態(tài)

3)促進(jìn)團(tuán)隊(duì)溝通:比如前面的狀態(tài)流轉(zhuǎn)圖,狀態(tài)機(jī)提供了一種圖形化的方式來描述系統(tǒng)行為,這對(duì)于團(tuán)隊(duì)成員之間的溝通非常有幫助。非技術(shù)團(tuán)隊(duì)成員也能理解狀態(tài)圖,從而更好地參與項(xiàng)目討論

4.狀態(tài)機(jī)對(duì)比與選型

下面我們就介紹幾種狀態(tài)機(jī)的核心實(shí)現(xiàn),大家可以作為參考,搭建符合自己業(yè)務(wù)場(chǎng)景的狀態(tài)機(jī)。

4.1 轉(zhuǎn)轉(zhuǎn)狀態(tài)機(jī)

轉(zhuǎn)轉(zhuǎn)狀態(tài)機(jī)主要看這個(gè)圖。

轉(zhuǎn)轉(zhuǎn)狀態(tài)機(jī)流程圖轉(zhuǎn)轉(zhuǎn)狀態(tài)機(jī)流程圖

1)項(xiàng)目啟動(dòng),從Mysql數(shù)據(jù)庫讀取狀態(tài)機(jī)配置的狀態(tài)轉(zhuǎn)換規(guī)則Transition,并在內(nèi)存使用Map保存。

2)Event事件發(fā)生后,根據(jù)當(dāng)前狀態(tài)、事件到Map獲取對(duì)應(yīng)的Action執(zhí)行。

3)這是init()方法加載轉(zhuǎn)換規(guī)則,轉(zhuǎn)換為Map,Map<String, List> fsmNodeMap,key是事件+當(dāng)前狀態(tài),value是要執(zhí)行的FsmNode類。

public class FsmNode {
    private Integer opType;
    private Integer role;
    private Integer sourceStatus;
    private Integer targetStatus;
    private NodeType nodeType;
    private FsmAction action;
    private HashSet<JobConfig> jobConfigs;
    private HashSet<TransactionConfig> transactionConfigs;
}

總結(jié)起來有如下特點(diǎn)

1)把狀態(tài)機(jī)流轉(zhuǎn)條件、執(zhí)行的業(yè)務(wù)類名(Transition)配置到數(shù)據(jù)庫。如果你的狀態(tài)機(jī)、狀態(tài)轉(zhuǎn)換條件特別多,那么存儲(chǔ)在數(shù)據(jù)庫就很方便查找。

2)通過定時(shí)任務(wù)輪訓(xùn)數(shù)據(jù)表,重試執(zhí)行失敗的Action。

3)無狀態(tài)設(shè)計(jì),每次狀態(tài)流轉(zhuǎn)無需生成狀態(tài)機(jī)實(shí)例,只要根據(jù)當(dāng)前狀態(tài)、事件到Map里找到需要執(zhí)行的Action及job來執(zhí)行就好。

4)支持每次狀態(tài)轉(zhuǎn)換的時(shí)候發(fā)送事務(wù)消息(結(jié)合數(shù)據(jù)庫事務(wù)實(shí)現(xiàn))適用場(chǎng)景:狀態(tài)機(jī)轉(zhuǎn)換條件配置特別多,需要定時(shí)任務(wù)補(bǔ)償執(zhí)行,需要在狀態(tài)轉(zhuǎn)換時(shí)候發(fā)送事務(wù)消息的場(chǎng)景。

以上就是宙斯?fàn)顟B(tài)機(jī)的核心功能,總結(jié)來說就是:把事件、當(dāng)前狀態(tài)、目標(biāo)狀態(tài)、要執(zhí)行的Action類配置數(shù)據(jù)庫里,執(zhí)行時(shí)候根據(jù)這個(gè)配置來查找Action并執(zhí)行。

4.2 Cola狀態(tài)機(jī)

參考Cola的官方文檔。阿里團(tuán)隊(duì)覺得開源狀態(tài)機(jī)不好用,太復(fù)雜且性能差,就自己寫了一個(gè)簡(jiǎn)潔版狀態(tài)機(jī)。詳見博客

Cola狀態(tài)機(jī)是一個(gè)輕量級(jí)的開源框架,相比Spring Statemachine和squirrel-foundation,它更加簡(jiǎn)單、輕量且性能極高。

Cola狀態(tài)機(jī)主要有如下特點(diǎn):

1)簡(jiǎn)單、輕量,僅支持狀態(tài)流轉(zhuǎn)的狀態(tài)機(jī),不支持嵌套、并行等高級(jí)玩法。

2)無狀態(tài)設(shè)計(jì)。可以使用一個(gè)狀態(tài)機(jī)實(shí)例來響應(yīng)所有的請(qǐng)求。

適用場(chǎng)景:Cola狀態(tài)機(jī)適用于需要高并發(fā)支持且希望簡(jiǎn)化狀態(tài)管理的場(chǎng)景。

4.2.1 Cola狀態(tài)機(jī)核心源碼解析

Cola 狀態(tài)機(jī)本質(zhì)上是狀態(tài)模式+兩個(gè)Map。

核心類核心類

第一個(gè)Map,Map<S, State< S, E, C>> stateMap,key為當(dāng)前狀態(tài),value為State對(duì)象。

State對(duì)象類似狀態(tài)模式,內(nèi)部存儲(chǔ)了狀態(tài)轉(zhuǎn)移transitions map,即第二個(gè)Map。

第二個(gè)Map,HashMap<E, Transition<S, E,C>> transitions,在State對(duì)象內(nèi)部,key是Event事件,value是Transition對(duì)象,Transition內(nèi)有要執(zhí)行的Action、初始狀態(tài)、目標(biāo)狀態(tài)、驅(qū)動(dòng)事件(Event)等。

執(zhí)行過程

1)業(yè)務(wù)代碼執(zhí)行入口,根據(jù)當(dāng)前狀態(tài)、事件傳參執(zhí)行。

StateMachine<States, Events, Context> stateMachine = builder.build(MACHINE_ID+"1");
        //觸發(fā)一次事件代碼
        States target = stateMachine.fireEvent(States.STATE2, Events.EVENT1, new Context());

2)根據(jù)當(dāng)前狀態(tài)找到map里的State。

public S fireEvent(S sourceStateId, E event, C ctx){
        isReady();
        //找到當(dāng)前狀態(tài)對(duì)應(yīng)的State
        State sourceState = getState(sourceStateId);
        //執(zhí)行
        return doTransition(sourceState, event, ctx).getId();
    }

3)從State里找到另一個(gè)Map,transitions,找到map配置的value,轉(zhuǎn)換規(guī)則。

private State<S, E, C> doTransition(State sourceState, E event, C ctx) {
        //找到對(duì)應(yīng)的Transition
        Optional<Transition<S,E,C>> transition = sourceState.getTransition(event);
        if(transition.isPresent()){
          //執(zhí)行
            return transition.get().transit(ctx);
        }
        Debugger.debug("There is no Transition for " + event);
        return sourceState;
    }

4)找到Transition里的action執(zhí)行。

@Override
    public State<S, E, C> transit(C ctx) {
        Debugger.debug("Do transition: "+this);
        this.verify();
        if(condition == null || condition.isSatisfied(ctx)){
            if(action != null){
            //執(zhí)行具體的action
                action.execute(source.getId(), target.getId(), event, ctx);
            }
            return target;
        }

        Debugger.debug("Condition is not satisfied, stay at the "+source+" state ");
        return source;
    }

Cola的源碼很簡(jiǎn)單,就是把當(dāng)前狀態(tài)、觸發(fā)的事件、目標(biāo)狀態(tài)、執(zhí)行的業(yè)務(wù)Action都配置兩個(gè)Map里,執(zhí)行時(shí)候根據(jù)當(dāng)前狀態(tài),事件分別去兩個(gè)map里拿Action出來執(zhí)行就好了。

4.3 Spring Statemachine

參考Spring Statemachine的官方文檔。Spring官方提供的一個(gè)狀態(tài)機(jī)框架,支持狀態(tài)的嵌套(substate)、狀態(tài)的并行(parallel, fork, join)、子狀態(tài)機(jī)等高級(jí)特性。

1)簡(jiǎn)單易用

2)狀態(tài)機(jī)結(jié)構(gòu)層次化,有助于簡(jiǎn)化狀態(tài)控制的開發(fā)過程。

3、功能完備。與Cola狀態(tài)機(jī)類似,也包括狀態(tài)(State)、事件(Event)、轉(zhuǎn)換(Transition)、動(dòng)作(Action)等要素。并提供了更豐富的狀態(tài)類型配置,如choice、join、fork、history等。

適用場(chǎng)景:適用于需要將復(fù)雜邏輯拆分為較小可管理任務(wù)、狀態(tài)嵌套或需要循環(huán)遍歷if-else結(jié)構(gòu)并進(jìn)行異常處理的場(chǎng)景。

4.3.1 部分源碼解析

1)我們看看狀態(tài)轉(zhuǎn)換時(shí),sendEvent都進(jìn)行了哪些操作。

Region.sendEvent() 向狀態(tài)機(jī)發(fā)布事件。

private Flux<StateMachineEventResult<S, E>> handleEvent(Message<E> message) {
  
  //檢查狀態(tài)機(jī)錯(cuò)誤 
//如果狀態(tài)機(jī)存在錯(cuò)誤(通過hasStateMachineError()方法檢查),則立即返回一個(gè)包含單個(gè)StateMachineEventResult對(duì)象的Flux流。
  //這個(gè)對(duì)象表示事件被拒絕(ResultType.DENIED),并包含了當(dāng)前狀態(tài)機(jī)實(shí)例、原始消息和拒絕結(jié)果類型。
  if (hasStateMachineError()) {
   return Flux.just(StateMachineEventResult.<S, E>from(this, message, ResultType.DENIED));
  }
  //處理正常事件流:
  return Mono.just(message)
   .map(m -> getStateMachineInterceptors().preEvent(m, this))
   .flatMapMany(m -> acceptEvent(m))
   .onErrorResume(error -> Flux.just(StateMachineEventResult.<S, E>from(this, message, ResultType.DENIED)))
   .doOnNext(notifyOnDenied());
 }

AbstractStateMachine.acceptEvent()接收事件。

//發(fā)送事件并收集結(jié)果:
    return cs.sendEvent(message)
     .collectList()
  //處理發(fā)送事件的結(jié)果:
使用collectList().flatMapMany(l -> {...})來收集sendEvent的結(jié)果,并將它們轉(zhuǎn)換為一個(gè)新的Flux流。
     .flatMapMany(l -> {
      Flux<StateMachineEventResult<S, E>> ret = Flux.fromIterable(l);
      if (!l.stream().anyMatch(er -> er.getResultType() == ResultType.ACCEPTED)) {
       Mono<StateMachineEventResult<S, E>> result = Flux.fromIterable(transitions)
        .filter(transition -> cs != null && transition.getTrigger() != null)
        .filter(transition -> StateMachineUtils.containsAtleastOne(transition.getSource().getIds(), cs.getIds()))
        .flatMap(transition -> {
  //查找可接受的觸發(fā)條件:
遍歷狀態(tài)轉(zhuǎn)換(transitions),找到與當(dāng)前狀態(tài)和事件負(fù)載匹配的觸發(fā)條件。
對(duì)每個(gè)匹配的觸發(fā)條件,評(píng)估其是否應(yīng)該觸發(fā)(通過transition.getTrigger().evaluate(triggerContext))。
如果觸發(fā)條件評(píng)估為真,則使用stateMachineExecutor.queueEvent將事件加入隊(duì)列,并設(shè)置一個(gè)回調(diào)來處理執(zhí)行結(jié)果。
  
         return Mono.from(transition.getTrigger().evaluate(triggerContext))
          .flatMap(
  ...
      
      return ret;

StateMachineExecutor.queueEvent()將事件添加到狀態(tài)機(jī)的隊(duì)列。

public Mono<Void> queueEvent(Mono<Message<E>> message, StateMachineExecutorCallback callback) {
  //這行代碼將傳入的事件消息(message)和一個(gè)延遲事件列表(deferList)合并成一個(gè)單一的Flux<Message<E>>流。這意味著所有這些事件都將按順序被處理。
  Flux<Message<E>> messages = Flux.merge(message, Flux.fromIterable(deferList));

  MonoSinkStateMachineExecutorCallback triggerCallback = new MonoSinkStateMachineExecutorCallback();
  Mono<Void> triggerCallbackSink = Mono.create(triggerCallback);

  return messages
   .flatMap(m -> handleEvent(m, callback, triggerCallback))
   .flatMap(tqi -> Mono.fromRunnable(() -> {
     triggerSink.emitNext(tqi, EmitFailureHandler.FAIL_FAST);
    })
    .retryWhen(Retry.fixedDelay(10, Duration.ofMillis(10))))
   .then()
   .and(triggerCallbackSink);
 }

從上面的源碼我們大概可以看出 Spring狀態(tài)機(jī)內(nèi)部通過事件發(fā)布、訂閱和線程池、阻塞隊(duì)列實(shí)現(xiàn)了整個(gè)狀態(tài)的流轉(zhuǎn)。到這里介紹完畢Spring狀態(tài)機(jī),詳細(xì)使用建議參考官方文檔,里面有很多高級(jí)用法,這里只是進(jìn)行簡(jiǎn)單功能介紹。

5.選型總結(jié)

特性

Cola狀態(tài)機(jī)

Spring狀態(tài)機(jī)

轉(zhuǎn)轉(zhuǎn)狀態(tài)機(jī)

集成性

較為獨(dú)立,但易于集成到其他Java項(xiàng)目中

與Spring框架緊密集成,方便使用Spring的各種特性(如依賴注入、AOP等)

依賴數(shù)據(jù)庫,易于集成到Java項(xiàng)目

功能豐富性

支持基本的狀態(tài)定義和轉(zhuǎn)換

提供了完整的狀態(tài)機(jī)功能,包括狀態(tài)定義、事件觸發(fā)、動(dòng)作執(zhí)行、狀態(tài)轉(zhuǎn)換和守衛(wèi)條件等,并發(fā)狀態(tài)、子狀態(tài)機(jī)

支持基本的狀態(tài)定義和轉(zhuǎn)換,同時(shí)提供失敗重試、事務(wù)消息等功能

學(xué)習(xí)成本

低,源碼較簡(jiǎn)單,同步API,使用更為直觀

較高,使用Reactive的Mono、Flux等響應(yīng)式編程模型

較低,源碼較簡(jiǎn)單易理解

使用場(chǎng)景

適用于中小型項(xiàng)目、需要輕量級(jí)狀態(tài)機(jī)管理的場(chǎng)景

適用于需要管理復(fù)雜狀態(tài)轉(zhuǎn)換邏輯、與Spring框架緊密結(jié)合的業(yè)務(wù)場(chǎng)景

需要輕量級(jí)狀態(tài)機(jī)管理,狀態(tài)機(jī)配置較多場(chǎng)景

5.1 業(yè)務(wù)簡(jiǎn)單用Cola狀態(tài)機(jī)

從前面的源碼分析來看,Cola狀態(tài)機(jī)通過兩個(gè)map來實(shí)現(xiàn)狀態(tài)流轉(zhuǎn),源碼簡(jiǎn)單易懂,擴(kuò)展也方便。更加簡(jiǎn)潔和直觀的狀態(tài)管理方式。如果你的項(xiàng)目比較簡(jiǎn)單,開發(fā)人員也比較少,僅使用狀態(tài)機(jī)輔助狀態(tài)流轉(zhuǎn),在滿足業(yè)務(wù)需求的前提下,可以考慮使用Cola狀態(tài)機(jī)。

5.2 業(yè)務(wù)復(fù)雜用Spring Statemachine

Spring Statemachine源碼、功能相對(duì)復(fù)雜,使用起來不夠直觀;同時(shí)不是無狀態(tài)的,因此在線程安全性方面需要額外的處理,但是功能完備,提供了豐富的狀態(tài)和事件處理機(jī)制,與Spring框架緊密集成,可以利用Spring的依賴注入、面向切面編程等特性,方便地進(jìn)行擴(kuò)展和集成。如果你的狀態(tài)轉(zhuǎn)換比較復(fù)雜,涉及到層次化狀態(tài)、并發(fā)狀態(tài)、子狀態(tài)機(jī),同時(shí)研發(fā)人員較多,研發(fā)實(shí)力較強(qiáng),后續(xù)考慮擴(kuò)展功能,可以考慮使用Spring的狀態(tài)機(jī)。

5.3 個(gè)性化訴求自研

如果你考慮自研狀態(tài)機(jī),并且你的狀態(tài)轉(zhuǎn)換比較多,或者轉(zhuǎn)換后,Action有重試需求,也可以參考轉(zhuǎn)轉(zhuǎn)宙斯?fàn)顟B(tài)機(jī),將狀態(tài)轉(zhuǎn)換邏輯配置到數(shù)據(jù),方便查找狀態(tài)轉(zhuǎn)換配置及從數(shù)據(jù)庫獲取Action數(shù)據(jù)進(jìn)行重試處理。

5.4 B2B復(fù)雜業(yè)務(wù)場(chǎng)景選型

下面是我把B2B整個(gè)保賣業(yè)務(wù)簡(jiǎn)化之后的流程圖,大家可以看到整個(gè)鏈路流程是很長很復(fù)雜。

保賣業(yè)務(wù)流程簡(jiǎn)圖保賣業(yè)務(wù)流程簡(jiǎn)圖

分而治之。我們把長鏈路劃分多為個(gè)階段,每個(gè)階段有自己的狀態(tài),使用狀態(tài)機(jī)來管理每個(gè)階段狀態(tài)流轉(zhuǎn),這樣就能把復(fù)雜問題簡(jiǎn)化為每個(gè)小問題解決。

回收段:

回收段狀態(tài)圖回收段狀態(tài)圖


銷售段:

圖片圖片

售后段:

圖片圖片

篇幅有限,就不列出詳細(xì)代碼了。

我們?cè)诒Yu業(yè)務(wù)、關(guān)戶退保證金項(xiàng)目中使用Spring狀態(tài)機(jī),主要考慮是我們業(yè)務(wù)場(chǎng)景特別復(fù)雜。同時(shí),我們根據(jù)保賣業(yè)務(wù)特點(diǎn),在Spring狀態(tài)機(jī)基礎(chǔ)功能上進(jìn)行一些擴(kuò)展。

調(diào)研發(fā)現(xiàn)B2B行業(yè)友商也使用了Spring狀態(tài)機(jī),他們考慮點(diǎn)也是狀態(tài)機(jī)對(duì)于復(fù)雜的業(yè)務(wù)場(chǎng)景的支持。

1)性能方面,我們B2B業(yè)務(wù)對(duì)并發(fā)性能要求不高,但是業(yè)務(wù)復(fù)雜度高,Spring狀態(tài)機(jī)性能完全可以滿足我們需求。

2)功能方面,Spring狀態(tài)機(jī)功能比較豐富,支持子狀態(tài)等,而我們業(yè)務(wù)需求比較復(fù)雜,同時(shí)有子狀態(tài)等業(yè)務(wù)場(chǎng)景,它可以滿足我們的業(yè)務(wù)需求。

3)Spring狀態(tài)機(jī)提供狀態(tài)機(jī)事件監(jiān)聽器,允許開發(fā)者監(jiān)聽狀態(tài)機(jī)的各種事件,如狀態(tài)變化、轉(zhuǎn)換觸發(fā)等,從而執(zhí)行相應(yīng)的業(yè)務(wù)邏輯。我們的關(guān)戶需求,也需要在關(guān)戶申請(qǐng)、申訴通過等節(jié)點(diǎn)觸發(fā)時(shí)進(jìn)行一些通用業(yè)務(wù)邏輯。

4)我們?cè)赟pring狀態(tài)機(jī)基礎(chǔ)上擴(kuò)展出事務(wù)消息,主要是基于Mysql數(shù)據(jù)庫表的事務(wù)實(shí)現(xiàn)。

5)擴(kuò)展出失敗重試功能,主要基于XXL-JOB定時(shí)任務(wù)掃描失敗數(shù)據(jù)并進(jìn)行重試。

其實(shí)架構(gòu)選型,沒有銀彈,也難有通用解決方案,大家還是需要結(jié)合自己的業(yè)務(wù)做選型及改造。

參考部分網(wǎng)上資料,如有侵權(quán),聯(lián)系我們。

關(guān)于作者黃培祖,采貨俠開發(fā)工程師

參考資料

[1] https://github.com/alibaba/COLA

[2] https://spring.io/projects/spring-statemachine

[3] https://blog.csdn.net/significantfrank/article/details/104996419

責(zé)任編輯:武曉燕 來源: 轉(zhuǎn)轉(zhuǎn)技術(shù)
相關(guān)推薦

2023-07-17 18:39:27

業(yè)務(wù)系統(tǒng)架構(gòu)

2022-04-07 17:30:31

Flutter攜程火車票渲染

2021-01-12 11:02:56

云計(jì)算云存儲(chǔ)技術(shù)云開發(fā)

2021-01-12 11:13:11

云備份云原生云平臺(tái)

2019-02-12 05:34:25

2014-09-11 15:05:40

驅(qū)動(dòng)設(shè)計(jì)驅(qū)動(dòng)開發(fā)

2020-09-27 14:24:58

if-else cod業(yè)務(wù)

2025-07-29 07:27:24

2025-11-05 01:00:00

架構(gòu)業(yè)務(wù)系統(tǒng)MVC

2013-08-15 09:00:49

云解決方案云服務(wù)

2023-06-28 06:33:37

2012-01-11 13:38:15

移動(dòng)BI解決方案

2022-07-04 19:02:06

系統(tǒng)業(yè)務(wù)思考

2022-03-10 16:01:58

NTT思科網(wǎng)絡(luò)

2011-02-15 13:21:17

業(yè)務(wù)連續(xù)性安全威脅

2021-02-25 11:15:38

備份解決方案存儲(chǔ)

2011-01-21 09:53:12

2011-11-30 13:08:55

企業(yè)防毒防毒方案拯救三

2013-07-17 09:09:47

IAMEMCAveksa

2022-05-28 16:08:04

前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲自拍都市欧美小说| 粉嫩一区二区三区| 成人午夜激情在线| 日韩av电影手机在线| 国产调教在线观看| 97视频一区| 色婷婷综合激情| 成人性做爰片免费视频| 亚洲 小说区 图片区 都市| 日韩精品免费视频人成| 欧美成人性生活| 91成人破解版| 99热这里只有精品首页| 欧美在线你懂的| 人妻无码久久一区二区三区免费| a黄色在线观看| 成人精品一区二区三区中文字幕| 国产精品丝袜久久久久久高清| 亚洲av无码一区二区三区在线| 欧美电影完整版在线观看| 欧美人妇做爰xxxⅹ性高电影| 国产精品入口芒果| 成年人网站在线| 国产欧美日韩在线| 国产欧美日韩伦理| av中文字幕在线免费观看| 久久看片网站| 91精品国产高清自在线| 欧美日韩亚洲国产另类| 日韩精品诱惑一区?区三区| 日韩精品视频在线观看网址| 在线成人精品视频| 国产精品一级在线观看| 欧美性受xxxx| 91av俱乐部| 激情黄产视频在线免费观看| 亚洲一区二区不卡免费| 玖玖精品在线视频| 午夜在线小视频| 久久精品在这里| 久久久久久久有限公司| 欧美特级特黄aaaaaa在线看| 精品在线亚洲视频| 国产精品视频在线观看| 久久精品五月天| 免费看黄裸体一级大秀欧美| 91国产视频在线| 日本在线视频中文字幕| 国内自拍视频一区二区三区| 久久久成人精品视频| 欧美成人久久久免费播放| 国产一区二区三区91| 亚洲精品一区二区三区不| 国产成人av无码精品| 97视频一区| 亚洲成人性视频| 亚洲精品激情视频| 精品三级在线观看视频| 亚洲国产精品热久久| 波多野结衣视频播放| 精品福利一区| 精品亚洲国产视频| 男人天堂av电影| 成人91在线| 色婷婷久久av| 国产a免费视频| 国内视频精品| 欧美在线激情网| 综合久久中文字幕| 精品一区二区三区免费| 91手机在线播放| 日本高清视频在线| 久久综合九色综合欧美就去吻| 鲁鲁狠狠狠7777一区二区| 毛片免费在线播放| 国产精品久久影院| 大地资源网在线观看免费官网| 在线观看操人| 福利二区91精品bt7086| 高清一区二区视频| 亚洲老司机网| 精品国产乱码久久久久久久| 超碰97人人干| 999久久久精品国产| 欧美成人免费一级人片100| 欧美日韩中文视频| 久久久天天操| 999国产在线| 户外极限露出调教在线视频| 亚洲欧美自拍偷拍色图| 日本福利视频一区| 日本在线精品| 精品播放一区二区| 国产精品九九九九九| 久久人体视频| 97香蕉超级碰碰久久免费软件| 最近国语视频在线观看免费播放| 精品一区二区免费视频| 国产欧美日韩伦理| 欧美jizz18性欧美| 欧美日韩国产精品一区二区不卡中文 | 久久视频在线| 国内精久久久久久久久久人| 中文字幕在线天堂| 国产成a人亚洲| 水蜜桃亚洲一二三四在线| 密臀av在线| 欧美日韩一区二区三区不卡| 精品人妻伦一二三区久| 欧美岛国激情| 国产不卡视频在线| 三级小视频在线观看| 国产精品少妇自拍| www.com毛片| 亚洲视频国产精品| 中文字幕av日韩| 国产精品久久久久久久久久久久久久久久久 | 中文字幕在线播放视频| 国产高清一区| 国产精品扒开腿爽爽爽视频| 欧美视频xxx| 亚洲黄网站在线观看| 欧美精品性生活| 香蕉视频一区二区三区| 欧美激情视频在线观看| 夜夜躁很很躁日日躁麻豆| www国产精品av| 加勒比成人在线| 一本一道久久a久久| xxx成人少妇69| 亚洲午夜在线播放| 国产欧美日本一区视频| 日本wwww视频| 日本妇女一区| 97激碰免费视频| 免费观看国产精品| 亚洲图片一区二区| 在线观看欧美一区二区| 亚洲精品国产成人影院| 国产精品最新在线观看| 国产小视频在线观看| 色天天综合色天天久久| 美女久久久久久久久久| 免费在线亚洲欧美| 精品欧美日韩在线| 丁香高清在线观看完整电影视频 | 亚洲欧美偷拍另类a∨色屁股| 波多结衣在线观看| 日本a口亚洲| 国产日韩欧美夫妻视频在线观看| 91社区在线观看| 欧美日韩国产综合一区二区| 99re6热在线精品视频| 青娱乐精品视频在线| 视频二区一区| 日韩成人在线一区| 久久综合亚洲社区| wwwav在线播放| 婷婷国产在线综合| 四虎永久免费影院| 视频精品一区二区| 在线观看成人av| 日韩有吗在线观看| 午夜精品久久久久久99热软件| 日本xxxxxwwwww| 色综合一个色综合| 狂野欧美性猛交| 国产一区二区三区不卡在线观看| 警花观音坐莲激情销魂小说| 亚洲乱码一区| 日本精品视频在线观看| √新版天堂资源在线资源| 5858s免费视频成人| 久久国产露脸精品国产| 97精品国产露脸对白| 久久九九国产视频| 香蕉视频官网在线观看日本一区二区| 亚洲www在线观看| 蜜桃在线视频| 最近中文字幕日韩精品 | 中文字幕在线日韩 | 国产精品suv一区二区三区| 久久精品水蜜桃av综合天堂| 爱爱爱爱免费视频| 在线 亚洲欧美在线综合一区| 欧美连裤袜在线视频| 97欧美成人| 欧美激情视频给我| 成年人在线视频| 欧美成人精品福利| 日韩 国产 欧美| 亚洲精品v日韩精品| av中文字幕免费观看| 国产一区中文字幕| 久久国产乱子伦免费精品| 999国产精品999久久久久久| 久久精品美女| 日韩成人18| 国产成人亚洲综合91| 污污视频在线| 中文字幕9999| 视频二区在线观看| 欧美精品 日韩| 蜜臀精品一区二区三区| 亚洲尤物视频在线| 欧美一级特黄高清视频| 92国产精品观看| 亚洲三级在线视频| 日本免费新一区视频| 国产3p露脸普通话对白| 99欧美视频| 日本一区二区精品视频| 国产精品久久久久久久久久白浆 | 粉嫩久久久久久久极品| 国产精品日韩久久久久| 极品av在线| 欧美精品成人在线| 免费在线午夜视频| 亚洲午夜久久久影院| 手机看片福利永久| 日韩午夜中文字幕| 夜夜躁很很躁日日躁麻豆| 色婷婷激情一区二区三区| 国产精品白浆一区二小说| 中文字幕佐山爱一区二区免费| 中文字幕av久久爽一区| 久久麻豆一区二区| avtt香蕉久久| 成人自拍视频在线观看| 永久av免费在线观看| 美女免费视频一区| 国产性生交xxxxx免费| 亚洲一区二区免费看| 男人的天堂狠狠干| 亚洲国产一区二区精品专区| 丰满人妻一区二区三区53号| 91精品婷婷色在线观看| 一区不卡字幕| 婷婷中文字幕一区| dy888午夜| 婷婷丁香综合| 综合久久国产| 91成人观看| 日韩精品第1页| 91精品福利| 四虎4hu永久免费入口| 亚洲色图二区| av动漫在线播放| 欧美激情1区2区| 日本黄大片在线观看| 欧美国内亚洲| www.在线观看av| 在线成人h网| 欧美色图色综合| 性欧美videos另类喷潮| www.xxx亚洲| 美日韩一区二区| 亚洲精品乱码久久久久久动漫| 国产伦理精品不卡| 涩视频在线观看| 99国产精品国产精品毛片| 久久久久久久久免费看无码| 久久久天堂av| 天堂网av2018| 亚洲激情欧美激情| 香蕉免费毛片视频| 在线免费观看日韩欧美| 91激情在线观看| 精品精品国产高清一毛片一天堂| 亚洲AV成人无码一二三区在线| 国产婷婷成人久久av免费高清 | 色天下一区二区三区| 欧美精品一区三区在线观看| 青青草91久久久久久久久| 一级全黄肉体裸体全过程| 雨宫琴音一区二区在线| 嫩草av久久伊人妇女超级a| 精品一区二区影视| 稀缺小u女呦精品呦| 久久久久久电影| 99鲁鲁精品一区二区三区| 亚洲午夜精品在线| 无码人妻精品一区二区蜜桃色欲| 7799精品视频| 无码精品在线观看| 中文一区二区视频| 成人在线高清免费| 国产精品视频播放| 99久久人爽人人添人人澡 | 在线视频一区二区三区| 国产影视一区二区| 亚洲精品www| 免费高清完整在线观看| 97香蕉超级碰碰久久免费软件 | 欧美日韩国产一二| 中文字幕亚洲精品乱码| 动漫av网站免费观看| 激情久久五月天| 精品人妻一区二区三区视频| 亚洲欧美日本在线| 97人妻一区二区精品视频| 日韩欧美成人一区二区| porn视频在线观看| 81精品国产乱码久久久久久| 电影一区中文字幕| 欧美一区二区三区四区夜夜大片| 狠狠88综合久久久久综合网| 国产精品天天av精麻传媒| 成人美女在线观看| 顶臀精品视频www| 在线日韩国产精品| 污视频网站免费观看| 欧美精品在线看| 久久久久伊人| 日本精品一区| 国产精品社区| 人妻激情偷乱频一区二区三区| 1区2区3区欧美| 中文字幕久久久久| 亚洲男人天堂2019| 狼人综合视频| 国产伦精品一区二区三区免费视频| 国产二区精品| 色戒在线免费观看| 国产女人水真多18毛片18精品视频| 日韩乱码人妻无码中文字幕| 精品少妇一区二区三区免费观看 | 高h放荡受浪受bl| 美女性感视频久久久| 精品自拍视频| 亚洲国产精品一区二区第一页| 久久精品一区| 色无极影院亚洲| 欧美午夜激情小视频| 日韩在线一区二区三区四区| 欧美人在线视频| 亚洲视频一起| 97干在线视频| www.欧美精品一二区| 国产精品theporn动漫| 精品国产免费人成电影在线观看四季 | 91视频免费观看| 日韩一区二区视频在线| 亚洲国产精品久久| аⅴ资源天堂资源库在线| 国产精品久久久久免费| 亚洲国产高清一区二区三区| 911亚洲精选| 午夜电影一区二区三区| 视频一区 中文字幕| 欧美在线视频免费观看| 精品欧美久久| 国产精品久久a| 自拍偷拍亚洲欧美日韩| 国产黄a三级三级三级| 欧美精品电影免费在线观看| 欧美偷窥清纯综合图区| 日韩欧美国产免费| 久久九九久久九九| 亚洲视频中文字幕在线观看| 久久天天躁狠狠躁老女人| 欧美日韩黄色| 人妻无码久久一区二区三区免费| 91香蕉国产在线观看软件| 国产又大又粗又爽| 色偷偷噜噜噜亚洲男人的天堂| а天堂中文最新一区二区三区| 国产午夜精品视频一区二区三区| 国产mv日韩mv欧美| 成人毛片在线播放| 中文字幕av一区二区| 亚洲一区二区三区中文字幕在线观看| 精品人妻少妇一区二区| 久久综合九色综合97婷婷女人| 伊人网免费视频| 色综合91久久精品中文字幕| 少妇久久久久| 亚洲免费av一区| 亚洲国产日韩精品| 国产午夜视频在线观看| 成人在线激情视频| 国产一区二区三区成人欧美日韩在线观看| 国产伦理片在线观看| 91精品国产综合久久国产大片| а√在线中文网新版地址在线| 视频一区二区在线| 国产suv精品一区二区883| 国产成人无码av| 九九精品在线视频| 九九视频免费观看视频精品 | 婷婷激情五月综合| 欧美成人合集magnet| 性欧美lx╳lx╳| 亚欧精品在线视频| 色琪琪一区二区三区亚洲区| 黄网页在线观看| 秋霞久久久久久一区二区| 国产麻豆午夜三级精品| 无码人妻熟妇av又粗又大| 欧美高清不卡在线|