国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区

當前位置:首頁 > 科技  > 軟件

轉轉游戲的賬號訂單流程重構之路

來源: 責編: 時間:2023-08-20 23:16:42 630觀看
導讀1、背景隨著需求的不斷迭代,項目代碼的復雜度也會越來越高,“屎山”也一天一天慢慢的堆積起來,對于游戲業務的賬號訂單流程也是如此。游戲訂單類型由原來的倆種增加到了現在的七種,早就已經到了需要重構的地步。但是由于

圖片9n428資訊網——每日最新資訊28at.com

既然有七種訂單類型,這好辦啊。可以采用策略+模板模式啊,一個抽象模板+七個子類就可以啦。但是后來仔細一想,如果將所有的處理邏輯都放在父類和子類當中,其實代碼整體也顯得十分臃腫。9n428資訊網——每日最新資訊28at.com

為了想出更好的解決方案,于是對原有代碼和業務流程進行了深入的梳理和總結,主要有以下幾點:9n428資訊網——每日最新資訊28at.com

  1. 所有訂單流程都是在客服發貨和自主發貨基礎上衍生出來的。
  2. 所有訂單流程都包含下單、支付、上傳賬密、發貨、確認收貨等節點。
  3. 在這些節點里不同訂單類型大多會有各自一些特定操作,但是這些操作其實并不屬于訂單的主流程。

通過以上分析,是不是可以將下單到確認收貨作為一層,將不同訂單類型的特定處理實現作為一層呢?這樣不就將訂單流程中各種特殊處理從訂單主流程剝離開了嗎,因此最終決定采用三層接口+策略模板的設計方案。9n428資訊網——每日最新資訊28at.com

2.2 三層接口+策略模板模式

接口設計如下:9n428資訊網——每日最新資訊28at.com

圖片9n428資訊網——每日最新資訊28at.com

  • 第一層接口

包含前端用戶進行交互、處理mq消息以及給其它服務調用的接口。9n428資訊網——每日最新資訊28at.com

  • 第二層接口

訂單核心主流程能力接口。將下單、支付到確認收貨等“不變”的基礎能力提供給頂層接口調用,這層接口有自主發貨流程和客服發貨流程兩個實現類。9n428資訊網——每日最新資訊28at.com

public interface IGameAccountOrderDealProcess {    /**     * 處理下單未支付訂單     */    int handlePlaceOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 處理支付成功訂單     */    int handlePaySuccessOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 處理已發貨訂單     */    int handleDeliverOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 處理支付前取消訂單     */    int handleCancelBeforePayOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 處理支付后取消訂單     */    int handleCancelAfterPayOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 處理交易成功訂單     */    int handleConfirmReceiptOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 賬號交易窗數據     */    <T extends TradeFlowData> T getOrderTradeData(String logStr, Long orderId, Integer device, Long uid);    /**     * 上傳賬密     */    ZZOpenScfBaseResult<String> uploadAccountAndPwd(GameAccountSelfTrade.AccountPwdArg arg, long uid, String logStr, ServiceHeaderEntity header) throws Exception;    /**     * 發貨     * @param orderContext     */    boolean deliverOrder(GameAccountOrderContext orderContext) throws Exception;    /**     * 訂單確認收貨     */    ZZOpenScfBaseResult<String> confirmReceiptOrder(GameAccountOrderContext orderContext, Long uid, boolean needCheckRisk) throws Exception;}
  • 第三層接口

各種訂單類型的特殊處理,每一種訂單模式都對應一個實現類。9n428資訊網——每日最新資訊28at.com

public interface ITradeSelfHandler {    GameAccountTradeFlow.GameAccountTradeType getOrderTrade();    /*------------處理mq消息相關---------------*/    /**     *1.插入表之前設置客服和extendInfo     */    void fillExtraOrderInfoBeforeInsert(GameAccountOrderResultEntity orderEntity, GameAccountOrderContext orderContext);    /**     * 下單后處理     */    void handleAfterPlaceOrder(GameAccountOrderContext orderContext);    /**     * 支付前取消處理     */    void handleCancelBeforePay(GameAccountOrderContext orderContext);    /**     * 支付后取消處理     */    int handleCancelAfterPay(GameAccountOrderContext orderContext) throws Exception;    /**     * 支付后一些額外處理     */    int handleAfterPaySuccess(GameAccountOrderContext orderContext);    /**     * 確認收貨處理     */    int handleAfterConfirmReceipt(GameAccountOrderContext orderContext) throws Exception;    /*---------------------------------*/    /**     * 獲取提現時間     */    Date getWithDrawlTime();    /**     * 發送支付成功push     */    void orderAlreadyPayPushMsgNew(GameAccountOrderContext orderContext, Pair<String, String> jumpUrl);    /**     * 獲取分帳賬戶、類別信息     */    List<AccountOrderSplitModel> getOrderSplitModelList(GameAccountOrderContext orderContext, OrderMaxSettleInfo settleInfo);    /**     * 定制各自spiUi     */    void buildOrderSpiUiData(GameAccountOrderContext orderContext, GameOrderSpiConfig bConfig, GameOrderSpiConfig sConfig, SpiUiData spiUiData) throws Exception;    /**     * 確認收貨后一些處理     */    void otherOperationAfterReceipt(GameAccountOrderContext orderContext, Long uid);}

