色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一種接口依賴關(guān)系分層方案

OSC開源社區(qū) ? 來源:OSCHINA 社區(qū) ? 2023-06-30 10:25 ? 次閱讀

1、背景

到店商詳?shù)^程中,需要提供的對(duì)外能力越來越多,如預(yù)約日歷、附近門店、為你推薦等。這其中不可避免會(huì)出現(xiàn)多個(gè)上層能力依賴同一個(gè)底層接口的場(chǎng)景。最初采用的方案是對(duì)外 API 入口進(jìn)來后獲取對(duì)應(yīng)的能力,并發(fā)調(diào)用多項(xiàng)能力,由能力層調(diào)用對(duì)應(yīng)的數(shù)據(jù)鏈路,進(jìn)行業(yè)務(wù)處理。

然而,隨著接入功能的增多,這種情況導(dǎo)致了底層數(shù)據(jù)服務(wù)的重復(fù)調(diào)用,如商品配置信息,在一次 API 調(diào)用過程中重復(fù)調(diào)了 3 次,當(dāng)流量增大或能力項(xiàng)愈多時(shí),對(duì)底層服務(wù)的壓力會(huì)成倍增加。

正值 618 大促,各方接口的調(diào)用都會(huì)大幅度增加。通過梳理接口依賴關(guān)系來減少重復(fù)調(diào)用,對(duì)本系統(tǒng)而言,降低了調(diào)用數(shù)據(jù)接口時(shí)的線程占用次數(shù),可以有效降級(jí) CPU。對(duì)調(diào)用方來說,減少了調(diào)用次數(shù),可減少調(diào)用方的資源消耗,保障底層服務(wù)的穩(wěn)定性。

原始調(diào)用方式:

e6fe81fe-1666-11ee-962d-dac502259ad0.jpg

2、優(yōu)化

基于上述問題,采用底層接口依賴分層調(diào)用的方案。梳理接口依賴關(guān)系,逐層向上調(diào)用,注入數(shù)據(jù),如此將同一接口的調(diào)用抽取到某層,僅調(diào)用一次,即可在整條鏈路使用。

改進(jìn)調(diào)用方式:

e717736c-1666-11ee-962d-dac502259ad0.jpg

只要分層后即可在每層采用多線程并發(fā)的方式調(diào)用,因?yàn)橥粚蛹?jí)中的接口無先后依賴關(guān)系。

3、如何分層?

接下來,如何梳理接口層級(jí)關(guān)系就至關(guān)重要。

接口梳理分層流程如下:

e751f6b8-1666-11ee-962d-dac502259ad0.jpg

第一步:構(gòu)建層級(jí)結(jié)構(gòu) 首先獲取到能力層依賴項(xiàng)并遍歷,然后調(diào)用生成數(shù)據(jù)節(jié)點(diǎn)方法。方法流程如下:構(gòu)建當(dāng)前節(jié)點(diǎn),檢測(cè)循環(huán)依賴(存在循環(huán)依賴會(huì)導(dǎo)致棧溢出),獲取并遍歷節(jié)點(diǎn)依賴項(xiàng),遞歸生成子節(jié)點(diǎn),存放子節(jié)點(diǎn)。

第二步:節(jié)點(diǎn)平鋪 定義 Map 維護(hù)平鋪結(jié)構(gòu),調(diào)用平鋪方法。方法流程如下:遍歷層級(jí)結(jié)構(gòu),判斷當(dāng)前節(jié)點(diǎn)是否已存在 map 中,存在時(shí)與原節(jié)點(diǎn)比較將層級(jí)大的節(jié)點(diǎn)放入(去除重復(fù)項(xiàng)),不存在時(shí)直接放入即可。然后處理子節(jié)點(diǎn),遞歸調(diào)用平鋪方法,處理所有節(jié)點(diǎn)。

