偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

讓API并行調(diào)用變得如絲般順滑的絕招

運維 數(shù)據(jù)庫運維
當數(shù)據(jù)量較大的時候,都會通過分庫分表來拆分,分擔讀寫的壓力。分庫分表后比較麻煩的就是查詢的問題,如果不是直接根據(jù)分片鍵去查詢的話,需要對多個表進行查詢。

[[360995]]

本文轉(zhuǎn)載自微信公眾號「猿天地」,作者尹吉歡。轉(zhuǎn)載本文請聯(lián)系猿天地公眾號。  

 當數(shù)據(jù)量較大的時候,都會通過分庫分表來拆分,分擔讀寫的壓力。分庫分表后比較麻煩的就是查詢的問題,如果不是直接根據(jù)分片鍵去查詢的話,需要對多個表進行查詢。

在一些復(fù)雜的業(yè)務(wù)場景下,比如訂單搜索,除了訂單號,用戶,商家 這些常用的搜索條件,可能還有時間,商品等等。

目前常見的做法將數(shù)據(jù)同步到 ES 這類搜索框架中進行查詢,然后通過搜出來的結(jié)果,一般是主鍵 ID, 再去具體的數(shù)據(jù)表中查詢完整的數(shù)據(jù),組裝返回給調(diào)用方。

比如下面這段代碼,首先查詢出文章信息,然后根據(jù)文章中的用戶 ID 去查詢用戶的昵稱。

  1. List<ArticleBO> articleBos = articleDoPage.getRecords().stream().map(r -> { 
  2.     String nickname = userManager.getNickname(r.getUserId()); 
  3.     return articleBoConvert.convertPlus(r, nickname); 
  4. }).collect(Collectors.toList()); 

如果文章有 10 條數(shù)據(jù),那么就需要調(diào)用 10 次用戶服務(wù)提供的接口,而且是同步調(diào)用操作。

當然我們也可以用并行流來實現(xiàn)并發(fā)調(diào)用,代碼如下:

  1. List<ArticleBO> articleBos = articleDoPage.getRecords().parallelStream().map(r -> { 
  2.     String nickname = userManager.getNickname(r.getUserId()); 
  3.     return articleBoConvert.convertPlus(r, nickname); 
  4. }).collect(Collectors.toList()); 

并行流的優(yōu)點很明顯,代碼不用做特別大的改動。需要注意如果用并行流,最好單獨定義一個 ForkJoinPool。

除了用并行流,還可以使用批量查詢的方式來提高性能,降低 RPC 的調(diào)用次數(shù),代碼如下:

  1. List<Long> userIds = articleDoPage.getRecords().stream().map(article -> article.getUserId()).collect(Collectors.toList()); 
  2. Map<Long, String> nickNameMap = userManager.queryByIds(userIds).stream().collect(Collectors.toMap(UserResponse::getId, UserResponse::getNickname)); 
  3. List<ArticleBO> articleBos = articleDoPage.getRecords().stream().map(r -> { 
  4.     String nickname = nickNameMap.containsKey(r.getUserId()) ? nickNameMap.get(r.getUserId()) : CommonConstant.DEFAULT_EMPTY_STR; 
  5.     return articleBoConvert.convertPlus(r, nickname); 
  6. }).collect(Collectors.toList()); 

但批量查詢還是同步模式,下面介紹如果使用 CompletableFuture 來實現(xiàn)異步并發(fā)調(diào)用,直接用原生的 CompletableFuture 也可以,但是編排能力沒有那么強,這里我們選擇一款基于 CompletableFuture 封裝的并行編排框來實現(xiàn)。

稍微做了下封裝,提供了更方便使用的工具類來實現(xiàn)并發(fā)調(diào)用多個接口的邏輯。

第一種方式,適用于比如從 ES 查出了一批 ID, 然后根據(jù) ID 去數(shù)據(jù)庫中或者調(diào)用 RPC 查詢真實數(shù)據(jù),最后得到一個 Map,可以根據(jù) Key 獲取對應(yīng)的數(shù)據(jù)。

內(nèi)部是多線程并發(fā)調(diào)用,會等到結(jié)果全部返回。

  1. public Object aggregationApi() { 
  2.     long s = System.currentTimeMillis(); 
  3.     List<String> ids = new ArrayList<>(); 
  4.     ids.add("1"); 
  5.     ids.add("2"); 
  6.     ids.add("3"); 
  7.     Map<String, UserResponse> callResult = AsyncTemplate.call(ids, id -> { 
  8.         return userService.getUser(id); 
  9.     }, u -> u.getId(), COMMON_POOL); 
  10.     long e = System.currentTimeMillis(); 
  11.     System.out.println("耗時:" + (e-s) + "ms"); 
  12.     return ""

另一個場景就是 API 聚合的場景,需要并行調(diào)用多個接口,將結(jié)果進行組裝。

  1. List<AsyncCall> params = new ArrayList<>(); 
  2. AsyncCall<IntegerInteger> goodsQuery = new AsyncCall("goodsQuery", 1); 
  3. params.add(goodsQuery); 
  4. AsyncCall<String, OrderResponse> orderQuery = new AsyncCall("orderQuery""100"); 
  5. params.add(orderQuery); 
  6. UserQuery q = new UserQuery(); 
  7. q.setAge(18); 
  8. q.setName("yinjihuan"); 
  9. AsyncCall<UserQuery, UserResponse> userQuery = new AsyncCall("userQuery", q); 
  10. params.add(userQuery); 
  11. AsyncTemplate.call(params, p -> { 
  12.     if (p.getTaskId().equals("goodsQuery")) { 
  13.         AsyncCall<IntegerInteger> query = p; 
  14.         return goodsService.getGoodsName(query.getParam()); 
  15.     } 
  16.     if (p.getTaskId().equals("orderQuery")) { 
  17.         AsyncCall<String, OrderResponse> query = p; 
  18.         return orderService.getOrder(query.getParam()); 
  19.     } 
  20.     if (p.getTaskId().equals("userQuery")) { 
  21.         AsyncCall<UserQuery, UserResponse> query = p; 
  22.         return userService.getUser(query.getParam()); 
  23.     } 
  24.     return null
  25. }); 

AsyncCall 中定義參數(shù)和響應(yīng)的類型,響應(yīng)結(jié)果會在執(zhí)行完后會自動設(shè)置到 AsyncCall 中。在 call 方法中需要根據(jù) taskId 去做對應(yīng)的處理邏輯,不同的 taskId 調(diào)用的接口不一樣。

源碼參考:https://github.com/yinjihuan/kitty

關(guān)于作者:尹吉歡,簡單的技術(shù)愛好者,《Spring Cloud 微服務(wù)-全棧技術(shù)與案例解析》, 《Spring Cloud 微服務(wù) 入門 實戰(zhàn)與進階》作者, 公眾號 猿天地 發(fā)起人。

原文鏈接:http://cxytiandi.com/blog/user/1

 

責任編輯:武曉燕 來源: 猿天地
相關(guān)推薦

2017-06-05 10:01:24

互聯(lián)網(wǎng)

2019-04-04 17:15:13

2010-08-06 17:09:14

加薪

2017-10-31 13:20:00

H5翻頁庫框架

2022-05-31 09:01:13

GitHub工具安全

2010-09-01 20:30:14

虛擬園區(qū)網(wǎng)網(wǎng)絡(luò)架構(gòu)H3C

2015-10-28 14:03:32

數(shù)據(jù)遷移數(shù)據(jù)

2025-02-19 13:00:00

移動端觸摸事件響應(yīng)速度JavaScrip

2021-06-07 17:46:31

Python 3.8Python編程語言

2021-08-16 12:13:02

SwiftUIList ArticleList

2010-09-15 21:14:48

IT管理網(wǎng)絡(luò)構(gòu)架Juniper Net

2011-06-21 15:42:32

筆記本技巧

2009-04-16 09:13:09

PHP代碼優(yōu)化提速

2022-10-10 09:41:54

LinuxWindowsWSL2

2020-07-20 10:40:52

Linux命令Ubuntu

2022-03-04 20:28:02

VueReact網(wǎng)頁

2022-10-26 10:24:21

2023-07-06 10:45:03

CIO領(lǐng)導(dǎo)力

2024-11-18 08:33:56

2015-12-02 09:37:24

數(shù)據(jù)中心數(shù)據(jù)中心優(yōu)化
點贊
收藏

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