當前位置: 妍妍網 > 碼農

公司新來一個架構師, 將消費金融系統重構了

2024-04-21碼農

架構師(JiaGouX)

我們都是架構師!
架構未來,你來不來?

  • 1、背景

  • 1.2 業務重組與合並

  • 1.2 解決技術債務

  • 1.3 影響開發效率

  • 1.4 監控體系不夠完善

  • 2、重構目標

  • 3、設計

  • 3.1 調研

  • 3.2 規劃

  • 3.3 修繕者模式

  • 3.4 領域設計(橫向拆分)

  • 3.5 模組設計(縱向拆分)

  • 3.6 程式碼設計

  • 4、上線過程

  • 5、監控

  • 6、總結


  • 1、背景

    1.2 業務重組與合並

    隨著需求不斷叠代,轉轉消費分期整體出現了一些調整,並提出了新的產品方向,在此背景下,對於經歷了久經滄桑的歷史服務,已經逐漸不適合未來的產品規劃。面對新的業務整合和重組,急需新的架構和思想來承載未來的業務。

    1.2 解決技術債務

    現階段存在的主要問題:

    1. 程式碼模組之間邊界感不強,需要透過模組拆分、服務拆分來區分業務邊界。

    2. 程式碼實作缺少層次感,設計模式單一,一層到底的冗長程式碼。
      此前,微服務拆分原則是按消費分期、合作方分期產品等維度進行整體拆分的,優點是明確了計畫職責,簡單的從需求維度進行服務拆分,確實是一種行之有效的方式,缺點是沒有對基礎功能進行剝離,以至於很多場景需要維護重復的程式碼,增加了計畫的維護成本。

    1.3 影響開發效率

    即使我們接手計畫已經有一段時間,並對計畫足夠了解時,但排查問題起來依然費力費時,而且系統內部程式碼錯綜復雜,呼叫鏈路交錯,難以正常維護,從長遠的開發效率考慮,盡快提出新型方案來代替現有結構。

    1.4 監控體系不夠完善

    線上異常機制不夠敏感,缺少關鍵業務指標的告警看板,作為一個業務開發,應保持對核心指標數據的敏感性。

    2、重構目標

    1. 不影響業務的正常運轉和叠代;

    2. 改善現有程式碼結構設計,讓程式碼易於擴充套件,提升開發效率;

    3. 采用新工程逐步替代原有介面,舊工程逐漸廢棄。

    3、設計

    3.1 調研

    開始重構之前,調研了互聯網消金通用的架構解決方案:

    通用方案

    由於是外部調研的通用架構設計,所以並非完全契合轉轉消費分期產品,但可以借鑒其分層架構設計的思想,在程式碼設計階段,可以先對核心模組進行拆解和規劃。

    3.2 規劃

    前端頁面與後端重構計劃分兩次叠代進行,分階段進行,可以有效分攤並降低計畫上線風險,第一次叠代圍繞後端主要模組進行剝離重新設計並上線;第二次重構目的是解決產品需求,對接前端新頁面。

    3.3 修繕者模式

    作為一個一線的業務開發,需要開展重構工作的同時還得保證產品需求的正常叠代,修繕者模式無疑是最佳選擇。 第一次叠代歷程,對於歷史工程邊緣邏輯保留並隔離,只對核心程式碼進行重構後轉移到到新工程,新工程逐步接手老舊邏輯,並對老工程提供RPC介面,逐漸取代。此方案整體風險最低,同時能兼顧到正常的需求叠代。
    第二次叠代歷程,經歷了第一次叠代後,新系統執行穩定,同時也具備接手新產品的能力,新工程開始與前端對接、聯調,在此之後,V2版本也正式上線。

    3.4 領域設計(橫向拆分)

    模組拆分
    1. 聚合業務:涵蓋了消費分期主要業務,根據其各自產品需求特點,作為上層業務程式碼,對前端、收銀台提供聚合介面。

    2. 基礎服務:使用者信貸所產生的數據、或依托合作方數據,圍繞金融分期服務提供的數據支持。

    3. 三方對接:基於轉轉標準API下的邏輯實作,同時具備靈活接入合作方介面的能力。

    3.5 模組設計(縱向拆分)

    基於以往計畫存在的問題,再結合消費分期的特點,我們對分期購買到賬單還款結清的整個流程進行拆解:使用者主動填寫申請資訊,送出授信申請並獲額,挑選商品分期下單,生成還款計劃,提供綁卡、賬單還款等功能。以上就是一個簡單的分期購物流程,基於以上流程,我們把消費分期所包含的公共模組,如授信前獲額、用信、賬單還款,這些富有金融服務內容的功能進行剝離。消費分期作為轉轉的產品原型,在聚合層中各自維護,互不影響。
    設計原則:在不改變原有程式碼邏輯的情況下,根據單一職責和依賴倒置原則的思想:對系統進行模組拆分與合並,以明確計畫職責降低耦合度;對包進行重新規劃,劃分包與包之間的邊界,進一步減少程式碼間的耦合。

    3.6 程式碼設計

    好的程式碼重構一定離不開設計模式,基於原有單一的策略模式,我們把合作方對接模組與基礎服務模組進行了拆解,采用雙層樣版、策略、工廠模式的組合,分別對授信、用信、貸後幾個模組單獨設計介面,維護好對合作方通用標準API介面,同時具備靈活接入的特點,舉個例子,以下為授信模組主要程式碼類圖:

    第一層作為基礎服務的策略模式;
    第二層作為合作方對接的策略模式。
    主要類圖設計:

    在定義介面與實作類後,形成了對合作方對接層依賴,同時對訂單、用信、授信等核心數據進行落地,對消費分期提供數據支撐,舉個例子,以下為授信模組主要程式碼:

    1. 基礎服務介面定義

    /**
     * 授信介面定義
     **/

    publicinterfaceICreditService{
    /**
    * appId,資方定義的一個唯一ID
    */

    String getAppId();
    /**
    * app名稱
    *
    @return zz or zlj
    */

    String getAppName();
    /**
    * 獲取授信結果
    *
    @return result
    */

    CreditResult creditResult(String logStr, Long uid);
    }

    1. 標準流程抽象

    /**
     * 標準API對接實作
     *
     **/

    publicabstract classAbstractCreditServiceimplementsICreditService{
    /**
    * 標準API對接
    *
    @return IBaseApiService
    */

    protectedabstract IBaseApiService getApiThirdService();
    @Override
    public AppConfig getPartner(){
    return commonConfigUtil.getAppConfig(getAppId());
    }
    @Override
    public CreditResult creditResult(String logStr, Long uid){
    CreditResultInput input = new CreditResultInput();
    input.setUid(uid);
    ResponseProtocol<CreditResultOutput> output = getApiThirdService().creditResult(logStr, input);
    String creditStatus = TransformUtil.approvalStatusTransform(output.getData());
    return CreditResult.builder().result(creditStatus).build();
    }
    }
    /**
     * 合作變異數異化接入
     */

    @Service
    @Slf4j
    public classZZABCCreditServiceImplextendsAbstractABCCreditService{
    @Resource
    ZZABCThirdServiceImpl abcThirdService;
    @Override
    public String getAppId(){
    return PartnerEnum.ABC_ZZ_API.getAppId();
    }
    @Override
    public String getAppName(){
    return AppNameEnum.ZZ.getValue();
    }
    @Override
    protected IABCThirdService getABCThirdService(){
    return abcThirdService;
    }
    }




    1. 標準API對接

    /**
     * 標準API對接
     *
     * @author Rouse
     * @date 2022/4/24 13:57
     */

    publicinterfaceIBaseApiService{
    /**
    * 標準API,獲取appId
    *
    @return appId
    */

    String getAppId();
    /**
    * 獲取授信結果
    */

    ResponseProtocol<CreditResultOutput> creditResult(CreditResultInput input);
    }

    1. 內部標準API實作

    /**
     * 合作方,標準API對接實作
     *
     * @author Rouse
     * @date 2022/4/24 14:04
     */

    @Slf4j
    publicabstract classAbstractBaseApiServiceimplementsIBaseApiService{
    @Override
    public ResponseProtocol<CreditResultOutput> creditResult(CreditResultInput input){
    // 通用加解密
    return getDataResponse(logStr, getAppConf().getUrl4CreditResult(), input, CreditResultOutput. class);
    }
    }

    1. 差異化合作方接入


    /**
     * ABC合作方介面封裝
     **/

    publicinterfaceIABCThirdServiceextendsIBaseApiService{
    /**
    * 標準API,獲取appId
    *
    @return appId
    */

    String getAppId();
    /**
    * 獲取授信結果
    */

    ResponseProtocol<ABCCreditResultOutput> creditResult(ABCCreditResultInput input);
    }
    /**
     * 合作方抽象方法封裝
     **/

    @Slf4j
    publicabstract classAbstractABCThirdServiceextendsAbstractBaseApiServiceimplementsIABCThirdService{
    @Override
    public ResponseProtocol<ABCCreditResultOutput> creditResult(ABCCreditResultInput input){
    // 加解密差異化實作
    return getDataResponse(logStr, getAppConf().getUrl4CreditResult(), input, ABCCreditResultOutput. class);
    }
    }

    /**
     * ABC合作方對接
     *
     */

    @Service
    @Slf4j
    public classZZABCThirdServiceImplextendsAbstractABCThirdService{
    @Override
    public String getAppId(){
    return PartnerEnum.ABC_API_ZZ.getAppId();
    }
    @Override
    public String getAppName(){
    return AppNameEnum.ZZ.getValue();
    }
    }


    4、上線過程

    對於老系統的重構,新系統上線過度期也至關重要,因為采用了新的表結構進行重新設計,涉及到數據的同步,我們采用單向數據同步,逐漸棄用老系統數據,如果灰度期間需要回滾,首先對數據進行回滾,優先保證線上服務穩定。
    以下是經歷兩次重構叠代的過程:

    5、監控


    1. 計畫重構監控先行,這次我們采用了轉轉告警機制和Prometheus線上監控,另外搭建了一套線上看板,及時發現各個模組的潛在隱患。

    2. 日誌,一個完美的系統離不開合理的日誌,日誌往往是定位問題最便捷的工具。

    6、總結

    透過此次技術重構,我們不僅解決了過去存在的技術債務問題,還提升了服務的穩定性和使用者體驗,也提升產品交付效率。

    技術重構並非一蹴而就,但只要我們有堅定的信念和不懈的努力,終將取得成功。參照一句名言:」不要因為懶惰而拒絕重構,不要因為無暇重構而成為你拖延的理由 。」 是的,重構是持續最佳化程式碼品質和可維護性的過程,需要我們時刻關註並付諸行動。

    我認為,重構的另一種價值:一個重構好的系統、往往具備通用性,可移植性。簡單說就是我們重構後的系統以最小的改動且能在同行中快速復用,因為你創造了一個穩定可靠的「輪子」,如果做到這點,無非你是這個行業技術解決方案的專家。

    如喜歡本文,請點選右上角,把文章分享到朋友圈
    如有想了解學習的技術點,請留言給若飛安排分享

    因公眾號更改推播規則,請點「在看」並加「星標」 第一時間獲取精彩技術分享

    ·END·

    相關閱讀:

    作者:羅思,金融技術部後端研發工程師。轉轉消費分期業務開發。

    來源:轉轉技術

    版權申明:內容來源網路,僅供學習研究,版權歸原創者所有。如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝!

    架構師

    我們都是架構師!

    關註 架構師(JiaGouX),添加「星標」

    獲取每天技術幹貨,一起成為牛逼架構師

    技術群請 加若飛: 1321113940 進架構師群

    投稿、合作、版權等信箱: [email protected]