第三步:分層(分組排序) 流處理平鋪結(jié)構(gòu),處理層級(jí)分組,存儲(chǔ)在 TreeMap 中維護(hù)自然排序。對(duì)應(yīng) key 中的數(shù)據(jù)節(jié)點(diǎn) Set 需用多線程并發(fā)調(diào)用,以保證鏈路調(diào)用時(shí)間

1 首先,定義數(shù)據(jù)結(jié)構(gòu)用于維護(hù)調(diào)用鏈路

Q1:為什么需要定義祖先節(jié)點(diǎn)?

A1:為了判斷接口是否存在循環(huán)依賴。如果接口存在循環(huán)依賴而不檢測(cè)將導(dǎo)致調(diào)用棧溢出,故而在調(diào)用過程中要避免并檢測(cè)循環(huán)依賴。在遍歷子節(jié)點(diǎn)過程中,如果發(fā)現(xiàn)當(dāng)前節(jié)點(diǎn)的祖先已經(jīng)包含當(dāng)前子節(jié)點(diǎn),說明依賴關(guān)系出現(xiàn)了環(huán)路,即循環(huán)依賴,此時(shí)拋異常終止后續(xù)流程避免棧溢出。

public class DataNode {
    /**
     * 節(jié)點(diǎn)名稱
     */
    private String name;
    /**
     * 節(jié)點(diǎn)層級(jí)
     */
    private int level;
    /**
     * 祖先節(jié)點(diǎn)
     */
    private List ancestors;
    /**
     * 子節(jié)點(diǎn)
     */
    private List children;
}

2 獲取能力層的接口依賴,并生成對(duì)應(yīng)的數(shù)據(jù)節(jié)點(diǎn)

Q1:生成節(jié)點(diǎn)時(shí)如何維護(hù)層級(jí)?

A1:從能力層依賴開始,層級(jí)從 1 遞加。每獲取一次底層依賴,底層依賴所生成的節(jié)點(diǎn)層級(jí)即父節(jié)點(diǎn)層級(jí) + 1。

/**
 * 構(gòu)建層級(jí)結(jié)構(gòu)
 *
 * @param handlers 接口依賴
 * @return 數(shù)據(jù)節(jié)點(diǎn)集
 */
private List buildLevel(Set handlers) {
    List result = Lists.newArrayList();

    for (String next : handlers) {
        DataNode dataNode = generateNode(next, 1, null, null);
        result.add(dataNode);
    }
    return result;
}

/**
 * 生成數(shù)據(jù)節(jié)點(diǎn)
 *
 * @param name 節(jié)點(diǎn)名稱
 * @param level 節(jié)點(diǎn)層級(jí)
 * @param ancestors 祖先節(jié)點(diǎn)(除父輩)
 * @param parent 父節(jié)點(diǎn)
 * @return DataNode 數(shù)據(jù)節(jié)點(diǎn)
 */
private DataNode generateNode(String name, int level, List ancestors, String parent) {
    AbstractInfraHandler abstractInfraHandler = abstractInfraHandlerMap.get(name);
    Set infraDependencyHandlerNames = abstractInfraHandler.getInfraDependencyHandlerNames();
    // 根節(jié)點(diǎn)
    DataNode dataNode = new DataNode(name);
    dataNode.setLevel(level);
    dataNode.putAncestor(ancestors, parent);
    if (CollectionUtils.isNotEmpty(dataNode.getAncestors()) && dataNode.getAncestors().contains(name)) {
        throw new IllegalStateException("依賴關(guān)系中存在循環(huán)依賴,請(qǐng)檢查以下handler:" + JsonUtil.toJsonString(dataNode.getAncestors()));
    }
    if (CollectionUtils.isNotEmpty(infraDependencyHandlerNames)) {
        // 存在子節(jié)點(diǎn),子節(jié)點(diǎn)層級(jí)+1
        for (String next : infraDependencyHandlerNames) {
            DataNode child = generateNode(next, level + 1, dataNode.getAncestors(), name);
            dataNode.putChild(child);
        }
    }
    return dataNode;
}

層級(jí)結(jié)構(gòu)如下:

e768abec-1666-11ee-962d-dac502259ad0.png

