初見微服務之服務註冊與發現

来源:http://www.cnblogs.com/willsuna/archive/2016/06/09/5571895.html
-Advertisement-
Play Games

1.什麼是服務註冊與發現 微服務將傳統的"巨石"應用拆分成一個一個的組件應用,每個組件應用提供特定的服務,可以是一個,也可以是多個,並且組件所含服務應該是可以動態擴展的,隨著時間推移、系統進化,可任意拆分、合併。 組件化應用和顆粒化的服務,遍佈在系統的各個角落,由不同的項目成員進行維護,微服務的核心... ...


1.什麼是服務註冊與發現

   微服務將傳統的"巨石"應用拆分成一個一個的組件應用,每個組件應用提供特定的服務,可以是一個,也可以是多個,並且組件所含服務應該是可以動態擴展的,隨著時間推移、系統進化,可任意拆分、合併。

   組件化應用和顆粒化的服務,遍佈在系統的各個角落,由不同的項目成員進行維護,微服務的核心是化整為零、各司其職,這就要求開發人員不得操作其業務或服務範圍以外的數據模型等資源,只能通過介面的訪問,使用某一服務。

   由於服務的跨度很大(公司很大的情況下)、數量很多(數以百計甚至更多),為保障系統的正常運行,必然需要有一個中心化的組件完成對各個服務的整合,即將分散於各處的服務進行彙總,彙總的信息可以是提供服務的組件名稱、地址、數量等,每個組件擁有一個監聽設備,當本組件內的某個服務的狀態變化時報告至中心化的組件進行狀態的更新。服務的調用方在請求某項服務時首先到中心化組件獲取可提供該項服務的組件信息(IP、埠等),通過預設或自定義的策略選擇該服務的某一提供者進行訪問,實現服務的調用。

   隨著分散式系統的發展,出現了越來越多的分散式調度系統,典型的有ZookeeperConsuletcd,在分散式系統中需要解決的一個問題即拜占庭將軍問題,參考網站8btc(比特幣咨詢網站)《拜占庭將軍問題深入探討》http://www.8btc.com/baizhantingjiangjun

  其中Zookeeper最為成熟,是Yahoo貢獻給Apache基金會的一個頂級開源項目,基於Paxos演算法,參考維基百科條目Paxos (computer science) https://en.wikipedia.org/wiki/Paxos_(computer_science),是HadoopHBase的重要組件。

   下麵一段是官網對於Zk的介紹。

ZooKeeper is a high-performance coordination service for distributed applications. It exposes common services - such as naming, configuration management, synchronization, and group services - in a simple interface so you don't have to write them from scratch. You can use it off-the-shelf to implement consensus, group management, leader election, and presence protocols. And you can build on it for your own, specific needs.

       Zk是為分散式應用設計的一個高性能協調服務,提供瞭如下的通用服務,如命名、配置管理、通過鎖和分組服務,封裝成簡單易用的介面而無需開發人員從頭編寫代碼。可以拿來即用,應用的領域有取得共識、分組管理、領導者選舉和協議呈現。還可以按需自定義功能。

Zketcd的比較如下表

 

語言

演算法

存儲方式

量級

Zookeeper

Java

Paxos

名稱空間(文件系統)

etcd

Go

Raft

K-V存儲

 

2.Zookeeper集群配置

    2.1 Standalone單機部署

       Zookeeper 的配置文件在 conf 目錄下,這個目錄下有 zoo_sample.cfg log4j.properties,你需要做的就是將 zoo_sample.cfg 改名為 zoo.cfg,因為 Zookeeper 在啟動時會找這個文件作為預設配置文件。下麵詳細介紹一下,這個配置文件中各個配置項的意義。

tickTime=2000 

dataDir=D:/devtools/zookeeper-3.2.2/build 

clientPort=2181

tickTime:這個時間是作為 Zookeeper 伺服器之間或客戶端與伺服器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。

dataDir:顧名思義就是 Zookeeper 保存數據的目錄,預設情況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄里。

