本文章是由機器翻譯。

預測:雲端

負載平衡工作者角色上的私用端點

約瑟夫 Fultz

年 1 月,在早期 David Browne 跟我一起載入平衡內部服務點 Windows Azure 背景工作角色的方案。一般而言,在背景工作角色中的服務端點會發佈,所以負載平衡器可以出面料理平衡呼叫所有執行個體。然而,我們已使用收件者的客戶需要未公開可定址的端點。此外,他們不想要採取某種類型的佇列作業的延遲時間。我們會在如何應付這項需求?

內部事件,讓我們探索各種技術和解決方案是,期間 David 和我出來的兩種不同方法來解決所面臨的挑戰。本月的專欄中,我會掩護我設計考量和用於原型這種方法的其中一個程式碼的位元。

我們不想要不小心 bottleneck 最終的方案,並非軟體 proxy 樣式解決方案。相反地,我選擇將提供有效的 IP 服務呼叫的軟體機制,且呼叫端節點會快取給定期間,以減少終點解析的額外負荷的端點。我會被視為三種主要策略所示:

• 靜態指派:將服務端點指派給每個呼叫的節點

• 集中式控制項:一個節點追蹤和控制的每一個呼叫端節點的工作分派

• 合作的控制項:允許任何指定的節點,表示它是用於服務呼叫

這些選擇的會與其一組的優點和缺點的一組。

靜態工作分派有其優點是容易實作。如果呼叫端和背景工作之間單位的對應相等,這可能是工作的平衡,因為網頁角色的負載平衡解決方案會依副檔名平衡背景工作角色上的呼叫的可行方法。

兩個主要的缺點是它不會處理高可用性的服務,也沒有解決任何不一致的情形,在呼叫端和服務節點之間的負載。如果我嘗試加以轉型以處理這些問題的靜態指派方案,方案幾乎趨勢的主力語言從開始若要移向集中式或合作的控制項。

集中式的控制

一般負載平衡器,將接收到的健康資訊標準與相互制衡這類資訊為基礎的服務要求利用集中式的控制項。它收集的資訊節點、 它對所做的工作分派的瞭解和任何活動訊號的資訊,以及它會指示要求以虛擬 IP (VIP) 到指定的節點。

中心點,會在這種情況下執行大多相同但它不會做為 proxy 要求,但呼叫端節點而是會詢問中央控制器會收到一個很好的位址來進行呼叫,並且控制站會指派根據它知道的位址 (請參閱圖 1)。呼叫端節點將快取端點,並使用預先決定的配量,而過期時就會重複解析程序。

圖 1集中控制

所有的智力值位於中央控制器,它必須追蹤所有來判斷要指派呼叫哪一個節點所需的必要資訊。這可能很簡單,例如循環配置資源,或可能要花上完整的資料收集與健康情況分析。它也可以複雜的各種不同的服務端點有不同的準則,以判斷可用性,這表示中央控制器是在背景工作集區中的服務實作所有細節。

從這項實作最大的 detractor 是如果中央控制站當機,然後系統處於長。這表示必須實作完全不同的解決方案,以解決高可用性的中央控制器。

在某些機械和矩陣系統工作者節點將會選擇主控制站以及,如果活動訊號遺失時,只需選擇一個新。雖然這是一個良好的設計,因為它結合的集中式的控制項和合作的控制項,它也會將加入顯著的負載分散機制的實作。

合作的控制項

項目知道透過管理順便找人幫執行已消失的人可以是真實的障礙實際上已經有人執行工作。詢問他直接他是否進行結果並沒有被更有利,並指定他的努力,好避是以判斷他是否實際上有時間來執行工作的最佳方式。例如是我的模型。

其概念是每一個呼叫的節點會以其目前指派的服務端點開頭,並且詢問您是否是仍可供使用 (請參閱圖 2)。如果不是,節點會繼續循環配置資源到可用集區,直到其中一個正面回應 (請參閱圖 3)。在那之後,稍早所述的相同到期快取機制用來減少端點解析度負荷。