3 數(shù)據(jù)節(jié)點(diǎn)平鋪(遍歷出所有后代節(jié)點(diǎn))

Q1:如何處理接口依賴過程中的重復(fù)項(xiàng)?

A1:遍歷所有的子節(jié)點(diǎn),將所有子節(jié)點(diǎn)平鋪到一層,平鋪時(shí)如果節(jié)點(diǎn)已經(jīng)存在,比較層級(jí),保留層級(jí)大的即可(層級(jí)大說明依賴位于更底層,調(diào)用時(shí)要優(yōu)先調(diào)用)。

/**
 * 層級(jí)結(jié)構(gòu)平鋪
 *
 * @param dataNodes 數(shù)據(jù)節(jié)點(diǎn)
 * @param dataNodeMap 平鋪結(jié)構(gòu)
 */
private void flatteningNodes(List dataNodes, Map dataNodeMap) {
    if (CollectionUtils.isNotEmpty(dataNodes)) {
        for (DataNode dataNode : dataNodes) {
            DataNode dataNode1 = dataNodeMap.get(dataNode.getName());
            if (Objects.nonNull(dataNode1)) {
                // 存入層級(jí)大的即可,避免重復(fù)
                if (dataNode1.getLevel() < dataNode.getLevel()) {
                    dataNodeMap.put(dataNode.getName(), dataNode);
                }
            } else {
                dataNodeMap.put(dataNode.getName(), dataNode);
            }
            // 處理子節(jié)點(diǎn)
            flatteningNodes(dataNode.getChildren(), dataNodeMap);
        }
    }
}

平鋪結(jié)構(gòu)如下:

e7b9af24-1666-11ee-962d-dac502259ad0.png

4 分層(分組排序)

Q1:如何分層?

A1:節(jié)點(diǎn)平鋪后已經(jīng)去重,此時(shí)借助 TreeMap 的自然排序特性將節(jié)點(diǎn)按照層級(jí)分組即可。

/**
 * @param dataNodeMap 平鋪結(jié)構(gòu)
 * @return 分層結(jié)構(gòu)
 */
private TreeMap> processLevel(Map dataNodeMap) {
    return dataNodeMap.values().stream().collect(Collectors.groupingBy(DataNode::getLevel, TreeMap::new, Collectors.toSet()))
}
分層如下:

e7f2bfc6-1666-11ee-962d-dac502259ad0.png

1. 根據(jù)分層 TreeMap 的 key 倒序即為調(diào)用的層級(jí)順序 對(duì)應(yīng) key 中的數(shù)據(jù)節(jié)點(diǎn) Set 需用多線程并發(fā)調(diào)用,以保證鏈路調(diào)用時(shí)間

4、分層級(jí)調(diào)用

梳理出調(diào)用關(guān)系并分層后,使用并發(fā)編排工具調(diào)用即可。這里梳理的層級(jí)關(guān)系,level 越大,表示越優(yōu)先調(diào)用。 這里以京東內(nèi)部并發(fā)編排框架為例,說明調(diào)用流程:

/**
 * 構(gòu)建編排流程
 *
 * @param infraDependencyHandlers 依賴接口
 * @param workerExecutor 并發(fā)線程
 * @return 執(zhí)行數(shù)據(jù)
 */