clientPort:這個埠就是客戶端連接 Zookeeper 伺服器的埠,Zookeeper 會監聽這個埠,接受客戶端的訪問請求。

當這些配置項配置好後,你現在就可以啟動 Zookeeper 了,啟動後要檢查 Zookeeper 是否已經在服務,可以通過 netstat ano 命令查看是否有你配置的 clientPort 埠號在監聽服務。

    2.2 集群部署

Zk進行集群部署時,需保證集群的數量為奇數個,即357…

Zookeeper 的集群模式除了上面的三個配置項還要增加下麵幾個配置項:

initLimit=5 

syncLimit=2 

server.1=192.168.211.1:2888:3888 

server.2=192.168.211.2:2888:3888

initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裡所說的客戶端不是用戶連接 Zookeeper 伺服器的客戶端,而是 Zookeeper 伺服器集群中連接到 Leader Follower 伺服器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是 tickTime)長度後 Zookeeper 伺服器還沒有收到客戶端的返回信息,那麼表明這個客戶端連接失敗。總的時間長度就是 5*2000=10

syncLimit:這個配置項標識 Leader Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4

server.A=BCD:其中 A 是一個數字,表示這個是第幾號伺服器;B 是這個伺服器的 ip 地址;C 表示的是這個伺服器與集群中的 Leader 伺服器交換信息的埠;D 表示的是萬一集群中的 Leader 伺服器掛了,需要一個埠來重新進行選舉,選出一個新的 Leader,而這個埠就是用來執行選舉時伺服器相互通信的埠。如果是偽集群的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信埠號不能一樣,所以要給它們分配不同的埠號。

除了修改 zoo.cfg 配置文件,集群模式下還要配置一個文件 myid,這個文件在 dataDir 目錄下,這個文件裡面就有一個數據就是 A 的值,Zookeeper 啟動時會讀取這個文件,拿到裡面的數據與 zoo.cfg 裡面的配置信息比較從而判斷到底是那個 server

3.Zookeeper服務註冊

Zookeeper新增、刪除節點的操作可以通過zk提供的基礎api進行操作,也可以選擇一些框架,方便我們的使用,這裡採用的是Curator

服務url路徑,舉例如下:

myapp/service/user/info 

myapp/service/configuration

存儲為zk集群如下名稱格式

myapp/service/ 

             | user/info 

             | configuration

提供服務的節點信息: 

public class ServiceProvider {     
    // 提供服務的實例id   
    private Integer instanceId; 
    // 提供服務的實例ip 
    private String ip; 
    // 提供服務的實例埠號
    private Integer port; 
    // 實例註冊時間         
    private Date registTime;  

    省略getter、setter方法

    public byte[] toBytes(){       

        try { 
            return JSONObject.fromObject(this).toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) { 
            throw new SystemException(); 
        } 
    }
}

註冊服務的方法如下:

public void register(String url, ServiceProvider node) { 
       CuratorFramework client = CuratorFrameworkFactory.newClient(url, sessionTimeout, connectionTimeout, new ExponentialBackoffRetry(1000, 3)); 

       client.getConnectionStateListenable().addListener(new ConnectionStateListener() {  

          @Override 
          public void stateChanged(CuratorFramework client, ConnectionState newState) { 
              watcher.process(); 
          } 
       }); 
       client.start();          

          logger.info("正在註冊 zookeeper 服務節點:path=" + path + ", data=" + node);

          client.create().creatingParentsIfNeeded().forPath(path, node.toBytes());

}

logger.info("正在註冊 zookeeper 服務節點:path=" + path + ", data=" + node);

4.Zookeeper服務發現

服務發現的策略可以自定義,如隨機分發、定比例分發、根據伺服器狀態分發等等,其中某種分發策略需要註冊時提供額外的伺服器負載信息等。

監聽器如下:

