Desde cero RPC (5) Utilice zookeeper como centro de registro y complete funciones como el descubrimiento de servicios

Resumen ejecutivo:

1. Dependencia del registro de Zookeeper

2. Zookeeper se da cuenta del principio de centro de registro. Nodo, nodo temporal, mecanismo de vigilancia.

3. Utilice el reloj para darse cuenta del centro de registro. El cliente y el servidor utilizan diferentes capacidades del registro.

 

 

Uno, primero agregue dependencias

<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		    <version>3.4.5</version>
		    <exclusions> 
             <exclusion>               
                <groupId>javax.jms</groupId> 
                <artifactId>jms</artifactId> 
             </exclusion> 
             <exclusion>                
                 <groupId>com.sun.jdmk</groupId>           
                  <artifactId>jmxtools</artifactId> 
             </exclusion> 
             <exclusion>             
                  <groupId>com.sun.jmx</groupId> 
                  <artifactId>jmxri</artifactId> 
             </exclusion>
          </exclusions>
		</dependency>
		<dependency>
		    <groupId>com.github.sgroschupf</groupId>
		    <artifactId>zkclient</artifactId>
		    <version>0.1</version>
		</dependency>

2. Pantalla de aplicación simple Zk API

package com.cloudwise.registy.zk;

import javax.swing.plaf.synth.SynthSpinnerUI;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

/**
  *
  * <p>Title: TestZookeeper 测试zkclient功能代码</p>  
  * <p>Description: </p>  
  * @author back  
  * @date 2019年8月17日
 */
public class TestZookeeper {

	
	public static void main(String[] args) throws InterruptedException {
		
		String addr = "192.168.231.135:2181";
		
		int connectionTimeout = 3000;
		
		ZkClient zkClient = new ZkClient(addr, connectionTimeout);
		
		String path = "/zk-data";
		boolean flag = zkClient.exists(path);
		if(flag)
			zkClient.delete(path);
		//创建永久节点
		zkClient.createPersistent(path);
		//节点下写入数据
		zkClient.writeData(path, "zk store data");
		//读取节点下数据
		String data = zkClient.<String>readData(path, true);
		
		System.out.println("读取数据 :  "+data);
		
		zkClient.subscribeDataChanges(path, new IZkDataListener() {
			
			@Override
			public void handleDataDeleted(String dataPath) throws Exception {
					System.out.println("节点数据删除 !");
			}
			
			@Override
			public void handleDataChange(String dataPath, Object data) throws Exception {
					System.out.println("节点数据更改");
			}
		});
		
		zkClient.writeData(path, "zk store data new");
		
		zkClient.delete(path);
		
		Thread.sleep(Integer.MAX_VALUE);
	}
}

3. Encapsulación del código del centro de registro

1. Capacidades de la interfaz de registro del lado del servidor

/**
 * 服务端注册中心
 * <p>Title: IRegisterCenter4Provider.java</p>  
* <p>Description: </p>  
* @author zhaojunjie  
* @date 2020年3月28日  
* @version 1.0
 */
public interface IRegisterCenter4Provider {

	/**
	 * 提供者信息注册到zk节点下
	 * @param serviceMetaData
	 */
	public void registerProvider(final List<ProviderService> serviceMetaData);
	/**
	 * 服务端获取提供者信息
	 * @return
	 */
	public Map<String, List<ProviderService>> getProviderServiceMap();
}

2. Capacidades de la interfaz de registro de clientes

/**
 * 代表客户端注册中心能力接口
 * <p>Title: IRegisterCenter4Invoker.java</p>  
* <p>Description: </p>  
* @author zhaojunjie  
* @date 2020年3月28日  
* @version 1.0
 */
public interface IRegisterCenter4Invoker {

	/**
	 * 客户端初始化服务提供者基本信息
	 */
	public void initProviderMap();
	/**
	 * 客户端获取服务端提供者信息
	 * @return
	 */
	public Map<String, List<ProviderService>> getServiceMetaDataMap4Consume();
	/**
	 * 消费端将缴费者信息注册到zk节点下
	 * @param invok
	 */
	public void registerInvoker(final InvokerService invokerService);
}

3. Realización del centro de registro

public class RegisterCenter implements IRegisterCenter4Invoker, IRegisterCenter4Provider{

	private static RegisterCenter registerCenter = new RegisterCenter();
	//key:接口 value:方法
	private static final Map<String, List<ProviderService>> providerServiceMap = new ConcurrentHashMap<>();
	//zk同步的信息
	private static final Map<String, List<ProviderService>> serviceMetaDataMap4Consume = new ConcurrentHashMap<String, List<ProviderService>>();
	