圖 2合作的控制項

圖 3平衡到另一個節點

這項設計被 HA 會搞定的根據設計,並判斷其可用時間和實際能夠以服務的呼叫端在背景工作的節點之間應該要有高精確度。每一個服務節點應該具有納入其實作是注意的事項,讓可用與否服務的特定的智力值。這是超過 CPU 或類似的智慧,可能是由節點所存取的下游系統的可用性一類的資訊。因此,如果節點傳回負、 錯誤或逾時,呼叫端節點查詢的下一個可用的 service 節點 ; 如果可以的話,會對該端點其服務呼叫。

從這個方案大 detractor 是圍牆的它需要兩邊來提供可用性服務和呼叫端] 和 [結束點],以確定端點可用性之間的呼叫通訊協定的實作。

原型

這個範例會執行下列動作:

  • 安裝程式判斷可用性的標準機制
  • 呼叫端就會快取可用的節點在短時間內
  • 我就可以停用的節點集配量,應該顯示為單一節點上正在通過平衡的呼叫
  • 一旦節點會再次可用,呼叫端應該要能夠回到上一個節點

幾個警告訊息:首先,我正在進行智慧地判斷可用性,提供任何工作我只是設定平衡的機制,並不擔心決策的智慧。此外,無法處理錯誤和逾時時,但那些會取得負的結果從可用性查詢相同方式處理。最後,我只抓取所有的背景工作角色,在部署中,但在實作中,則為 true 一更具智慧的方法,決定所有可用的服務端點可能會理想的例如登錄機制或只是嘗試叫用每個端點上的服務以及標示為可能的端點成功呼叫。程式碼不會前往遠一點的位置做為要求特定的私用端點,如果不同每個服務,那麼,無法使用的區別器。

首先要是如何取得 Ip 從在部署中的背景工作角色的清單。若要達到該目標我必須設定角色。背景工作角色的方法,我可以開啟 [設定] 視窗,並加入內部服務端點,如所示圖 4

圖 4加入內部服務端點,背景工作角色

我也已標示為 PrivateServices 的部署中的背景工作角色。使用的 RoleEnvironment 物件,而標籤 「 API,很容易擷取節點:

if (_CurrentUriString == null) {
  System.Collections.ObjectModel.ReadOnlyCollection<RoleInstance> 
    ServiceInstances = null;
  System.Collections.ObjectModel.ReadOnlyCollection<RoleInstance> 
    WebInstances = null;

  ServiceInstances = 
    RoleEnvironment.Roles["PrivateServices"].Instances;
  WebInstances = 
    RoleEnvironment.Roles["ServiceBalancingWeb"].Instances;

我將會符合開始檢查可用性使用序數節點的節點。 當有多個 Web 角色比背景工作角色,我將使用 mod 函式,使其符合開始節點。 有了手的形狀和測試可用性的開始節點中的執行個體,我可以啟動執行迴圈,並測試結束點 (請參閱圖 5)。

圖 5測試端點

while (!found && !Abort) {
  string testuri = 
    ServiceInstances[idxSvcInstance].InstanceEndpoints[
    "EndPointServices"].IPEndpoint.ToString();
  found = CheckAvailability(testuri);
  if (found) { 
    ServiceUriString = testuri; 
  }
  else {
    idxSvcInstance++;
    if (idxSvcInstance >= ServiceInstances.Count) { 
      idxSvcInstance = 0; 
    }
    loopCounter++;
    if (loopCounter == ServiceInstances.Count) { 
      Abort = true; 
    }
  }
}

請注意沒有名為 CheckAvailability 的函式呼叫 (請參閱圖 6)。 該函式中建立使用無的安全性模式,因為端點只用於內部的繫結。 我具現化服務用戶端設定合理的逾時時間,並傳回呼叫的值。

圖 6CheckAvailability

static public bool CheckAvailability(string uri) {
  bool retval = true;
  Binding binding = new NetTcpBinding(SecurityMode.None);
  EndPointServicesRef.EndPointServicesClient endpointsvc = 
    new EndPointServicesRef.EndPointServicesClient(binding, 
    new EndpointAddress(@"net.tcp://" + uri));
  endpointsvc.InnerChannel.OperationTimeout = 
    new System.TimeSpan(0,0,0,0, 5000);

  try {
    retval = endpointsvc.IsAvailable();
  }
  catch (Exception ex) {
    // Todo: handle exception
    retval = false;
  }
  return retval;
}

如果在呼叫期間發生錯誤,我只是傳回 false,允許迴圈以移到下一個節點,並檢查其可用性。 不過請注意,若要判斷網頁角色執行個體在我下執行的程式碼目前的數字將已剖析為執行個體識別碼。 若要使其能夠工作完全我必須開啟任意內部 (可能已被外部) 端點。 如果我還沒有,它不會遞增 ID 及剖析便會是沒有什麼用處,因為每個節點看起來會像只有一個。

若要建立的節點清單的另一種方式會逐一查看所有節點,找出目前正在執行的節點清單中的序數位置,或只是將它們排列 IP 的最後一個八位元。 後者的兩個方法之一就是更是個笨蛋篡改,但此特定範例,我只是使用執行個體識別碼。

一個多個要注意的是在實際部署與開發光纖、 爆滿,強制我在剖析程式碼中處理不同 ID 的結構如下:

string[] IdArray = 
  RoleEnvironment.CurrentRoleInstance.Id.Split('.');
int idxWebInstance = 0;
if (!int.TryParse((IdArray[IdArray.Length - 1]), 
  out idxWebInstance)) {
  IdArray = RoleEnvironment.CurrentRoleInstance.Id.Split('_');
  idxWebInstance = int.Parse((IdArray[IdArray.Length - 1]));
}

這應該傳回我可以快取的很好的結束點 IP 到靜態變數中。 我再設定計時器。 當時間事件引發時我要自己將結束點設定為 null,導致再次尋找有效的端點服務使用的程式碼:

System.Timers.Timer invalidateTimer = 
  new System.Timers.Timer(5000);
invalidateTimer.Elapsed += (sender, e) => 
  _CurrentUriString = null;
invalidateTimer.Start();

在此我使用短的持續期間為 5 秒因為我想要確保在簡短的測驗執行我可以跳躍至少一個 Web 角色至另一個端點一旦停用的其中一個服務節點。

執行這個示範

現在,我要修改預設的網頁和其程式碼後置,只是要顯示的它建立親和性的節點。 我也會新增按鈕來停用] 節點。 程式碼的這兩個部份都相當簡單。 例如,[停用] 按鈕會停用與要求取得平衡的 Web 網頁關聯的服務端點。 因此,它可能會導致一些古怪 UI 大致瞭解這個測試範例。

將在 UI 中新增標籤] 和 [指令按鈕。 在標籤中我會印出指定的結束點的 ID 和按鈕可讓我停用] 節點,因此我可以看到所有節點上一步上線之前,與單一端點相關聯的 Web 角色。 內部的程式碼後置我必須加入一些程式碼上取得端點將頁面載入 (請參閱圖 7)。

圖 7示範網頁程式碼

protected void Page_Load(object sender, EventArgs e) {
  string UriString = EndpointManager.GetEndPoint();
  LastUri=UriString;
            
  Binding binding = new NetTcpBinding(SecurityMode.None);
            
  EndPointServicesRef.EndPointServicesClient endpointsvc = 
    new EndPointServicesRef.EndPointServicesClient(binding, 
    new EndpointAddress(@"net.tcp://" + UriString));
  lblMessage.Text = "WebInstacne ID: " + 
    RoleEnvironment.CurrentRoleInstance.Id.ToString() + 
    " is Calling Service @ " + UriString + " & IsAvailable = " + 
    endpointsvc.IsAvailable().ToString();
  cmdDisable.Enabled=true;
}

因為其實我只有嘗試說明合作的平衡,我還沒有實作另一個服務方法或介面,因此我只是重複使用的 IsAvailable 方法,可說明此點。

圖 8顯示作用中的原型應用程式。 第一次您所見 ID (一個是從開發),IP 以及是否可用。 重新整理網頁會要求之間取得平衡,因此端點還會顯示以不同的方式。 我按一下 [停用] 按鈕,若要設定的琵式碼執行的一小部分會呼叫 DisableNode 的目前結束點:

protected void cmdDisable_Click(object sender, EventArgs e) {
  Binding binding = new NetTcpBinding(SecurityMode.None);
  EndPointServicesRef.EndPointServicesClient endpointsvc = 
    new EndPointServicesRef.EndPointServicesClient(binding, 
    new EndpointAddress(@"net.tcp://" + LastUri));
  endpointsvc.DisableNode();
}

圖 8執行示範

DisableNode 方法只是設定 [強制決定布林值,然後設定計時器,以重新啟用它。計時器是設定為較長的時間比快取的端點,以便於說明這點在測試回合到期:

public void DisableNode() {
  AvailabilityState.Enabled = false;
  AvailabilityState.Available = false;

  System.Timers.Timer invalidateTimer = 
    new System.Timers.Timer(20000);
  invalidateTimer.Elapsed += (sender, e) => EnableNode();
  invalidateTimer.Start();
}

[停用] 節點,與來自不同的網頁伺服器的後續要求應該所有平衡至相同的工作者端點。

超過此範例

這顯然是一個小範例可說明此點,不過我想要反白顯示幾個步驟,應考量的實質實作。我也要先說明一下 David 的實作,以解決問題,因為他解決的問題,我沒有網域。

所以我這個範例中呼叫的節點會做為角色啟動程序的一部分執行端點解決程式碼的意圖。它會快取靜態成員中或在根據快取過期實際的快取重新整理的結束點。不過,它無法合併服務實作,讓與被在 IP 層級的單位的細粒控制項的一部分,連接埠組合。根據要解決的實際問題及服務結構的設計,我可能會放棄另選擇一種樣式。

若要取得這個執行生產環境中,以下是幾個步驟,請考慮和可能解決:

  • 決定可用性智慧。這表示不可能的項目檢查 (CPU、 磁碟、 後端連線狀態等等),但也應該用來翻轉之間正在可用的位元的臨界值。
  • 邏輯來處理這種情況所有傳回無法使用。
  • 若要快取端點配量的相關決策。
  • 若要變更設定,EndpointManager 中的某些其他方法的集區與一般的執行階段維護移除節點。
  • 所有的一般例外狀況處理和診斷通常包含於服務實作。

我知道那些可能平時沒有句話,但我喜歡堅持的指導方針的"沒有 Guessing"。

在快速 David 的方法的摘要,他設定錯誤定義域和升級的網域之間矩陣以確保呼叫端可用性所偏好的相同網域中的端點符合端點可用性。我認為這是個好主意。結合我與他的實作會確定您的 Web 服務的背景工作角色遵循相同服務層次協議如果可能的話,但在沒有可用的情況下,它必須能夠以任何其他節點之間取得平衡。

結論

我希望 Windows Azure 平台會發展為允許負載平衡的私用端點為組態的點。那時候,如果這是您需要 (未經處理的通訊端會幾乎都想保護層級由內部),然後程式碼解決方案可能會回到最簡單的方法。藉由切割離開實際服務呼叫,並結束點解析度呼叫這些組件的啟動時,它應該將 value-add 程式碼初始狀態,且不同於基礎程式碼。因此,一旦就像這樣的功能就會變成可用來設定,服務應該繼續執行可讓您停用平衡的程式碼。

Joseph Fultz* 是架構設計人員,在 Microsoft 技術中心在達拉斯為基地,他在工作與企業客戶和 Isv 設計及原型設計的軟體解決方案以滿足商務及市場的需求。他是在事件,例如 Tech· 的語音Ed 和類似的內部訓練事件。*