2016-09-22 157 views
9

我使用gRPC與Python作爲客戶端/服務器內kubernetes莢... 我想能夠啓動相同類型(gRPC服務器)的多個莢並讓客戶端連接到他們(隨機)。gRPC客戶端負載平衡

我派發了10個服務器,並設置了一個「服務」來定位它們。然後,在客戶端,我連接到服務的DNS名稱 - 這意味着kubernetes應該執行負載平衡並將我指向隨機服務器吊艙。 實際上,客戶端調用gRPC函數(這很好用),但是當我查看日誌時,我發現所有調用都轉到同一個服務器pod。

我認爲客戶端正在做某種DNS緩存,導致所有的呼叫被髮送到同一臺服務器。是這樣嗎?是否有禁用它,並設置相同的存根客戶端進行「新」呼叫,並通過每個電話通過DNS獲取新的IP?

我知道如果每次都會查詢DNS服務器,可能會導致開銷,但分配負載對我來說現在更重要。

編輯

可能不是一個緩存的問題...可能只是GRPC的工作方式。 HTTP/2和持久的可重用連接。任何方式在每次通話後「斷開」?

回答

10

讓我藉此機會通過描述事情應該如何工作來回答。

方式的客戶端LB工作在GRPCÇ核心(對於所有的基礎,但Java和去香料或GRPC)如下(權威的文檔,可以發現here):

客戶端LB保持簡單和故意「愚蠢」。我們選擇實施複雜LB策略的方式是通過外部LB服務器(如上述文檔中所述)。你不關心這種情況。相反,您只需創建一個頻道,該頻道將使用(默認)優先選擇 LB策略。

LB策略的輸入是已解析地址的列表。在使用DNS時,如果foo.com解析爲[10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4],則策略將嘗試建立到所有這些連接的連接。成功連接的第一個將成爲選擇的,直到它斷開。因此名稱爲「先挑選」。一個更長的名字本來可以是「先選擇並儘可能長時間地堅持下去」,但是這個名字是爲了一個非常長的文件名:)。如果/當選擇的人斷開連接時,選擇優先策略將移動到返回下一個成功連接的地址(在內部稱爲「連接的子信道」)(如果有的話)。再一次,只要它保持連接,它將繼續選擇這個連接的子信道。如果全部失敗,通話將失敗。

這裏的問題是,DNS解析,被固有地基於拉,僅在信道創建觸發1)和2)在所選擇的連接的子信道的斷線。

截至目前,哈克的解決方案是創建爲每個請求的新渠道(效率非常低,但它會做給你設置的伎倆)。

在2017年第一季度(見https://github.com/grpc/grpc/issues/7818)來考慮改變將允許客戶選擇不同的LB政策,即循環賽。另外,我們可能會考慮在該客戶端配置中引入一個「隨機化」位,這會在對它們執行循環之前對地址進行洗牌,從而有效地實現您的目標。

+0

謝謝你的詳細解答。其實,我已經做了,你有什麼建議和創建爲每個請求(效率不高,我知道)的新渠道。從你的答案我明白,只有在DNS第一個IP會得到請求,直到它停止(沒有可用的連接/死亡/墜毀),只有那麼客戶端將獲得第二個IP等等......是嗎? – Idan

+0

是的。直到變化使人們有可能首先作爲LB政策選擇代替挑循環賽,如提及。 –

+0

是否有擴大多臺gRPC服務器的典型解決方案?或客戶端負載平衡? –

1

如果您創建了vanilla Kubernetes服務,該服務應該有自己的負載平衡虛擬IP(請檢查kubectl get svc your-service是否顯示CLUSTER-IP爲您的服務)。如果是這種情況,DNS緩存不應該成爲問題,因爲單個虛擬IP應該將實際後端中的流量分開。

嘗試​​確認您的服務確實知道您的所有後端。

如果您有headless service,則DNS查找將返回帶有10個IP(每個Pod一個IP)的A記錄。如果您的客戶始終選擇A記錄中的第一個IP,那麼這也將解釋您所看到的行爲。

+0

沒有爲服務器CLUSTER_IP,我可以看到,我有所有的端點,當我做「GET端點」。仍然到同一臺服務器。我認爲這可能是gRPC的工作方式和連接重用的HTTP/2 ... – Idan