public Sirector buildSirector(Set infraDependencyHandlers, ThreadPoolExecutor workerExecutor) {
    Sirector sirector = new Sirector<>(workerExecutor);
    long start = System.currentTimeMillis();
    // 依賴順序與執(zhí)行順序相反
    TreeMap> levelNodes;
    TreeMap> cacheLevelNodes = localCacheManager.getValue("buildSirector");
    if (Objects.nonNull(cacheLevelNodes)) {
        levelNodes = cacheLevelNodes;
    } else {
        levelNodes = getLevelNodes(infraDependencyHandlers);
        ExecutorUtil.executeVoid(asyncTpExecutor, () -> localCacheManager.putValue("buildSirector", levelNodes));
    }
    log.info("buildSirector 梳理依賴關(guān)系耗時(shí):{}", System.currentTimeMillis() - start);
    // 最底層接口執(zhí)行
    Integer firstLevel = levelNodes.lastKey();
    EventHandler[] beginHandlers = levelNodes.get(firstLevel).stream().map(node -> abstractInfraHandlerMap.get(node.getName())).toArray(EventHandler[]::new);
    EventHandlerGroup group = sirector.begin(beginHandlers);

    Integer lastLevel = levelNodes.firstKey();
    for (int i = firstLevel - 1; i >= lastLevel; i--) {
        EventHandler[] thenHandlers = levelNodes.get(i).stream().map(node -> abstractInfraHandlerMap.get(node.getName())).toArray(EventHandler[]::new);
        group.then(thenHandlers);
    }
    return sirector;
}

5、 個(gè)人思考

作為接入內(nèi)部 RPC、Http 接口實(shí)現(xiàn)業(yè)務(wù)處理的項(xiàng)目,在使用過程中要關(guān)注調(diào)用鏈路上的資源復(fù)用,尤其長(zhǎng)鏈路的調(diào)用,要深入考慮內(nèi)存資源的利用以及對(duì)底層服務(wù)的壓力。

要關(guān)注對(duì)外服務(wù)接口與底層數(shù)據(jù)接口的響應(yīng)時(shí)差,分析調(diào)用邏輯與流程是否合理,是否存在優(yōu)化項(xiàng)。

多線程并發(fā)調(diào)用多個(gè)平行數(shù)據(jù)接口時(shí),如何使得各個(gè)線程的耗時(shí)方差盡可能小?




審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RPC
    RPC
    +關(guān)注

    關(guān)注

    0

    文章

    111

    瀏覽量

    11540
  • HTTP接口
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    1814

原文標(biāo)題:一種接口依賴關(guān)系分層方案