public class ZookeeperGlobalCacheWatcher { 

public void watch(Closeable client, String path){ 
      cache = new TreeCache((CuratorFramework)client, path); 
      cache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                publishEvent(new CacheWatcherEvent(event)); 
            } 
        }); 
        try {
            cache.start(); 
            logger.info("啟動treeCache watcher"); 
        } catch (Exception e) { 
            throw new SystemException(); 
        } 
    } 
}

服務發現: 

public List<ServiceProvider> getServiceProvider() { 
    if(treeCache == null){ 
        // 監聽器zookeeperGlobalCacheWatcher,監聽zookeeper的狀態
        treeCache = (TreeCache)zookeeperGlobalCacheWatcher.getCache(); 
    }         
    List<ServiceProvider> providers = new ArrayList<ServiceProvider>();  
    try { 
           // 數據轉換
            if(treeCache.getCurrentChildren(path) != null){                 
                for(Entry<String, ChildData> item : treeCache.getCurrentChildren(path).entrySet()){                      
                    ChildData data = item.getValue(); 
                    if(data != null && data.getData() != null && data.getData().length > 0){ 
                        providers.add(JsonUtil.json2Object(new String(item.getValue().getData(), "UTF-8"), ZookeeperServiceProvider.class)); 
                    } 
                } 
            } 
      } catch (Exception e) { 
            throw new SystemException(); 
      }         
      return providers; 
}

   服務註冊和發現是整個微服務軟體架構的核心,zookeeper成熟穩定的性能廣受青睞,在系統技術選型和開發過程中,zookeeper都是占有這絕對的優勢。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。 1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:public synchronized void ...
  • △abstract不可以修飾成員變數 △一個類可以沒有抽象方法,可以定義為抽象類,這樣的目的是不能讓其他類建立本類對象,交給子類完成. △abstract和static(可以被類名調用方法,但是抽象方法調用沒有意義)final(不能被覆蓋方法)private(私有方法無法覆蓋) △介面只能被實現.被 ...
  • 首先介紹一款簡單利落的分頁利器:bootstrap-paginator 效果截圖: GitHub官方下載地址:https://github.com/lyonlai/bootstrap-paginator 備用下載地址:http://files.cnblogs.com/files/Dreamer-1/ ...
  • 在《JavaScript設計模式》關於中介者模式的介紹里,裡面有些錯誤和擅自添加的例子,雖然例子(英文版沒有)是為了讓人更好理解,但是該篇章加上的例子卻給人誤導的感覺,所以如果有人讀這個章節時,建議看英文版。 在看這個模式時候,我只想弄明白一點,中介者模式與訂閱/發佈模式的區別在哪? 中介者模式定義 ...
  • 1.意圖 運用共用技術有效地支持大量細粒度的對象。 2.動機 Flyweight模式描述瞭如何共用對象,使得可以細粒度地使用它們,而無需高昂的代價。flyweight是一個共用對象,它可以同時在多個場景(context)中使用,並且在每個場景中flyweight都可以作為一個獨立的對象 這一點與非共 ...
  • 在未讀《JavaScript設計模式》這本書前,在我的印象里,單例模式就是每個類只會產生一個實例,非常簡單。在細看到這個模式時候,有些疑惑單例模式與工廠模式的區別,雖然看起來像最大區別在於是否多次實例化。 單例(Singleton)模式 單例模式它限制了類的實例化次數只能一次。在實例不存在的情況下, ...
  • 這一篇主要講述構造器(Constructor)模式和模塊(Module)模式以及相關的變體模式,例子是JavaScript代碼。 構造器(Constructor)模式 對象構造器用於創建特定類型的對象——準備好對象以備使用,同時接收構造器可以使用的參數,以在第一次創建對象時,設置成員屬性和方法的值。 ...
  • 1.TEMPLATE METHOD 泛型,也就是這個模式,是可以基於泛型的。 我們往往會有一些演算法,比如排序演算法。它的演算法部分,我可以把它放在一個基類裡面,這樣具體類型的比較可以放在子類裡面。 看如下冒泡排序演算法: 先看int的排序: 只要實現了比較和交換2個介面,就可以了。 在看看基於泛型的子類: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...