2.3 具體實現

  • 核心代碼收攏到一個服務,相關接口進行聚合

原先在客服后臺、定時任務、mq集群都有一些訂單的操作,但是這些代碼基本都是重復的,所以此次重構在訂單核心服務中新增相應的訂單操作功能,統一由其它服務進行RPC調用。9n428資訊網——每日最新資訊28at.com

圖片9n428資訊網——每日最新資訊28at.com

將訂單相關的接口、工具類集中到同一個包下,方便定位。9n428資訊網——每日最新資訊28at.com

圖片9n428資訊網——每日最新資訊28at.com

  • 整體類圖及設計原則圖片
  1. 命名規范:類名、變量名、方法名盡量見名知義。
  2. 單一職責:各個模塊各司其職,避免與其它模塊過度耦合。
  3. 準備訂單上下文,清除RPC重復調用問題。
//上下文實體public class GameAccountOrderContext {    private String logStr;    private Long orderId;    private Integer mqStatus;    private Order order;    private GameAccountOrderResultEntity accountOrderEntity;    private AccountOrderStatusEnum orderStatus;    private Boolean hasInsuranceService;//訂單是否有保險    private GameAccountTradeFlow.GameAccountTradeType tradeType;    private GameAccountProductData accountProductData;    private ZZProduct product;    private ZZProductExt productExt;    private Map<String, String> extValueMap;    private AccountHelpSaleClue helpSaleClue;//幫賣線索    private DistributionShareInfoDTO distributionShareInfo;//分銷信息    private ITradeSelfHandler tradeSelfHandler;    private Integer serviceUiStatus;//對應訂單spi狀態}//上下文準備GameAccountOrderContext orderContext = orderContextBuilder.buildAccountOrderContext(order, zzProduct, logStr);

3、上線保障

訂單流程不管對于什么業務,基本都是最重要的一個環節,為了避免產生重大問題,需要做到以下兩點:9n428資訊網——每日最新資訊28at.com

  1. 嚴格保證線下測試的準確性。
  2. 出現線上問題,影響范圍要盡可能小。

3.1 流程測試

根據賬號訂單流程的特點,在測試的時候遵循以下原則:9n428資訊網——每日最新資訊28at.com

  • 訂單流程正常跑通
  • 訂單分帳正確
  • 訂單保險正常
  • 各個節點與原來保持一致
  • 相關push、私信正常發送
  • 統計日志正常打印

對于每一種訂單流程,同時進行新、老流程訂單的測試。逐一對比新、老流程的買家側和賣家側各個流程節點的頁面、按鈕、跳轉、push、私信等是否保持一致。9n428資訊網——每日最新資訊28at.com

3.2 灰度策略

為了避免產生重大問題,上線后必須采取灰度策略,不然出了問題就可能就是事故了。本次采用的灰度策略是上線后按訂單類型、訂單量進行灰度,同時將灰度訂單落表記錄,配置如下:9n428資訊網——每日最新資訊28at.com

