高並發場景下的流控管理


   任何應用都有一個設計指標,當應用的壓力超過了他設計所能承載的能力時,就好比一座只允許行人通過的獨木橋,是無法承載一輛坦克的重量的,這個時候,為了讓機器能夠繼續運行,在不宕機的情況下盡其所能的對一部分用戶提供服務,保證整個流程能夠繼續走下去,這個時候,就必須對應用進行流控,丟棄一部分用戶的請無法避免。

  流控可以從多個維度來進行,比如針對QPS並發線程數黑白名單加權分級等等,最典型最直接的便是針對QPS並發線程數的流控。當然,要進行流控,首先等有一個流控的閥值,這個閥值不是說拍拍腦袋就能夠想出來,不同類型的應用,所面臨的情況不一樣,也沒有一個統一的衡量標准,必須經過多輪的壓力測試,才能夠得出一個比較靠譜的數值。

一、簡單的流控

1、使用Semphore進行並發流控

 模擬代碼如下所示:

  Semaphore semphore = new Semaphore(10);  
  if(semphore.getQueueLength() > 10){  
   //等待隊列閥值為10時  
    return;  
  }  
  try {  
   semphore.acquire();  
       
   //干活  
       
  } catch (InterruptedException e) {  
       e.printStackTrace();  
  }finally{  
     semphore.release();//釋放  
  }  

也可以參見:http://ifeve.com/concurrency-practice-1/

2、使用樂觀鎖加上下文切換進行流控

public void enter(Object obj){  
 
    boolean isUpdate = false;  
    int countValue = count.get();  
    if(countValue > 0){  
        isUpdate = count.compareAndSet(countValue, countValue -1);   
        if(isUpdate)return;  
    }  
  
    concurQueue.add(obj);  
  
    try {  
        obj.wait();  
    } catch (InterruptedException e) {  
        logger.error("flowcontrol thread was interrupted .......",e);  
    }  
    return ;  
 }  
  
public void release(){  
  
    synchronized(count){  
        if(count.get() < VALVE){  
            count.set(count.get() + 1);  
        }  
    }  
  
    Object obj = concurQueue.remove();  
    if(obj != null){  
        synchronized (obj) {  
            obj.notify();  
        }  
    }  
    System.out.println("notify ...............");  
    return ;  
}  

具體采用信號量還是使用上下文切換形式,需要根據臨界代碼段執行的時間而定

    當請求進來時,調用配置的concurrentlock的enter方法,判斷是否達到閥值,如果沒有達到閥值,則進入,進行處理, 處理完后計數器加1,如果已經達到閥值則放入等待隊列,因為等待隊列是消耗內存的,因此等待隊列也必須有閥值,如果隊列超過閥值,請求直接丟棄
二、漏斗算法和桶令牌算法

  利用現存的算法,比如:漏斗算法和桶令牌算法進行流量的控制。

參考:http://www.inter12.org/archives/962

           https://blog.jamespan.me/2015/10/19/traffic-shaping-with-token-bucket/

1、漏桶算法(Leaky bucket)

   漏桶算法強制一個常量的輸出速率而不管輸入數據流的突發性,當輸入空閑時,該算法不執行任何動作.就像用一個底部開了個洞的漏桶接水一樣,水進入到漏桶里,桶里的水通過下面的孔以固定的速率流出,當水流入速度過大會直接溢出,可以看出漏桶算法能強行限制數據的傳輸速率.如下圖所示:


2、令牌桶(Token bucket)

  令牌桶算法的基本過程如下:

每秒會有 r 個令牌放入桶中,或者說,每過 1/r 秒桶中增加一個令牌

  1. 桶中最多存放 b 個令牌,如果桶滿了,新放入的令牌會被丟棄
  2. 當一個 n 字節的數據包到達時,消耗 n 個令牌,然后發送該數據包
  3. 如果桶中可用令牌小於 n,則該數據包將被緩存或丟棄

漏桶和令牌桶比較

“漏桶算法”能夠強行限制數據的傳輸速率,而“令牌桶算法”在能夠限制數據的平均傳輸數據外,還允許某種程度的突發傳輸。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允許突發地傳輸數據直到達到用戶配置的上限,因此它適合於具有突發特性的流量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM