1. 程式人生 > >區域感知負載均衡器 Ribbon

區域感知負載均衡器 Ribbon

        Ribbon 簡介
        Ribbon 是 Netflix 釋出的雲中間層服務開源專案,其主要功能是提供客戶側軟體負載均衡演算法,將 Netflix 的中間層服務連線在一起。
        Why Ribbon?
        Ribbon 的區域感知負載均衡器的功能久經考驗。區域感知負載均衡器內建電路跳閘邏輯,可被配置基於區域同源關係(Zone Affinity,也就是更傾向於選擇發出呼叫的服務所在的託管區域內,這樣可用降低延遲,節省成本)選擇目標服務例項。它監控每個區域中執行的例項的運維行為,而且能夠實時快速丟棄一整個區域。在面對整個區域的故障時,這幫我們提升了彈性。簡單的來說,在配置檔案中列出LB後面所有的機器,ribbon 會自動幫你去連這些機器(基於某種規則,如隨機連線、輪流連線,基於響應時間等等)。我們很方便地使用 Ribbon 實現自定義負載均衡演算法。
        Ribbon 的其他一些特性

  1. 發現服務,比如需要增加一些機器,可以實現 Ribbon 的一個介面將這個機器加到列表裡(請參考《Ribbon 和 wowza 的整合開發》的動態修改負載節點案例);
  2. 對 Cloud 平臺的支援:比如對 AWS 來說,有引數支援只返回同一個 zone 的伺服器地址,這樣避免跨 zone 呼叫所引起的網路延時;
  3. 故障恢復能力:可以將一些不可用的伺服器剔除。
        Ribbon 架構圖
ribbon-architecture-dirgram
        Ribbon 時序圖
Ribbon-wowza-sequence
        如何使用 Ribbon?
        Ribbon 提供了框架來支援通用的 LB 機制,同時也提供了對 Netflix eureka 框架的支援。接下來我們來看一下如何在 Java 專案裡使用 Ribbon。
        配置檔案(sample-client.properties)
# Max number of retries on the same server (excluding the first try)
sample-client.ribbon.MaxAutoRetries=1


# Max number of next servers to retry (excluding the first server)
sample-client.ribbon.MaxAutoRetriesNextServer=1


# Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true


# Interval to refresh the server list from the source
sample-client.ribbon.ServerListRefreshInterval=2000


# Connect timeout used by Apache HttpClient
sample-client.ribbon.ConnectTimeout=3000


# Read timeout used by Apache HttpClient
sample-client.ribbon.ReadTimeout=3000


# Initial list of servers, can be changed via Archaius dynamic property at runtime
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80

        每個條目的格式是為
<clientName>.<nameSpace>.<propertyName>=<value>
        clientName 將被接下來的工廠用於建立客戶端。nameSpace 是可配置的,預設是 "ribbon"。常用屬性名可以從 CommonClientConfigKey 獲取。
        這些屬性也可以被定義作系統屬性進行獲取,也可以以 Archaius 載入的任何屬性資源進行獲取。
        Java 程式碼測試
public static void main(String[] args) throws Exception {
      ConfigurationManager.loadPropertiesFromResources("sample-client.properties");  // 1
      System.out.println(ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers"));
      RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client");  // 2
      HttpClientRequest request = HttpClientRequest.newBuilder().setUri(new URI("/")).build(); // 3
      for (int i = 0; i < 20; i++)  {
      	HttpClientResponse response = client.executeWithLoadBalancer(request); // 4
      	System.out.println("Status code for " + response.getRequestedURI() + "  :" + response.getStatus());
      }
      ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer();
      System.out.println(lb.getLoadBalancerStats());
      ConfigurationManager.getConfigInstance().setProperty(
      		"sample-client.ribbon.listOfServers", "www.linkedin.com:80,www.google.com:80"); // 5
      System.out.println("changing servers ...");
      Thread.sleep(3000); // 6
      for (int i = 0; i < 20; i++)  {
      	HttpClientResponse response = client.executeWithLoadBalancer(request);
      	System.out.println("Status code for " + response.getRequestedURI() + "  : " + response.getStatus());
      	response.releaseResources();
      }
      System.out.println(lb.getLoadBalancerStats()); // 7
}

        程式碼解釋:
  1. 使用 Archaius ConfigurationManager 載入屬性;
  2. 使用 ClientFactory 建立客戶端和負載均衡器;
  3. 使用 builder 構建 http 請求。注意我們只支援 URI 的 "/" 部分的路徑,一旦伺服器被負載均衡器選中,會由客戶端計算出完整的 URI;
  4. 呼叫 API client.executeWithLoadBalancer(),不是 exeucte() API;
  5. 動態修正配置中的伺服器池;
  6. 等待伺服器列表重新整理(配置檔案中定義的重新整理間隔是為 2 秒鐘);
  7. 打印出負載均衡器記錄的伺服器統計資訊。
        負載均衡器統計包含了很多用於監控的資訊,可以用於負載均衡演算法的輸入。
        關於 Ribbon 客戶端使用的小 demo(包括 LB 呼叫、動態調整負載均衡節點)請參考部落格《Ribbon 和 wowza 的整合開發》。
        參考資料