因爲疫情的影響,在家一個月了,火鍋、烤肉、燒烤、奶茶已經不認識我是誰了。往往翻到一點關於美食的東西,就饞的不行。終於等到復工,當晚就點了一個火鍋外賣,在家準備解解饞。如今火鍋外賣挺方便的,若是不想洗鍋,能夠點一次性鍋,點的食材也都是切好的,我一瞬間點了牛肉,豬肉、牛肉丸、魚丸、蝦滑、毛肚、黃喉、土豆等食材。等到外賣到來,擺好全部東西,準備開吃,但是吃着吃着,我發現味道並無想象中那麼好了,難道是我一個月就已經忘記了火鍋味?後來我發現是由於我把不少食材一古腦兒都放在鍋裏了,而在外面吃的時候會根據食材的不一樣來決定燙仍是煮,煮多久等等。就拿出名的重慶九宮格火鍋來講:算法
中心格:溫度高,就是用來燙的,適合比較容易熟的食材,如毛肚、肥牛、腰片等。markdown
十字格:溫度中等,用來入味,適合下蝦滑、其特點爲邊煮邊吃等。併發
四角格:溫度低,適合長時間蒸煮須要入味的食材,好比腦花、肥腸、魷魚等。ide
針對不一樣的食材有須要不一樣的火候,這可能就是愛情中常常講的很懸的「合適」吧。由於一次性鍋比較小,所能放的食材比較少,因此不少時候我就在等肉煮熟,在等待中以爲這很是像限流的場景,由此對限流展開了一陣思考。高併發
機器在單位時間內所能承載或者處理的請求數是有限的,這個閥值取決於機器的總體性能以及代碼中這次請求所要處理的邏輯。在高併發的場景下,若是不對請求進行限流,可能會出如今單位時間內大量請求涌入某臺機器實例,致使大量請求在隊列等待,或者致使機器資源耗盡,甚至是服務掛掉。除了防止因爲流量洪峯致使服務被擊垮之外,必定的限流也能保證整個集羣的QPS最佳,由於若是一臺機器實例掛掉,整個集羣就少了一臺機器處理請求,別的機器就要分擔更多的請求,若是流量洪峯持續時間過長,會拖垮整個集羣。咱們知道請求能夠被拒絕,可是服務絕對不能所有掛。因此爲了保證服務的高可用,限流是必不可少的一個方案。性能
目前耳熟能詳的限流算法有:spa
介紹這兩種算法前先擬定一個場景,見下圖:code
我腦海中想要吃某個食材,就會去看火鍋裏面有沒有這個食材已經被煮熟,這是我發送的一個request(假設一個食材只能被看成一個request發送),須要火鍋給予我response,而火鍋若是沒有對應的食材,則會去食材庫查看是否有對應的原材料,這個時候就是火鍋向食材庫進行請求。這是一個很簡單的調用鏈。orm
漏桶算法用上面的場景就很好理解,當火鍋瞬間想要毛肚、牛肉等N個食材,也就是食材庫會接收到火鍋的N個請求,可是火鍋在1s內只能煮Q個食材且Q<N,也就是火鍋能處理的響應只有Q個,假設食材庫存最多能處理的食材是M個,而且N<M,那麼其實食材庫是能夠承受住這麼多的請求的,可是當食材庫在1s內把N個食材整理好返回給火鍋時,火鍋並不可以煮得下這麼多,這個時候火鍋就會溢出,反觀計算機,也就是在單位時間內provider端返回響應時consumer端並不能承受住該回調洪峯,致使consumer端被擊垮。隊列
這個時候就能夠用漏桶算法來解決這類問題,它能夠保證火鍋每一秒想要的食材只能是t個,也就是火鍋的請求速率是恆定的,那麼在單位時間內,食材庫返回的響應也能得以控制,這樣就不會形成火鍋溢出,也就是服務被擊垮的狀況。
漏桶算法雖然能夠對回調洪峯作流量整形,可是對於用戶洪峯,服務依舊會有被擊垮的風險,好比當我1s內想要吃r個食材時,可是r>Q,也就是火鍋沒有辦法承受住我這麼大的請求量,那麼火鍋依舊會被擊垮,這種時候不該該用漏桶算法去限制我想要吃的數量,由於限制了我單位時間想要吃的食材數,就等同於每個單位時間可以發出請求數量就被限制了,而在一個產品中,若是每一個用戶的請求速率都被限制成同樣而且並不快,那這樣的產品將很難被接受。
對於這種用戶洪峯,令牌桶算法能夠有效的對流量進行整形。仍是拿火鍋這個例子,上面不是說火鍋在1s內只能煮Q個食材嗎,那麼我就把這個鍋用擋板分割成Q 個空間(假設一個空間只能煮一個食材),有點相似於重慶九宮格火鍋。當我瞬間想要吃X 個食材時,每一個食材都從一個空間裏面去拿,若是那個空間是空的,則火鍋能夠煮我想要的食材,若是瞬間整個鍋沒有空的空間,則其餘請求都被拒絕,當一個空間的食材被我取走後,該空間就會被釋放,又能夠用來接受食材請求而且煮食材。這就是令牌桶算法。
除了對兩個限流算法從新審視了他們的應用場景外,還對限流粒度也作了思考,從粒度上來講一次請求,無非就是一次RPC的方法調用,因此最小的粒度應該是方法級別的限流,也就是上述火鍋案例中,針對我想要吃某個食材這個請求進行限流。若是對每一個方法都配置不一樣的閥值,整個系統的維護成本就會大大增長,因此通常只是對特殊的方法採用更細的閥值配置。除了方法級別的限流外,更上一層的就是服務級別的限流,一個服務會有不少個方法,有時候咱們不想要對一個一個方法進行限流,可能存在某個服務在一些商城促銷活動等場景下須要限流,而這時候但願可以直接對某個服務進行限流,而並非對服務中的方法進行一一限流,服務粒度的限流是用的最多的。再上一層就是對集羣進行限流,也許是某幾臺機器的性能不佳,因此不能跟正常的機器配置同樣的限流閥值。面向整個集羣的限流通常是用做兜底的保護措施,使系統不會被忽然流量洪峯擊垮。