迴圈請求報204問題分析

記得要微笑發表於2021-10-10

背景

商家自主新增配件需求(Freemarker+JQuery前後端未分離專案)中,追加配件彈窗內批量複製貼上配件會迴圈呼叫獲取聯想詞介面,如果複製貼上的配件名稱很多(20+),只有一部分請求成功(狀態碼200)返回響應體,其他請求成功(狀態碼204)但沒有返回響應體。

右側為空.gif

問題分析

對比釋出詢價頁、追加配件頁發現這三個頁面都有同樣的問題,為什麼迴圈併發呼叫介面會報204呢?跟運維、架構溝通後發現,這個問題的根源是閘道器層多了防爬、限流處理,因為當我們的系統被頻繁的請求的時候,就有可能 將系統壓垮,有了閘道器,那麼就可以在閘道器係統做限流,因為所有的請求都需要先通過閘道器係統才能路由到微服務中。

img

令牌桶演算法

令牌桶演算法是比較常見的限流演算法之一,大概描述如下:

1)所有的請求在處理之前都需要拿到一個可用的令牌才會被處理;

2)根據限流大小,設定按照一定的速率往桶裡新增令牌;

3)桶設定最大的放置令牌限制,當桶滿時、新新增的令牌就被丟棄或者拒絕;

4)請求達到後首先要獲取令牌桶中的令牌,拿著令牌才可以進行其他的業務邏輯,處理完業務邏輯之後,將令牌直接刪除;

5)令牌桶有最低限額,當桶中的令牌達到最低限額的時候,請求處理完之後將不會刪除令牌,以此保證足夠的限流

如下圖:

img

cass-webagent閘道器專案中,限流配置如下:

icec:
  limiter:
    enabled: true
    pathConfig:
      burstCapacity: 10 #令牌桶的容量,同一個地址允許在一秒鐘內完成的最大請求數
      replenishRate: 5 #允許使用者每秒處理多少個請求
    routeConfig:
      burstCapacity: 50 #令牌桶的容量,同一個服務允許在一秒鐘內完成的最大請求數
      replenishRate: 20 #允許使用者每秒處理多少個請求
    customConfigs: #自定義令牌桶的容量
    - name: "path:/agentBuy/decodePartNo"
      config.burstCapacity: 500
    - name: "path:/agentBuy/getFastOEMore"
      config.burstCapacity: 500
    - name: "path:/maindata/llq/getDitchPriceSingle"
      config.burstCapacity: 100
    #- name: "route:web-market"
    #  config.burstCapacity: 51

當使用者一秒內請求數量超過20個時,可能有一部分請求返回204(no content

image-20211009191250709.png

解決方案

1、前端控制每秒的請求併發數

比如,每個一個時間段傳送一定量級的請求,利用一個偽死迴圈阻塞主執行緒

//第一種,使用while迴圈
function sleep(delay) {
    var start = (new Date()).getTime();
    while((new Date()).getTime() - start < delay) {
        continue;
    }
}

//或者使用for迴圈
function sleep(delay) {
    for(var t = Date.now(); Date.now() - t <= d;);
}

2、在閘道器增加自定義某些介面路徑允許使用者每秒處理的請求量

3、將迴圈呼叫改成批量介面,這才是最徹底的解決方案

總結

本文僅僅是這類問題做一個分析記錄,在開發中我們要避免這種迴圈呼叫介面的場景。

相關文章