	private static String ZK_SERVICE = PropertyHelper.getProperty("zookeeper", String.class);
	
	private static int ZK_SESSION_TIMEOUT = 3000;
	
	private static int ZK_CONNECT_TIMEOUT = 3000;
	
	private static String ROOT_PATH = "/back_register";

	private static String PROVIDER_TYPE = "/provider";
	
	private static String INVOKER_TYPE = "/consumer";
	
	private static volatile ZkClient zkClient = null;
	
	private RegisterCenter(){}
	
	public static RegisterCenter singleton(){
		return registerCenter;
	}
	@Override
	public void registerProvider(List<ProviderService> serviceMetaData) {
		if(serviceMetaData == null){
			return;
		}
		//连接zk 注册服务
		synchronized (RegisterCenter.class) {
			for (ProviderService providerService : serviceMetaData) {
				String serviceKey = providerService.getServiceInterface().getName();
				List<ProviderService> list = providerServiceMap.get(serviceKey);
				if(list == null){
					list = new ArrayList<ProviderService>();
				}
				list.add(providerService);
				providerServiceMap.put(serviceKey, list);
			}
			if(zkClient == null){
				zkClient = new ZkClient(ZK_SERVICE, ZK_SESSION_TIMEOUT, 
						ZK_CONNECT_TIMEOUT, new SerializableSerializer());
			}
			boolean exists = zkClient.exists(ROOT_PATH);
			
			if(!exists){
				zkClient.createPersistent(ROOT_PATH, true);
			}
			
			for (Entry<String, List<ProviderService>> entry : providerServiceMap.entrySet()) {
				
				String serviceNode = entry.getKey();
				String basePath = ROOT_PATH + "/" + serviceNode;
				String servicePath = ROOT_PATH + "/" + serviceNode + PROVIDER_TYPE;
				exists = zkClient.exists(basePath);
				if(!exists){
					zkClient.createPersistent(basePath);
				}
				exists = zkClient.exists(servicePath);
				if(!exists){
					zkClient.createPersistent(servicePath);
				}
				int servicePort = entry.getValue().get(0).getServicePort();
				String ip = IPHelper.getCurrentIp();
				String currentServiceIpNode = servicePath + "/" + ip + "|" + servicePort;
				exists = zkClient.exists(currentServiceIpNode);
				if(!exists){
					zkClient.createEphemeral(currentServiceIpNode);
				}
				zkClient.subscribeChildChanges(servicePath, new IZkChildListener() {
					
					@Override
					public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
						if(currentChilds == null){
							currentChilds = new ArrayList<>();
						}
						List<String> transform = Lists.transform(currentChilds, new Function<String, String>() {
							@Override
							public String apply(String input) {
								
								return org.apache.commons.lang3.StringUtils.split(input, "|")[0];
							}
						});
						refreshActivityService(transform);
					}

				});
			}
			
		}
	}

	/**
	 * 服务端刷新服务列表
	 */
	private void refreshActivityService(List<String> serviceIpList) {
		
		if(serviceIpList == null){
			serviceIpList = Lists.newArrayList();
		}
		Map<String,List<ProviderService>> currentServiceMetaDataMap = Maps.newHashMap();
		
		for (Entry<String, List<ProviderService>> entry : providerServiceMap.entrySet()) {
			String key = entry.getKey();
			List<ProviderService> providerServices = entry.getValue();
			List<ProviderService> serviceMetaDataModelList = currentServiceMetaDataMap.get(key);
			if(serviceMetaDataModelList == null){
				serviceMetaDataModelList = Lists.newArrayList();
			}
			for (ProviderService providerService : providerServices) {
				if(serviceIpList.contains(providerService.getServerIp())){
					serviceMetaDataModelList.add(providerService);
				}
			}
			currentServiceMetaDataMap.put(key, serviceMetaDataModelList);
		}
		providerServiceMap.putAll(currentServiceMetaDataMap);
	}
	
	/**
	 * 客户端刷新列表
	 * @param transform
	 */
	private void refreshServiceMetaDataMap(List<String> serviceIpList) {
		if(serviceIpList == null){
			serviceIpList = Lists.newArrayList();
		}
		Map<String,List<ProviderService>> currentServiceMetaDataMap = Maps.newHashMap();
		for (Entry<String, List<ProviderService>> entry : serviceMetaDataMap4Consume.entrySet()) {
			String key = entry.getKey();
			List<ProviderService> serviceList = entry.getValue();
			List<ProviderService> providerServiceList = currentServiceMetaDataMap.get(key);
			if(providerServiceList == null){
				providerServiceList = Lists.newArrayList();
			}
			for (ProviderService providerService : serviceList) {
				if(serviceIpList.contains(providerService.getServerIp())){
					providerServiceList.add(providerService);
				}
			}
			currentServiceMetaDataMap.put(key, providerServiceList);
		}
		serviceMetaDataMap4Consume.putAll(currentServiceMetaDataMap);
		System.out.println("serviceMetaDataMap4Consume : " + JsonUtils.writeToString(serviceMetaDataMap4Consume));
	}
	/**
	 * 获得服务信息
	 * @return
	 */
	private Map<String, List<ProviderService>> fetchorUpdateServiceMetaData() {
		Map<String, List<ProviderService>> providerServiceMap = Maps.newConcurrentMap();
		synchronized (RegisterCenter.class) {
			if(zkClient == null){
				zkClient = new ZkClient(ZK_SERVICE, ZK_SESSION_TIMEOUT, 
						ZK_CONNECT_TIMEOUT, new SerializableSerializer());
			}
			String providerPath = ROOT_PATH;
			List<String> providerServices = zkClient.getChildren(providerPath);
			for (String serviceName : providerServices) {
				String servicePath = providerPath + "/" + serviceName + PROVIDER_TYPE;
				List<String> ipList = zkClient.getChildren(servicePath);
				for (String ipPath : ipList) {
					String serverIp = org.apache.commons.lang3.StringUtils.split(ipPath, "|")[0];
					String serverPort = org.apache.commons.lang3.StringUtils.split(ipPath, "|")[1];
					List<ProviderService> providerServiceList = providerServiceMap.get(serviceName);
					if(providerServiceList == null){
						providerServiceList = Lists.newArrayList();
					}
					ProviderService providerService = new ProviderService();
					try {
						providerService.setServiceInterface(ClassUtils.getClass(serviceName));
					} catch (ClassNotFoundException e) {
						throw new RuntimeException(e);
					}
					providerService.setServerIp(serverIp);
					providerService.setServicePort(Integer.parseInt(serverPort));
					providerServiceList.add(providerService);
					providerServiceMap.put(serviceName, providerServiceList);
				}
				zkClient.subscribeChildChanges(servicePath, new IZkChildListener() {
					
					@Override
					public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
						if(currentChilds == null){
							currentChilds = Lists.newArrayList();
						}
						List<String> transform = Lists.transform(currentChilds, new Function<String, String>() {
							@Override
							public String apply(String input) {
								
								return org.apache.commons.lang3.StringUtils.split(input, "|")[0];
							}
						});
						refreshServiceMetaDataMap(transform);
					}

				});
			}
		}
		return providerServiceMap;
	}
	
	@Override
	public Map<String, List<ProviderService>> getProviderServiceMap() {
		return providerServiceMap;
	}

	@Override
	public void initProviderMap() {
		if(MapUtils.isEmpty(serviceMetaDataMap4Consume)){
			serviceMetaDataMap4Consume.putAll(fetchorUpdateServiceMetaData());
		}
	}

	

	@Override
	public Map<String, List<ProviderService>> getServiceMetaDataMap4Consume() {
		return serviceMetaDataMap4Consume;
	}

	@Override
	public void registerInvoker(InvokerService invokerService) {
		if(invokerService == null){
			return;
		}
		
		synchronized (RegisterCenter.class) {
			if(zkClient == null){
				zkClient = new ZkClient(ZK_SERVICE, ZK_SESSION_TIMEOUT, 
						ZK_CONNECT_TIMEOUT, new SerializableSerializer());
			}
			boolean exists = zkClient.exists(ROOT_PATH);
			
			if(!exists){
				zkClient.createPersistent(ROOT_PATH, true);
			}
			
			String serviceNode = invokerService.getTargetInterface().getName();
			String servicePath = ROOT_PATH + "/" + serviceNode + INVOKER_TYPE;
			exists = zkClient.exists(servicePath);
			if(!exists){
				zkClient.createPersistent(servicePath);
			}
			
			String ip = IPHelper.getCurrentIp();
			String currentServiceIpNode = servicePath + "/" + ip;
			exists = zkClient.exists(currentServiceIpNode);
			if(!exists){
				zkClient.createEphemeral(currentServiceIpNode);
			}
			
		}
	}
	
	
}

 

Supongo que te gusta

Origin blog.csdn.net/MrBack/article/details/99688401
Recomendado
Clasificación