[  {    "orderType": 6,//訂單類型    "dayNum": 50,//每日灰度量    "isTotalGray": true//是否全量  }] /**  * 判斷訂單是否走新交易流程  */public boolean isNewOrderProcess(String logStr, GameAccountOrderContext orderContext) {        Long orderId = orderContext.getOrderId();        try {            if (gameGrayTestService.isNewTradeProcessOrder(orderId)){                return true;            }            GameAccountOrderResultEntity orderEntity = accountOrderManage.getGameAccountOrderEntity(orderId, logStr);            GameAccountTradeFlow.GameAccountTradeType orderTradeType = orderContext.getTradeType();            String orderRedisSet = String.format("account_order_gray_set_%s_%s", Objects.nonNull(orderEntity) ? orderEntity.getSelfType() : orderTradeType.getSelfType(), DateUtil.format(new Date(), "yyyy-MM-dd"));            if (ZZGameRedisUtil.sismember(orderRedisSet, orderId.toString())){                return true;            }            if (newAccountOrderTradeSwitch){                return true;            }            Optional<OrderGrayConfig> grayConfigOptional = grayConfigList.stream().filter(c->c.getOrderType() == orderTradeType.getSelfType()).findFirst();            if (grayConfigOptional.isPresent()){                OrderGrayConfig grayConfig = grayConfigOptional.get();                if (Objects.nonNull(grayConfig.getIsTotalGray()) && grayConfig.getIsTotalGray()){                    return true;                }                if (orderContext.getOrderStatus() != AccountOrderStatusEnum.place_order){//只處理新訂單                    return false;                }                String dayNumKey = String.format(NEW_ORDER_PROCESS_GRAY_NUM, DateUtil.format(new Date(), "yyyy-MM-dd"), orderTradeType.getSelfType());                if (NumberUtils.toInt(ZZGameRedisUtil.get(dayNumKey)) < grayConfig.getDayNum()){                    int result = gameGrayTestService.insertNewTradeProcessOrder(orderId);                    log.info("{} desc=insert_gray_order_data orderId={} result={}", logStr, orderId, result);                    if (result > 0){                        ZZGameRedisUtil.increAndGet(dayNumKey, 1);                        ZZGameRedisUtil.expire(dayNumKey, 3600*24);                        ZZGameRedisUtil.sadd(orderRedisSet, orderId.toString());                        ZZGameRedisUtil.expire(orderRedisSet, 3600*24);                    }                    return result >= 0;                }                return false;            }        } catch (Exception e) {            log.error("{} desc=isNewOrderProcess_error orderId={}", orderContext.getLogStr(), orderContext.getOrderId(), e);        }        return false;}

3.3 異常機制

在一些重要的節點設置告警機制,比如上傳賬密、發貨、提現等節點出現異常時會發送企業微信告警通知,可以第一時間關閉灰度,查找問題。9n428資訊網——每日最新資訊28at.com

圖片9n428資訊網——每日最新資訊28at.com

不過對于分帳正確性保障這塊只是通過測試確保正確,這種最好是可以接入中臺的BCP(Business Check Platform)系統。它是一種標準化數據校對平臺,支持標準化數據源接入,基于事件觸發規則執行,進行業務數據校對,可以及時快速的發現業務異常數據并實時告警。9n428資訊網——每日最新資訊28at.com

4 總結

在對訂單流程進行重構之后,新增或修改某種訂單模式,只需增改相應的訂單類型處理類就可以了,也不用擔心本次修改會影響到其它的訂單模式,大大提高了開發效率。此外,重構代碼可以幫助我們進一步深入了解整個業務流程,發現代碼的壞味道,提升代碼結構設計能力。9n428資訊網——每日最新資訊28at.com

本文鏈接:http://m.rrqrq.com/showinfo-26-6161-0.html轉轉游戲的賬號訂單流程重構之路

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 谷歌的Project IDX會扼殺其他應用程序開發框架嗎?

下一篇: 基于模塊聯邦與大倉模式的商家巨石應用拆分實踐

標簽:
  • 熱門焦點
Top 国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区
欧美一区二区精美| 91精品国产综合久久久久久久| 亚洲精品免费电影| 欧美美女激情18p| 好吊色欧美一区二区三区四区| 亚洲精品久久久久久国产精华液| 一区二区国产日产| 国产一区二区h| 久久久噜噜噜久久中文字幕色伊伊| 91久久久久| 国产美女主播视频一区| 欧美久久久影院| a美女胸又www黄视频久久| 亚洲国产一区二区三区| 欧美日韩国产大片| 亚洲精品系列| 成人激情开心网| 亚洲一区中文日韩| 日韩三级在线观看| 亚洲午夜一级| fc2成人免费人成在线观看播放| 午夜精品福利一区二区蜜股av| 欧美精品1区2区| 久久亚洲影院| 国产精品免费一区二区三区在线观看 | 一区二区视频欧美| 国产精品一区二区男女羞羞无遮挡 | 99久久99久久综合| 欧美大片日本大片免费观看| www.日本不卡| |精品福利一区二区三区| 国语精品中文字幕| 亚洲免费视频成人| 六月天综合网| 国产尤物一区二区| 国产日韩欧美不卡在线| 久久久久国产精品午夜一区| 国产一区二区三区四区五区入口| 欧美一区二区精品在线| 国内一区二区三区在线视频| 天天av天天翘天天综合网色鬼国产| 欧美精品在线一区二区| 欧美精品国产一区二区| 亚洲成人av中文| 2024国产精品| 亚洲永久免费精品| 91色综合久久久久婷婷| 亚洲成人资源在线| 精品国产一区二区亚洲人成毛片 | 91精品久久久久久久久99蜜臂| 欧美一区综合| 天涯成人国产亚洲精品一区av| 久久精品一区二区三区不卡牛牛| 国产日韩欧美一区二区| 国产成人a级片| 日欧美一区二区| 久久久蜜桃精品| 久久综合九九| 欧美另类视频| 国产一区二区三区黄视频| 亚洲综合色婷婷| 亚洲精品一区二区三区99| 色狠狠桃花综合| 国产一区日韩欧美| 国产一区二区网址| 五月婷婷激情综合| 欧美国产精品中文字幕| 91精品国产全国免费观看| 夜夜爽av福利精品导航| 成人午夜在线视频| 国产综合色视频| 伊人性伊人情综合网| 精品久久久久久久一区二区蜜臀| 久久精品一二三区| 黑人一区二区三区四区五区| 国产麻豆视频精品| 午夜国产精品影院在线观看| 国产精品美女久久久久aⅴ国产馆| 欧美人妇做爰xxxⅹ性高电影| 久久中文字幕一区二区三区| 国产一区亚洲| 国产一区美女在线| 精品一区中文字幕| 性欧美疯狂xxxxbbbb| 一区二区三区产品免费精品久久75| 精品国产精品网麻豆系列| 在线电影一区二区三区| 久久精品中文字幕一区二区三区| 91免费观看视频| 国产成a人无v码亚洲福利| 午夜精彩视频在线观看不卡| 亚洲制服丝袜av| 亚洲欧美在线高清| 国产精品免费网站在线观看| 精品理论电影在线| 欧美精品一区男女天堂| 欧美精品在线一区二区| 国产精品亚洲综合久久| 伊人影院久久| 欧美日韩精品久久| 一区在线视频观看| 欧美久久99| 影音先锋亚洲电影| 欧美视频在线观看| 亚洲国产精品www| 欧美色123| 国产精品乡下勾搭老头1| 国产精品一卡二| 国产精品一线二线三线精华| 国产成人在线免费观看| 久久97超碰色| 亚洲成人精品一区| 亚洲图片自拍偷拍| 国产亚洲精品超碰| 国产精品国产三级国产普通话99 | 国产精品毛片a∨一区二区三区| 国产精品全国免费观看高清| 久久久久国产精品免费免费搜索| 日韩欧美专区在线| 日韩一区二区高清| 日韩欧美专区在线| 国产午夜久久久久| 亚洲国产经典视频| 一区二区在线观看免费| 亚洲精品乱码久久久久久日本蜜臀| 一二三区精品福利视频| 樱花草国产18久久久久| 夜夜嗨av一区二区三区四季av| 视频一区中文字幕国产| 午夜av一区二区| 国产激情一区二区三区| 国产成人在线视频播放| 国产激情一区二区三区| 成人av免费在线播放| 欧美福利视频| 亚洲欧美高清| 色爱区综合激月婷婷| 欧美成人三级在线| 国产亚洲精品bt天堂精选| 有坂深雪av一区二区精品| 亚洲成人福利片| 久久国产福利国产秒拍| 91蜜桃网址入口| 亚洲片区在线| 在线播放国产精品二区一二区四区 | 91传媒视频在线播放| 在线精品视频小说1| 亚洲精品在线电影| 国产精品国产三级国产普通话蜜臀| 亚洲超碰97人人做人人爱| 美国欧美日韩国产在线播放| av中文字幕在线不卡| 欧美性事免费在线观看| 国内精品久久久久久久果冻传媒| 久久精品在线| 欧美一区二区三区四区久久| 亚洲免费在线视频| 免费观看日韩电影| 国产精品二区二区三区| 免费一级欧美片在线播放| 欧美成人性福生活免费看| 国产精品国模大尺度视频| 亚洲色图清纯唯美| 国产成人综合在线| 在线欧美视频| 日韩一区二区三免费高清| 国产精品久久国产精麻豆99网站| 麻豆91在线观看| 91原创在线视频| 老司机精品导航| 久久噜噜亚洲综合| 亚洲三级免费观看| 成人免费三级在线| 亚洲一区二区三区欧美 | 欧美一区二区三区免费视频| 国产精品久久久久永久免费观看| 精品亚洲欧美一区| 激情综合激情| 精品日韩在线一区| 亚洲最快最全在线视频| 波波电影院一区二区三区| 国产精品毛片在线| 亚洲一区二区三区高清| 日本一区二区三级电影在线观看 | 国产精品影视在线| 久久精品日产第一区二区三区| 2020国产精品自拍| 亚洲一区二区三区免费视频| 色综合色综合色综合| 久久精品男女| 亚洲欧美日韩久久精品| 国产成人在线看| 欧美午夜视频网站| 中文字幕在线一区二区三区| 成人激情视频网站| 日本韩国一区二区三区| 国产日产欧美一区二区三区| 久久99精品久久久久婷婷| 91浏览器打开| 精品剧情在线观看|