壹個api接口 /srm/api2/disabletime 需要提供最大600qps的能力,超過600qps之後需要進行限流,返回429 http code。
現在業務節點壹***20臺,為了異地多活,分布在2機房gz和gz6,倆機房各十臺機器上。
服務限流通常有以下倆種方式:
倆種方式各有優點和缺點
本次實驗就是使用的第壹種方式,為了保證qps達到600之後能限流,所以理想情況下(也就是流量分部均勻的情況)每臺機器的qps為30=600/20,但是實際情況發現,每天機器上的該api的請求量非常的不均,有的是個位數,有的達到了50多個。
可能有人有疑惑,每個節點流量不均有什麽影響呢?那我解釋下。當整個服務的流量來了600qps時,由於流量不均,有的節點流量分布是40或者50的請求量,有的節點是個位數8,5的請求量。現在每臺機器的配置的qps為30,那麽大於30qps的那些節點就出觸發限流了,最終導致整個服務沒有達到600qps時就觸發限流了。
想要了解流量為什麽不均勻,需要首先搞清楚業務整體架構。
最初理解的架構如下,可以很明顯的發現,在gz和gz6倆機房的slb數量不壹致,也就導致了gz的業務機器流量大於gz6的業務機器流量。
理論上 ,gz 的 slb流量會發給 gz 的 nginx,gz6 的slb流量會發給 gz6 的 nginx。騰訊雲的負載均衡,發給 slb 的流量,不區分 gz 與 gz6 ,在所有 slb 的機器裏執行輪詢策略的負載均衡。
那麽gz 的 slb 機器數量比 gz6 多,那 gz機房獲得的流量就比 gz6機房多, gz 的 nignx獲得的流量就比 gz6的nginx多。
上面解釋看似合理,結論就是:由於gz和gz6倆機房的業務節點數量相同,而gz和gz6的slb的數量不同, 最終導致了倆機房的流量不均,進而導致了gz和gz6的業務節點的流量不均 。
下圖是對接口壓測2分鐘,每秒600qps的流量趨勢圖,可以出在gz和gz6的流量大致分部均勻,大致在300Qps左右,這也就間接的證明了上面的想法不對。
上面倆張的流量分部印證了上面的架構是不對的,通過查詢,正確的架構如下,可以看出和上面的架構圖有幾點不同
架構看起來是沒問題,流量到最終端的業務節點也是均勻的,但是事實就是流量是不均勻的,我們結合實際情況來看下,比如輪訓業務節點為a->b->c:
首先slb的輪訓 據指定url來輪訓 的,是 根據整個服務的所有請求 的來輪訓的 ,比如第壹個壓測請求打到的是a業務節點,如果當前時間整個服務沒有別的請求,那麽第二個壓測請求肯定會打到b業務節點,但實際情況是,當前時間肯定有別的請求,所以第二個壓測請求時可能打到的還是a業務節點,也可能是b業務節點,可能是集群中的任何壹個業務節點,我猜測就是這個原因導致了最終的流量不均勻。
為了證明這個猜想,我們可以看看 21:49:00 這個時間點所有機器上的所有請求是不是大致平均的,如果是平均的,則證明我們猜想正確。
可以看出所有機器的請求量大致基本相同,我們的猜想正確。
使用第壹種方式通常有個大前提: 是各個機器流量分布必須非常均勻的,每臺機器配置的qps=總qps/機器節點數量。但是由於網絡總是不穩定性或者其他原因通常流量是不均勻的,所以需要每臺節點配置的qps加壹些Buffer,40或者50qps 。
如果使用第二種方式的話,我們直接在redis配置600qps即可,因為不需要關註每臺機器流量的流量分布,管妳節點的流量是50還8呢,只要總和大於600qps後,服務就會觸發限流了。
如果第二種方式能夠實現,建議使用第二種方式。