文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    一種PCIe接口的視頻采集解決方案

    一種PCIe接口的視頻采集解決方案
    發(fā)表于 04-30 06:29

    一種低成本高速USB接口的設(shè)計(jì)方案

    一種基于DSP平臺(tái)的低成本高速USB接口方案
    發(fā)表于 05-10 07:13

    分享一種智能卡接口的設(shè)計(jì)方案

    分享一種智能卡接口的設(shè)計(jì)方案
    發(fā)表于 05-27 06:01

    介紹一種差分串行接口方案

    折疊式手機(jī)面臨哪些問題?一種滿足手機(jī)高速圖像數(shù)據(jù)傳輸?shù)牟罘执?b class='flag-5'>接口方案
    發(fā)表于 06-01 06:51

    如何去實(shí)現(xiàn)一種高速通信接口的設(shè)計(jì)?

    一種FPGA與DSP的高速通信接口設(shè)計(jì)與實(shí)現(xiàn)方案
    發(fā)表于 06-02 06:07

    一種基于TMS320C6xll接口的圖像獲取方案

    本文提出了一種基于TMS320C6xll接口的圖像獲取方案
    發(fā)表于 06-03 06:53

    分享一種CH451與AMEG32的接口方案

    分享一種CH451與AMEG32的接口方案
    發(fā)表于 06-04 06:06

    基于mcu的一種分層軟件架構(gòu)的相關(guān)資料分享

    基于mcu的一種分層軟件架構(gòu)()1、寫在前面先來個(gè)圖:經(jīng)過了段時(shí)間的琢磨與思考。借鑒操作系統(tǒng)的分層原理,也搞出來了
    發(fā)表于 11-03 06:46

    一種基于負(fù)載均衡的分層副本定位方法

    提出一種基于負(fù)載均衡的分層副本定位方法――RepliLoc。從副本信息存儲(chǔ)和副本定位計(jì)算2負(fù)載考慮,將副本定位問題劃分為社區(qū)層和社區(qū)聯(lián)合層。分別采用應(yīng)用層廣播方式和基于P2
    發(fā)表于 04-16 08:49 ?16次下載

    一種高效、低延時(shí)的會(huì)議密鑰管理方案

    提出一種高效、低延時(shí)的會(huì)議密鑰管理方案——分層分組式密鑰管理(DCKM)方案,DCKM解決了其他密鑰管理方案中數(shù)據(jù)在子組間傳遞時(shí)必須經(jīng)過多次
    發(fā)表于 04-23 10:48 ?21次下載

    一種包含異常傳播的類間數(shù)據(jù)依賴分析方法

    類間數(shù)據(jù)依賴分析是類間數(shù)據(jù)流測(cè)試的基礎(chǔ)。本文通過分析類簇級(jí)測(cè)試中的異常傳播對(duì)程序數(shù)據(jù)依賴的影響,提出一種包括異常結(jié)構(gòu)在內(nèi)的類間C++程序數(shù)據(jù)依賴分析方法,根據(jù)類間
    發(fā)表于 03-01 14:54 ?9次下載

    一種有效的多關(guān)系聚類算法

    一種有效的多關(guān)系聚類算法_鄧左祥
    發(fā)表于 01-03 15:24 ?0次下載

    一種新的識(shí)別和保留模型特征的自適應(yīng)分層算法

    針對(duì)3D打印中已有自適應(yīng)分層算法不能有效保留模型特征的問題,提出了一種新的識(shí)別和保留模型特征的自適應(yīng)分層算法。首先,擴(kuò)展了模型特征的定義,引入了模型特征丟失和偏移的概念;然后,提出了一種
    發(fā)表于 01-05 10:48 ?0次下載
    <b class='flag-5'>一種</b>新的識(shí)別和保留模型特征的自適應(yīng)<b class='flag-5'>分層</b>算法

    基于mcu的一種分層軟件架構(gòu)

    基于mcu的一種分層軟件架構(gòu)()1、寫在前面先來個(gè)圖:經(jīng)過了段時(shí)間的琢磨與思考。借鑒操作系統(tǒng)的分層原理,也搞出來了
    發(fā)表于 10-28 09:51 ?13次下載
    基于mcu的<b class='flag-5'>一種</b><b class='flag-5'>分層</b>軟件架構(gòu)

    介紹一種基于分層聚類方法的木馬通信行為檢測(cè)模型

    一種基于分層聚類方法的木馬通信行為檢測(cè)模型
    的頭像 發(fā)表于 07-30 11:51 ?1208次閱讀
    介紹<b class='flag-5'>一種</b>基于<b class='flag-5'>分層</b>聚類方法的木馬通信行為檢測(cè)模型
    主站蜘蛛池模板: 欧美xxxav| 日日a.v拍夜夜添久久免费| 国产在线高清视频| 国产在线精品亚洲| 精品久久伊人| 毛片网站网址| 免费国产久久拍久久爱| 暖暖视频免费观看高清完整版| 欧美性类s0x| 四虎永久在线精品国产| 亚洲国产高清视频在线观看| 尹人久久大香找蕉综合影院| 97豆奶视频国产| 刺激性视频黄页| 国产亚洲精品97在线视频一| 精品人妻伦一二三区久久AAA片| 伦理片在线线249| 日本综艺大尺度无删减版在线 | 99精品国产免费观看视频| jaPanesmature儿母| 国产精品69人妻无码久久久| 黑人操白逼| 欧美九十老太另类| 午夜特级毛片| 1a级毛片免费观看| 俄罗斯美幼| 久久精品一区二区免费看| 区产品乱码芒果精品P站在线| 亚洲AV无码一区二区三区乱子伦| 最近更新2019中文字幕免费| 床上色APP下载免费版 | 97人妻丰满熟妇AV无码| 俄罗斯美女啪啪| 久久精品国产在热亚洲| 人人啪日日观看在线| 亚洲免费无码中文在线| ewp系列虐杀在线视频| 黑人巨大交牲老太| 青青视频国产色偷偷| 亚洲免费人成 久久| mdapptv麻豆下载|