利用zookeeper實現自己的服務註冊中心
首先確定服務註冊中心的結構資訊:具體如下圖所示
首先定義客戶端註冊介面,定義了一些基本方法;
package lin.remoting.framework.register; import java.util.List; import java.util.Map; /** * 消費端註冊中心 */ public interface IRegisterCenterInvoker { /** * 由客戶端啟動首次從zookeeper中首次拉去資訊 */ public void initProviderMap(); /** * 消費端獲取服務提供者資訊 * @return */ public Map<String,List<ProviderService>> getServiceMetaDataMap4Consume(); public void registerInvoker(final InvokerService invoker); }
具體實現類如下:
package lin.remoting.framework.register; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.ZkClient; import org.I0Itec.zkclient.serialize.SerializableSerializer; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * 服務呼叫者註冊中心 */ public class RegisterCenterInvoker implements IRegisterCenterInvoker { //服務提供者列表:key :服務提供者介面,value:服務提供者服務方法列表 private static final Map<String, List<ProviderService>> providerServiceMap = new ConcurrentHashMap<String, List<ProviderService>>(); public static final Map<String, List<ProviderService>> serviceMetaDataMapConsume = new ConcurrentHashMap<String, List<ProviderService>>(); private static volatile ZkClient zkClient = null; private static String ZK_SERVICE = "127.0.0.1"; private static int ZK_SESSION_TIME_OUT = 999999; private static int ZK_CONNECTION_TIME_OUT = 999999; private static RegisterCenterInvoker RegisterCenterInvoker = new RegisterCenterInvoker(); private static String ROOT_PATH = "/config_register/" + "lin"; private static String PROVIDER_TYPE = "/provider"; private static String INVOKER_TYPE = "/consumer"; private RegisterCenterInvoker() { } public static RegisterCenterInvoker singleton() { return RegisterCenterInvoker; } public void initProviderMap() { if (serviceMetaDataMapConsume.isEmpty()) { serviceMetaDataMapConsume.putAll(fetchOrUpdateServiceMetaData()); } } /** * 使用該函式前請確保已經使用initProviderMap()已近從zookeeper拉取訊息到本地進行快取 * * @return */ public Map<String, List<ProviderService>> getServiceMetaDataMap4Consume() { return serviceMetaDataMapConsume; } /** * 該函式用於消費者將自身資訊註冊到zookeeper上 * * @param invoker */ public void registerInvoker(InvokerService invoker) { if (invoker == null) { return; } synchronized (RegisterCenterInvoker.class) { if (zkClient == null) { zkClient = new ZkClient(ZK_SERVICE, ZK_SESSION_TIME_OUT, ZK_CONNECTION_TIME_OUT, new SerializableSerializer()); } boolean exist = zkClient.exists(ROOT_PATH); if (!exist) { zkClient.createPersistent(ROOT_PATH, true); } //建立服務消費者節點 String consumeName = invoker.getTargetInterface().getSimpleName(); exist = zkClient.exists(ROOT_PATH+"/"+consumeName); if (!exist) { zkClient.createPersistent(ROOT_PATH+"/"+consumeName); } String consumeNodePath = ROOT_PATH + "/" + consumeName + INVOKER_TYPE; exist = zkClient.exists(consumeNodePath); if (!exist) { zkClient.createPersistent(consumeNodePath); } //建立當前服務端節點 String localIp = invoker.getIP(); String currentConsumeServicePath = consumeNodePath + "/" + localIp; exist = zkClient.exists(currentConsumeServicePath); if (!exist) { zkClient.createEphemeral(currentConsumeServicePath); } } } private Map<String, List<ProviderService>> fetchOrUpdateServiceMetaData() { final Map<String, List<ProviderService>> providerServiceMap = new ConcurrentHashMap<String, List<ProviderService>>(); List<ProviderService> providerServices = null; //連線zk 加鎖防止重複註冊。 synchronized (IRegisterCenterInvoker.class) { if (zkClient == null) { zkClient = new ZkClient(ZK_SERVICE, ZK_SESSION_TIME_OUT, ZK_CONNECTION_TIME_OUT, new SerializableSerializer()); } //從這裡開始從伺服器獲取服務提供者列表 String providerPath = ROOT_PATH; //獲取根節點下所有的子節點 List<String> provideServices = zkClient.getChildren(providerPath); for (String serviceName : provideServices) { //指定服務名下的所有提供者路勁 String servicePath = ROOT_PATH + "/" + serviceName + PROVIDER_TYPE; //所有提供者ip List<String> ipPathList = zkClient.getChildren(servicePath); for (String ipPath : ipPathList) { String[] ipAndPort = ipPath.split("\\|"); String serverIp = ipAndPort[0]; String serverPort = ipAndPort[1]; //引用型 與初始創的為同一個引用 providerServices = providerServiceMap.get(serviceName); if (providerServices == null) { providerServices = new ArrayList<ProviderService>(); providerServiceMap.put(serviceName, providerServices); } ProviderService providerService = new ProviderService(); try { //將服務名轉化為類 這裡根據自己的實際情況設定,事實上這裡可以通過配置 //檔案來確定 providerService.setTargetInterface(Class.forName("lin.remoting.framework.register." + serviceName)); } catch (Exception e) { throw new RuntimeException(e); } providerService.setIP(serverIp); providerService.setPort(Integer.parseInt(serverPort)); //將服務新增到列表當中 providerServices.add(providerService); } //遍歷完後將服務列表新增到其中 providerServiceMap.put(serviceName, providerServices); zkClient.subscribeChildChanges(servicePath, new IZkChildListener() { public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception { if (currentChilds == null) { currentChilds = new ArrayList<String>(); } List<String> tmp = new ArrayList<String>(); for (String ipPort : currentChilds) { tmp.add(ipPort.split("\\|")[0]); } // System.out.println("父路徑"+parentPath); //呼叫函式重新重新整理本地伺服器資料 refreshServiceMetaDataMap(tmp); } }); } } return providerServiceMap; } // 根據ip來判斷 一個服務提供者是否失去作用 public void refreshServiceMetaDataMap(List<String> ipList) { if (ipList == null) { ipList = new ArrayList<String>(); } Map<String, List<ProviderService>> currentServiceMetaDataMap = new ConcurrentHashMap<String, List<ProviderService>>(); for (Map.Entry<String, List<ProviderService>> entry : serviceMetaDataMapConsume.entrySet()) { String serviceName = entry.getKey(); List<ProviderService> providerServices = entry.getValue(); List<ProviderService> currentProviders = currentServiceMetaDataMap.get(serviceName); if (currentProviders == null) { currentProviders = new ArrayList<ProviderService>(); } //需要全部遍歷,因為一臺機器可能提供多個服務 for (ProviderService providerService : providerServices) { if (ipList.contains(providerService.getIP())) { currentProviders.add(providerService); } } currentServiceMetaDataMap.put(serviceName, currentProviders); } //hashMap 函式此時每個對用的serviceName已經對用當前的新服務提供者列表 //服務名相同,當前currentProviders會覆蓋原鍵對應得值 serviceMetaDataMapConsume.putAll(currentServiceMetaDataMap); /* Set<String> keys = serviceMetaDataMapConsume.keySet(); for (String key : keys) { List<ProviderService> providerServices = RegisterCenterInvoker.serviceMetaDataMapConsume.get(key); // System.out.println("跟新大小" + providerServices.size() + "size"); for (ProviderService providerService : providerServices) { System.out.println(providerService); } } */ } }
下面是上面所用到的一些類
package lin.remoting.framework.register; /** * 用於封裝一個服務消費者的基本資訊 */ public class InvokerService { private Class<?> targetInterface; private String IP; public InvokerService(Class<?> targetInterface, String IP) { this.targetInterface = targetInterface; this.IP = IP; } public Class<?> getTargetInterface() { return targetInterface; } public void setTargetInterface(Class<?> targetInterface) { this.targetInterface = targetInterface; } public String getIP() { return IP; } public void setIP(String IP) { this.IP = IP; } }
package lin.remoting.framework.register; //該類用於封裝提供服務類訊息 public class ProviderService { //服務介面 即該服務提供者面向的物件 private Class<?> targetInterface; //服務提供者地址 private String IP; //服務提供者的埠號; private int port; public Class<?> getTargetInterface() { return targetInterface; } public void setTargetInterface(Class<?> targetInterface) { this.targetInterface = targetInterface; } public String getIP() { return IP; } public void setIP(String IP) { this.IP = IP; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } @Override public String toString() { return this.targetInterface.getName() + " IP: " + this.IP + " port: " + this.port; } }
package lin.remoting.framework.register; public class Myservice { }
關於伺服器端的註冊中心的實現將在我的下一篇博文為大家實現
相關推薦
利用zookeeper實現自己的服務註冊中心
首先確定服務註冊中心的結構資訊:具體如下圖所示 首先定義客戶端註冊介面,定義了一些基本方法; package lin.remoting.framework.register; import java.util.List; import java.util.Map;
利用Zookeeper實現分布式鎖及服務註冊中心
建立連接 oid 等待 某個文件 改名 解壓 als 中文字符 blog 原文:利用Zookeeper實現分布式鎖及服務註冊中心對於Zookeeper的定義以及原理,網上已經有很多的優秀文章對其進行了詳細的介紹,所以本文不再進行這方面的闡述。 本文主要介紹一些基本的準備工
使用zookeeper作為服務註冊中心
zookeeper作為服務註冊中心 下載安裝 zookeeper官網下載最新版,修改conf/zoo.cfg配置檔案,如果是windows系統必須指定dataDir具體路徑 執行bin/zkServer.cmd啟動zookeeper服務 注意,zookeeper版本必
SpringCloud服務註冊中心比較:Consul vs Zookeeper vs Etcd vs Eureka
這裡就平時經常用到的服務發現的產品進行下特性的對比,首先看下結論: Feature Consul zookeeper etcd euerka 服務健康檢查 服務狀態,記憶體,硬碟等 (弱)長連線,keepalive 連線心跳 可配支援 多資料中心
Spring Cloud 中使用zookeeper作為服務註冊中心與配置中心
前段時間,瞭解了通過spring-cloud-config-server與spring-cloud-eureka-server作為配置中心與註冊中心,同時瞭解到基於zookeeper或consul可以完成同樣的事情,所以必須瞭解一下,這樣有利於實際工作的技術對比
服務註冊中心Eureka vs Zookeeper vs Consul
初始 fan 協調 ip協議 恢復模式 出錯 維護 機器 更新數據 前言 在現在雲計算和大數據快速發展的今天,業務快速發展和變化。我們以前的單一應用難以應對這種快速的變化, 因此我們需要將以前單一的大應用不斷進行差分,分成若幹微小的應用或者服務,這就是微服務的思想。但
Spring Cloud使用Consul或Zookeeper替換Euraka作為服務註冊中心
一、使用Consul替換Euraka作為服務註冊中心 1、“服務提供者”啟動類註解替換 將註解@EnableEurekaClient替換成@EnableDiscoveryClient 2、pom.xml檔案中新增依賴 <dependency>
Spring Cloud+ spring boot +mybatis+ mysql+ Eureka+ Ribbon實現 服務註冊中心 服務提供 服務消費
一、spring cloud簡介spring cloud 為開發人員提供了快速構建分散式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件匯流排、全域性鎖、決策競選、分散式會話等等。它執行環境簡單,可以在開發人員的電腦上跑。另外說明spring cloud是基
基於ZooKeeper的服務註冊中心
本文介紹基於ZooKeeper的Dubbo服務註冊中心的原理。 1.ZooKeeper中的節點 ZooKeeper是一個樹形結構的目錄服務,支援變更推送,因此非常適合作為Dubbo服務的註冊中心。 注:在ZooKeeper中,節點分為兩類,第一類
SpringCloud 筆記 (一)---- 簡單搭建服務註冊中心與服務,實現服務註冊中心高可用
此spring cloud筆記系列都來源於翟永超的spring cloud微服務實戰一書,可自行去下載,我這裡只是記錄一下學習的筆記 此文件有關於服務註冊中心。 快速構建一個服務註冊中心專案 Pom <parent>
服務註冊中心,Eureka比Zookeeper好在哪裡?
開發十年,就只剩下這套架構體系了! >>>
螞蟻金服服務註冊中心 MetaServer 功能介紹和實現剖析 | SOFARegistry 解析
SOFAStack (Scalable Open Financial Architecture Stack) 是螞蟻金服自主研
Spring Cloud Eureka 分散式開發之服務註冊中心、負載均衡、宣告式服務呼叫實現
介紹 本示例主要介紹 Spring Cloud 系列中的 Eureka,使你能快速上手負載均衡、宣告式服務、服務註冊中心等 Eureka Server Eureka 是 Netflix 的子模組,它是一個基於 REST 的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。 服務註冊和發現對於微服務架
學習一下 SpringCloud (二)-- 服務註冊中心 Eureka、Zookeeper、Consul、Nacos
(1) 相關博文地址: 學習一下 SpringCloud (一)-- 從單體架構到微服務架構、程式碼拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105682.html (2)程式碼地址: https://github.com/lyh-man/Sprin
使用Spring Cloud搭建服務註冊中心
gets log 筆記本電腦 這樣的 ins 閱讀 筆記本 快速 名稱 我們在之前的博客中已經介紹過阿裏的分布式服務框架dubbo【Linux上安裝Zookeeper以及一些註意事項】【一個簡單的案例帶你入門Dubbo分布式框架】,但是小夥伴們應該也看到了,阿裏的dubbo
springboot 註冊服務註冊中心(zk)的兩種方式
stop height span implement exceptio com strong class sta 在使用springboot進行開發的過程中,我們經常需要處理這樣的場景:在服務啟動的時候,需要向服務註冊中心(例如zk)註冊服務狀態,以便當服務狀態改變的時
Spring Cloud Eureka 2 (Eureka Server搭建服務註冊中心)
class XML bsp gist client intellij 嘗試 ati register 工具:IntelliJ IDEA 2017.1.2 x64、maven3.3.9 打開IDE file===>new===>project next
Spring Cloud Eureka 4 (高可用服務註冊中心)
自己 def port hello -c 圖片 sys img 效果 在微服務這樣的分布式環境中,我們需要充分考慮發生故障的情況,所以在生產環境中必須考慮對各個組件進行高可用部署,對於服務註冊中心也是一樣。 Eureka Server 的高可用實際上就是講自己作為服
從零開始搭建系統3.2——微服務註冊中心開發及部署
註冊 cnblogs 開始 htm www post 服務註冊 logs get 從零開始搭建系統3.2——微服務註冊中心開發及部署從零開始搭建系統3.2——微服務註冊中心開發及部署
Spring Cloud構建微服務架構—創建“服務註冊中心”
springboot springcloud mybatis eureka config 創建一個基礎的Spring Boot工程,命名為eureka-server,並在pom.xml中引入需要的依賴內容: <parent> <groupId>org.springf