ZooKeeper,策展人以及微服务负载平衡的工作方式
Zookeeper如何確保每位工人都能愉快地從工作委托經理那里得到一些工作。
Apache ZooKeeper是注冊,管理和發現在不同計算機上運行的服務的工具。 當我們必須處理具有許多節點的分布式系統時,它是技術堆棧中必不可少的成員,這些節點需要知道其依賴關系從何處啟動。
但是ZooKeeper的級別很低,即使標準用例也需要很多行代碼。 這就是Apache Curator誕生的原因–一個比ZooKeeper更友好,更易于使用的包裝器庫。 使用Curator,我們可以用更少的代碼和更簡潔的方式交付更多內容。
“ Guava對于Java來說就像Curator對ZooKeeper一樣” – ZooKeeper提交者Patrick Hunt
使用ZooKeeper負載均衡微服務
我們習慣于在應用程序前面部署負載均衡器的情況。 它的作用是確保每個單個節點獲得或多或少相同的流量。
在微服務世界中,情況是相同的,但是與單片方法相比,我們具有顯著的優勢:當我們需要擴展應用程序時,我們不必復制整個系統并將其部署在功能強大的服務器上即可平穩運行。 我們只能將精力集中在需要擴展的小模塊上,因此擴展成本要低得多(無論是在服務器成本還是在很多情況下為部署模塊做準備所需的開發方面)。
但是隨著我們系統的發展,我們最終會得到許多可擴展的模塊,每個模塊都需要單獨的負載平衡器。 這似乎很麻煩,因為即使沒有基礎架構,我們的基礎架構也非常復雜。 幸運的是,如果我們將ZooKeeper用作服務編排和發現工具,則可以使用內置的負載平衡功能,而不會在我們的微服務架構中引入任何其他復雜性。
為了展示ZooKeeper中開箱即用的負載平衡工作方式,我們需要兩項服務:將多次部署的工作人員,以及將任務委派給已注冊工作人員的經理。
簡單工人
讓我們從創建一個簡單的工作程序開始,該工作程序將偵聽給定的端口并在要求執行其工作時返回一些結果。 為了實現這個微小的微服務,我們將使用Groovy, Undertow輕量級servlet容器,當然還要使用ZooKeeper和Curator。
我們的工作人員將由一個小類組成,該小類的主要方法可以完成三件事:
class Main {static final void main(String[] args) {// Step 1: Extract name and port number to launch worker// Step 2: Configure and start Rest server on given port// Step 3: Register worker in ZooKeeper} }為簡便起見,我將在此處省略步驟1和2,您可以在GitHub project上查看完整的源代碼。 我們的工作人員只有一個端點GET / work,它會返回一個響應,并帶有被叫工作人員的名字:
@Path("/") class Main {@GET@Path("/work")public String work() {String response = "Work done by $workerName"println responsereturn response}}步驟3: ZooKeeper中的注冊工作人員是最有趣的地方,因此我將對其進行詳細說明:
private static void registerInZookeeper(int port) {CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", new RetryNTimes(5, 1000))curatorFramework.start()ServiceInstance<Void> serviceInstance = ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}")).address('localhost').port(port).name("worker").build()ServiceDiscoveryBuilder.builder(Void).basePath("load-balancing-example").client(curatorFramework).thisInstance(serviceInstance).build().start() }- 第2-3行:我們創建并啟動CuratorFramework客戶端,該客戶端包裝了我們要在ZooKeeper實例上執行的所有操作。 為簡單起見,我們將localhost與默認端口一起使用(通常,它應該是ZooKeeper的運行實例的URL)
- 第4-9行創建了代表我們的工作人員的ServiceInstance。 我們傳遞了從其他微服務呼叫此工作人員所需的所有“聯系方式”
- 第11-16行在由CuratorFramework客戶端表示的ZooKeeper中注冊我們的實例。
出發工人
現在,Worker已經準備就緒,因此我們可以創建胖子罐(使用Gradle fatJar任務),然后使用以下命令啟動它:
java -jar simple-worker/build/libs/simple-worker-1.0-shadow.jar Worker_1 18005在啟動worker之前,請記住您需要在默認2181端口上運行的ZooKeeper實例!
要檢查worker是否正在運行,您應該在http:// localhost:18005 / work上打開瀏覽器,并在其中看到“ Worker_1完成的工作”文本。 要驗證工作人員是否已在ZooKeeper中正確注冊了自己,請啟動命令行客戶端:
cd/bin ./zkCli.sh然后執行ls命令,查看在/ load-balancing-example / worker路徑下注冊的一個節點:
[zk: localhost:2181(CONNECTED) 1] ls /load-balancing-example/worker <enter> [f69545e8-8466-40c0-93e9-f493eb7496b4]簡單的經理
現在,由于我們有工作人員在監聽/ work的請求,因此我們可以創建簡單的經理服務委托任務給其下屬。 主要方法看上去與簡單工作人員項目中的方法非常相似,主要區別在于我們沒有在ZooKeeper中注冊,我們僅創建角色(給驚喜)為我們提供工作人員實例的ServiceProvider 。 所以基本的工作流程是:
要創建ServiceProvider,我們必須創建CuratorFramework客戶端,連接到ZooKeeper,然后獲取具有給定名稱的服務的ServiceProvider,在本例中為worker :
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", new RetryNTimes(5, 1000)) curatorFramework.start()ServiceDiscovery<Void> serviceDiscovery = ServiceDiscoveryBuilder.builder(Void).basePath("load-balancing-example").client(curatorFramework).build() serviceDiscovery.start()serviceProvider = serviceDiscovery.serviceProviderBuilder().serviceName("worker").build() serviceProvider.start()- 第1-2行,創建ZooKeeper客戶端,方法與簡單工作者相同
- 第4-8行,創建ServiceDiscovery,它將能夠為我們提供服務提供商。
- 第10-11行。 創建并啟動ServiceProvider,將用于獲取工作程序節點的工作實例。
最后,我們需要一個Rest端點,管理器在其上等待任務委派:
@GET @Path("/delegate") public String delegate() {def instance = serviceProvider.getInstance()String address = instance.buildUriSpec()String response = (address + "/work").toURL().getText()println responsereturn response }起始經理
Manager已準備就緒,執行fatJar任務后,我們可以使用以下命令啟動它:
java -jar simple-manager/build/libs/simple-manager-1.0-shadow.jar 18000為了驗證它是否正常工作,我們可以在瀏覽器中打開( http:// localhost:18000 / delegate )以查看消息“ Worker_1完成的工作”。
經理對其員工一無所知。 他唯一知道的是服務已在ZooKeeper中的特定路徑下注冊。 這很簡單,無論我們是在本地啟動多個工作人員還是在不同國家/地區的不同服務器上分布。
使用ZooKeeper開箱即用的負載平衡
想象一下這樣的情況:經理從首席執行官那里獲得了太多任務,以至于他需要多個工人來委派工作。 在標準情況下,我們將被迫擴大規模并在他們前面放置負載平衡器。 但是ZooKeeper無需任何其他工作即可為我們提供此功能。
讓我們添加更多在不同端口上偵聽的工作者:
java -jar simple-worker/build/libs/simple-worker-1.0-shadow.jar Worker_1 18005 &java -jar simple-worker/build/libs/simple-worker-1.0-shadow.jar Worker_2 18006 &java -jar simple-worker/build/libs/simple-worker-1.0-shadow.jar Worker_3 18007 &java -jar simple-worker/build/libs/simple-worker-1.0-shadow.jar Worker_4 18008 &訣竅是所有工作程序都在ZooKeeper中的同一路徑下注冊,因此當我們在/ load-balancing-example / worker下列出節點時,將看到四個實例:
[zk: localhost:2181(CONNECTED) 0] ls /load-balancing-example/worker <enter> [d5bc4eb9-8ebb-4b7c-813e-966a25fdd843, 13de9196-bfeb-4c1a-b632-b8b9969b9c0b, 85cd1387-2be8-4c08-977a-0798017379b1, 9e07bd1d-c615-430c-8dcb-bf228e9b56fc]這里最重要的是,要利用這四個新工作人員,經理不需要對代碼進行任何更改。 我們可以在流量增加時啟動新的工作程序實例,或者在無事可做時將其關閉。 Manager與這些操作脫鉤,它仍然調用ServiceProvider來獲取worker的實例并將工作傳遞給他。
所以現在當我們打開http:// localhost:18000 / delegate并按幾次刷新時,我們將看到:
Work done by Worker_1 Work done by Worker_2 Work done by Worker_3 Work done by Worker_4 Work done by Worker_1 Work done by Worker_2 Work done by Worker_3它是如何實現的? 默認情況下,ServiceProvider使用Rounded-robin ProviderStrategy實現,該實現旋轉給定路徑下可用的實例,從而使每個實例都有一些工作要做。 如果默認機制不符合我們的需求,我們當然可以實施自定義策略。
摘要
今天就這些。 如您所見,通過使用Apache ZooKeeper和Curator,我們可以在無需部署,監視和管理單獨負載均衡器的情況下生存。 即使沒有微服務架構,基礎架構也非常復雜。
翻譯自: https://www.javacodegeeks.com/2014/07/zookeeper-curator-and-how-microservices-load-balancing-works.html
總結
以上是生活随笔為你收集整理的ZooKeeper,策展人以及微服务负载平衡的工作方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle最新的Java 8更新破坏了
- 下一篇: 编写JUnit测试的另一种方法(Jasm