首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

5、zookeeper的java -Curator(服务注册与发现)Zookeeper系列文章目录一、知识介绍二、示例1三、示例2

  • 23-09-04 16:01
  • 4021
  • 9553
blog.csdn.net

Zookeeper系列文章目录

1、zookeeper3.7.1安装与验证
2、zookeeper基本操作及应用示例(shell、java api、应用场景示例)
3、zookeeper的选举----经验证符合事实,网上很多都是错误的
4、zookeeper的java三种客户端介绍-Curator(crud、事务操作、监听、分布式计数器、分布式锁)
5、zookeeper的java -Curator(服务注册与发现)


目录

  • Zookeeper系列文章目录
  • 一、知识介绍
    • 1、ServiceInstance
    • 2、ServiceProvider
    • 3、ServiceDiscovery
      • 1)、注册/注销服务
      • 2)、查询服务
      • 3)、服务缓存
  • 二、示例1
    • 1、pom.xml
    • 2、ServiceInstance
    • 3、ServiceProvider及ServiceDiscovery
    • 4、注册服务的添加、删除、查询
    • 5、验证示例1
  • 三、示例2
    • 1、InstanceDetails
    • 2、ProviderService
    • 3、ConsumerService
    • 4、验证


本文介绍使用zookeeper的Curator类库实现服务的注册与发现。
该示例会涉及到本专栏下的其他文章,比如:4、zookeeper的java三种客户端介绍-Curator(crud、事务操作、监听、分布式计数器、分布式锁)
等文章,都是在该专栏下的。

一、知识介绍

Curator Service Discovery它对此抽象出了ServiceInstance、ServiceProvider、ServiceDiscovery三个接口,通过它我们可以很轻易的实现Service Discovery。

1、ServiceInstance

Curator中使用ServiceInstance作为一个服务实例,ServiceInstances具有名称,ID,地址,端口和/或ssl端口以及可选的payload(用户定义)。ServiceInstances以下列方式序列化并存储在ZooKeeper中:
在这里插入图片描述

2、ServiceProvider

ServiceProvider是主要的抽象类。它封装了发现服务为特定的命名服务和提供者策略。提供者策略方案是从一组给定的服务实例选择一个实例。有三个捆绑策略:轮询调度、随机和粘性(总是选择相同的一个)。
ServiceProviders是使用ServiceProviderBuilder分配的。消费者可以从ServiceDiscovery获取ServiceProviderBuilder。ServiceProviderBuilder允许设置服务名称和其他几个可选值。
必须通过调用start()来启动ServiceProvider 。完成后,应该调用close()。
ServiceProvider中有以下两个重要方法:

/** 获取一个服务实例 */
public ServiceInstance<T> getInstance() throws Exception;
/** 获取所有的服务实例 */
public Collection<ServiceInstance<T>> getAllInstances() throws Exception;
  • 1
  • 2
  • 3
  • 4

在使用curator 2.x(ZooKeep3.4.x)时,服务提供者对象必须由应用程序缓存并重用。因为服务提供者添加的内部NamespaceWatcher对象无法在ZooKeep3.4.x中删除,所以为每个对相同服务的调用创建一个新的服务提供者最终将耗尽JVM的内存。

3、ServiceDiscovery

为了创建ServiceProvider,必须有一个ServiceDiscovery。它是由一个ServiceDiscoveryBuilder创建。开始必须调用start()方法。当使用完成应该调用close()方法。
如果特定实例有I/O错误,等等。您应该调用ServiceProvider.NoteError(),并传入实例。ServiceProvider将临时将有错误的实例视为“关闭”。实例的阈值和超时是通过DownInstancePolicy设置的,该策略可以传递给ServiceProviderBuilder(注意:如果没有指定默认DownInstancePolicy,则使用默认DownInstancePolicy)。

对于更精细的控制,您可以使用以下方法:

1)、注册/注销服务

通常,将应用程序的服务描述符传递给ServiceDiscovery构造函数,它将自动注册/注销服务。但是,如果需要手动执行此操作,请使用以下方法:

/** 注册服务 */
public void registerService(ServiceInstance<T> service) throws Exception;
/** 注销服务 */
public void unregisterService(ServiceInstance<T> service) throws Exception;
  • 1
  • 2
  • 3
  • 4

2)、查询服务

您可以查询所有服务名称、特定服务的所有实例或单个服务实例。

/** 查询所有服务名称 */
public Collection<String> queryForNames() throws Exception;
/** 查询特定服务的所有实例 */
public Collection<ServiceInstance<T>> queryForInstances(String name) throws Exception;
/** 查询单个服务实例 */
public ServiceInstance<T> queryForInstance(String name, String id) throws Exception;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3)、服务缓存

上述每个查询方法都直接调用ZooKeeper。
如果经常查询服务,还可以使用ServiceCache。它在内存中缓存特定服务的实例列表。它使用Watcher监听使列表保持最新。
可以通过ServiceDiscovery.serviceCacheBuilder()返回的构建器分配ServiceCache 。
通过调用start()启动ServiceCache对象,完成后,应调用close()。
然后可以通过调用以下内容获取服务的当前已知实例列表:

/** 获取缓存服务列表 */
public List<ServiceInstance<T>> getInstances();
ServiceCache支持在Watcher更新实例列表时收到通知的侦听器:
/**
 * Listener for changes to a service cache
 */
public interface ServiceCacheListener extends ConnectionStateListener {
    /**
     * Called when the cache has changed (instances added/deleted, etc.)
     */
    public void cacheChanged();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

二、示例1

1、pom.xml

		<dependency>
			<groupId>org.projectlombokgroupId>
			<artifactId>lombokartifactId>
			<version>1.18.22version>
		dependency>
		<dependency>
			<groupId>org.apache.curatorgroupId>
			<artifactId>curator-frameworkartifactId>
			<version>5.3.0version>
		dependency>
		
		<dependency>
			<groupId>org.apache.curatorgroupId>
			<artifactId>curator-clientartifactId>
			<version>5.3.0version>
		dependency>
		
		<dependency>
			<groupId>org.apache.curatorgroupId>
			<artifactId>curator-x-discoveryartifactId>
			<version>5.3.0version>
		dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2、ServiceInstance

该serviceInstance是经过扩展后的,也可以不需要那么多的属性。

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.Data;

/**
 * @author alanchan
 *
 */
@Data
public class InstanceDetails {
	public static final String ROOT_PATH = "/service";
	
	//该服务拥有哪些方法
	public Map<String, Service> services = new HashMap<>();

	//服务描述
	private String serviceDescription;

	public InstanceDetails() {
		this.serviceDescription = "";
	}

	public InstanceDetails(String serviceDescription) {
		this.serviceDescription = serviceDescription;
	}

	@Data
	public static class Service {
		//方法名称
		private String methodName;

		//方法描述
		private String description;

		//方法所需要的参数列表
		private List<String> params;

	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

3、ServiceProvider及ServiceDiscovery

import java.io.Closeable;
import java.io.IOException;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.utils.CloseableUtils;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;

/**
 * @author alanchan
 *
 */
public class ExampleServer implements Closeable {

	private final ServiceDiscovery<InstanceDetails> serviceDiscovery;
	private final ServiceInstance<InstanceDetails> serviceInstance;

	public ExampleServer(CuratorFramework client, String path, String serviceName, String description)
			throws Exception {
		UriSpec uriSpec = new UriSpec("{scheme}://foo.com:{port}");

		serviceInstance = ServiceInstance
				.<InstanceDetails>builder()
				.name(serviceName)
				.payload(new InstanceDetails(description))
				.port((int) (65535 * Math.random()))
				.uriSpec(uriSpec)
				.build();

		JsonInstanceSerializer<InstanceDetails> serializer = new JsonInstanceSerializer<InstanceDetails>(
				InstanceDetails.class);

		serviceDiscovery = ServiceDiscoveryBuilder
				.builder(InstanceDetails.class)
				.client(client)
				.basePath(path)
				.serializer(serializer)
				.thisInstance(serviceInstance)
				.build();
	}

	public ServiceInstance<InstanceDetails> getServiceInstance() {
		return serviceInstance;
	}

	public void start() throws Exception {
		serviceDiscovery.start();
	}

	@Override
	public void close() throws IOException {
		CloseableUtils.closeQuietly(serviceDiscovery);
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

4、注册服务的添加、删除、查询

本示例是通过键盘输入方式进行服务的注册、删除、查询操作。


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.curator.framework.CuratorFramework;
//import org.apache.curator.shaded.com.google.common.base.Predicate;
//import org.apache.curator.shaded.com.google.common.collect.Iterables;
//import org.apache.curator.shaded.com.google.common.collect.Lists;
//import org.apache.curator.shaded.com.google.common.collect.Maps;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.curator.utils.CloseableUtils;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceProvider;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.apache.curator.x.discovery.strategies.RandomStrategy;
import org.apache.zookeeper.KeeperException;
import org.zookeeper_curator.App;
import org.zookeeper_curator.Constant;

/**
 * @author alanchan
 *
 */
public class ConsumerExampleServer {
	private static final String PATH = "/discovery/example";

	public static void main(String[] args) throws Exception {
		CuratorFramework client = null;
		ServiceDiscovery<InstanceDetails> serviceDiscovery = null;
		Map<String, ServiceProvider<InstanceDetails>> providers = Maps.newHashMap();
		try {
			client = App.createWithOptions(Constant.zkServerAddress, Constant.retryPolicy, Constant.CONNECTION_TIMEOUT,
					Constant.SESSION_TIMEOUT);
			client.start();

			JsonInstanceSerializer<InstanceDetails> serializer = new JsonInstanceSerializer<InstanceDetails>(
					InstanceDetails.class);

			serviceDiscovery = ServiceDiscoveryBuilder.builder(InstanceDetails.class).client(client).basePath(PATH)
					.serializer(serializer).build();
			serviceDiscovery.start();
			// 服务列表
//			List servers = Lists.newArrayList();

//			testingServiceName 添加成功
//			1 type(s)
//			testingServiceName
//				desc: http://foo.com:57438
//			addInstance(String serviceName, String description, CuratorFramework client,List servers)
//			addInstance("testingServiceName","desc", client,  servers);
//		
			// deleteInstance(String serviceName, List servers)
//			deleteInstance("testingServiceName", servers);

			// listRandomInstance(String serviceName, ServiceDiscovery
			// serviceDiscovery,Map> providers)
//			listRandomInstance("testingServiceName", serviceDiscovery, providers);

			// listInstances(ServiceDiscovery serviceDiscovery)
//			listInstances(serviceDiscovery);

			// 采用命令方式操作几个方法
			command(serviceDiscovery, providers, client);
		} finally {
			for (ServiceProvider<InstanceDetails> cache : providers.values()) {
				CloseableUtils.closeQuietly(cache);
			}
			CloseableUtils.closeQuietly(serviceDiscovery);
			CloseableUtils.closeQuietly(client);
		}
	}

	private static void command(ServiceDiscovery<InstanceDetails> serviceDiscovery,
			Map<String, ServiceProvider<InstanceDetails>> providers, CuratorFramework client) throws Exception {
		List<ExampleServer> servers = Lists.newArrayList();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			boolean done = false;
			while (!done) {
				System.out.print("> ");

				String line = in.readLine();
				if (line == null) {
					break;
				}

				String command = line.trim();
				String[] parts = command.split("\s");
				if (parts.length == 0) {
					continue;
				}
				String operation = parts[0];
				String args[] = Arrays.copyOfRange(parts, 1, parts.length);

				if (operation.equalsIgnoreCase("q") || operation.equalsIgnoreCase("quit")) {
					done = true;
				} else if (operation.equals("add")) {
					addInstance(args[0], args[1], client, servers);
				} else if (operation.equals("delete")) {
					deleteInstance(args[0], servers);
				} else if (operation.equals("random")) {
					listRandomInstance(args[0], serviceDiscovery, providers);
				} else if (operation.equals("list")) {
					listInstances(serviceDiscovery);
				}
			}
		} finally {
			for (ExampleServer server : servers) {
				CloseableUtils.closeQuietly(server);
			}
		}
	}

	// 删除服务
	private static void deleteInstance(String serviceName, List<ExampleServer> servers) {
		ExampleServer server = Iterables.find(servers, new Predicate<ExampleServer>() {
			@Override
			public boolean apply(ExampleServer server) {
				return server.getServiceInstance().getName().endsWith(serviceName);
			}
		}, null);
		if (server == null) {
			System.err.println("没有查到服务名称为: " + serviceName + "的服务");
			return;
		}

		servers.remove(server);
		CloseableUtils.closeQuietly(server);
		System.out.println("移除服务名称为:: " + serviceName + "的服务");
	}

	// 查看服务
	private static void listRandomInstance(String serviceName, ServiceDiscovery<InstanceDetails> serviceDiscovery,
			Map<String, ServiceProvider<InstanceDetails>> providers) throws Exception {

		ServiceProvider<InstanceDetails> provider = providers.get(serviceName);
		if (provider == null) {
			provider = serviceDiscovery.serviceProviderBuilder().serviceName(serviceName)
					.providerStrategy(new RandomStrategy<InstanceDetails>()).build();
			providers.put(serviceName, provider);
			provider.start();

			Thread.sleep(2500); // give the provider time to warm up - in a real application you wouldn't need
								// to do this
		}

		ServiceInstance<InstanceDetails> instance = provider.getInstance();
		if (instance == null) {
			System.err.println("没有查到服务名称为: " + serviceName + "的服务");
		} else {
			System.out.println("	" + instance.getPayload().getServiceDescription() + ": " + instance.buildUriSpec());
		}
	}

	// 查看服务列表
	private static void listInstances(ServiceDiscovery<InstanceDetails> serviceDiscovery) throws Exception {
		try {
			Collection<String> serviceNames = serviceDiscovery.queryForNames();

			for (String serviceName : serviceNames) {
				Collection<ServiceInstance<InstanceDetails>> instances = serviceDiscovery
						.queryForInstances(serviceName);
				System.out.println(serviceName);
				for (ServiceInstance<InstanceDetails> instance : instances) {
					System.out.println(
							"	" + instance.getPayload().getServiceDescription() + ": " + instance.buildUriSpec());
				}
			}

		} catch (KeeperException.NoNodeException e) {
			e.printStackTrace();
			System.err.println("没有找到服务注册实例.");
		} finally {
			CloseableUtils.closeQuietly(serviceDiscovery);
		}
	}

	// 添加服务
	private static void addInstance(String serviceName, String description, CuratorFramework client,
			List<ExampleServer> servers) throws Exception {
		ExampleServer server = new ExampleServer(client, PATH, serviceName, description);
		servers.add(server);
		server.start();

		System.out.println(serviceName + " 添加成功");
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199

5、验证示例1


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.curator.framework.CuratorFramework;
//import org.apache.curator.shaded.com.google.common.base.Predicate;
//import org.apache.curator.shaded.com.google.common.collect.Iterables;
//import org.apache.curator.shaded.com.google.common.collect.Lists;
//import org.apache.curator.shaded.com.google.common.collect.Maps;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.curator.utils.CloseableUtils;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceProvider;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.apache.curator.x.discovery.strategies.RandomStrategy;
import org.apache.zookeeper.KeeperException;
import org.zookeeper_curator.App;
import org.zookeeper_curator.Constant;

public class Test {
	private static final String PATH = "/discovery/example";

	public static void main(String[] args) throws Exception {

		CuratorFramework client = null;
		ServiceDiscovery<InstanceDetails> serviceDiscovery = null;
		Map<String, ServiceProvider<InstanceDetails>> providers = Maps.newHashMap();
		try {
			client = App.createWithOptions(Constant.zkServerAddress, Constant.retryPolicy, Constant.CONNECTION_TIMEOUT,
					Constant.SESSION_TIMEOUT);
			client.start();

			JsonInstanceSerializer<InstanceDetails> serializer = new JsonInstanceSerializer<InstanceDetails>(
					InstanceDetails.class);

			serviceDiscovery = ServiceDiscoveryBuilder.builder(InstanceDetails.class).client(client).basePath(PATH)
					.serializer(serializer).build();
			serviceDiscovery.start();

			processCommands(serviceDiscovery, providers, client);
		} finally {
			for (ServiceProvider<InstanceDetails> cache : providers.values()) {
				CloseableUtils.closeQuietly(cache);
			}
			CloseableUtils.closeQuietly(serviceDiscovery);
			CloseableUtils.closeQuietly(client);
		}
	}

	private static void processCommands(ServiceDiscovery<InstanceDetails> serviceDiscovery,
			Map<String, ServiceProvider<InstanceDetails>> providers, CuratorFramework client) throws Exception {
		printHelp();
		List<ExampleServer> servers = Lists.newArrayList();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			boolean done = false;
			while (!done) {
				System.out.print("> ");

				String line = in.readLine();
				if (line == null) {
					break;
				}

				String command = line.trim();
				String[] parts = command.split("\s");
				if (parts.length == 0) {
					continue;
				}
				String operation = parts[0];
				String args[] = Arrays.copyOfRange(parts, 1, parts.length);

				if (operation.equalsIgnoreCase("help") || operation.equalsIgnoreCase("?")) {
					printHelp();
				} else if (operation.equalsIgnoreCase("q") || operation.equalsIgnoreCase("quit")) {
					done = true;
				} else if (operation.equals("add")) {
					addInstance(args, client, command, servers);
				} else if (operation.equals("delete")) {
					deleteInstance(args, command, servers);
				} else if (operation.equals("random")) {
					listRandomInstance(args, serviceDiscovery, providers, command);
				} else if (operation.equals("list")) {
					listInstances(serviceDiscovery);
				}
			}
		} finally {
			for (ExampleServer server : servers) {
				CloseableUtils.closeQuietly(server);
			}
		}
	}

	private static void deleteInstance(String[] args, String command, List<ExampleServer> servers) {
		if (args.length != 1) {
			System.err.println("syntax error (expected delete ): " + command);
			return;
		}

		final String serviceName = args[0];
		ExampleServer server = Iterables.find(servers, new Predicate<ExampleServer>() {
			@Override
			public boolean apply(ExampleServer server) {
				return server.getServiceInstance().getName().endsWith(serviceName);
			}
		}, null);

		if (server == null) {
			System.err.println("No servers found named: " + serviceName);
			return;
		}

		servers.remove(server);
		CloseableUtils.closeQuietly(server);
		System.out.println("Removed a random instance of: " + serviceName);
	}

	private static void listRandomInstance(String[] args, ServiceDiscovery<InstanceDetails> serviceDiscovery,
			Map<String, ServiceProvider<InstanceDetails>> providers, String command) throws Exception {
		if (args.length != 1) {
			System.err.println("syntax error (expected random ): " + command);
			return;
		}

		String serviceName = args[0];
		ServiceProvider<InstanceDetails> provider = providers.get(serviceName);
		if (provider == null) {
			provider = serviceDiscovery.serviceProviderBuilder().serviceName(serviceName)
					.providerStrategy(new RandomStrategy<InstanceDetails>()).build();
			providers.put(serviceName, provider);
			provider.start();

			Thread.sleep(2500); // give the provider time to warm up - in a real application you wouldn't need
								// to do this
		}

		ServiceInstance<InstanceDetails> instance = provider.getInstance();
		if (instance == null) {
			System.err.println("No instances named: " + serviceName);
		} else {
			outputInstance(instance);
		}
	}

	private static void outputInstance(ServiceInstance<InstanceDetails> instance) {
		System.out.println("	" + instance.getPayload().getServiceDescription() + ": " + instance.buildUriSpec());
	}

	private static void listInstances(ServiceDiscovery<InstanceDetails> serviceDiscovery) throws Exception {
		try {
			Collection<String> serviceNames = serviceDiscovery.queryForNames();
			System.out.println(serviceNames.size() + " type(s)");
			for (String serviceName : serviceNames) {
				Collection<ServiceInstance<InstanceDetails>> instances = serviceDiscovery
						.queryForInstances(serviceName);
				System.out.println(serviceName);
				for (ServiceInstance<InstanceDetails> instance : instances) {
					outputInstance(instance);
				}
			}

		} catch (KeeperException.NoNodeException e) {
			System.err.println("There are no registered instances.");
		} finally {
			CloseableUtils.closeQuietly(serviceDiscovery);
		}
	}

	private static void printHelp() {
		System.out.println(
				"An example of using the ServiceDiscovery APIs. This example is driven by entering commands at the prompt:
");
		System.out.println("add  : Adds a mock service with the given name and description");
		System.out.println("delete : Deletes one of the mock services with the given name");
		System.out.println("list: Lists all the currently registered services");
		System.out.println("random : Lists a random instance of the service with the given name");
		System.out.println("quit: Quit the example");
		System.out.println();
	}

	private static void addInstance(String[] args, CuratorFramework client, String command, List<ExampleServer> servers)
			throws Exception {
		// simulate a new instance coming up
		// in a real application, this would be a separate process

		if (args.length < 2) {
			System.err.println("syntax error (expected add  ): " + command);
			return;
		}

		StringBuilder description = new StringBuilder();
		for (int i = 1; i < args.length; ++i) {
			if (i > 1) {
				description.append(' ');
			}
			description.append(args[i]);
		}

		String serviceName = args[0];
		ExampleServer server = new ExampleServer(client, PATH, serviceName, description.toString());
		servers.add(server);
		server.start();

		System.out.println(serviceName + " added");
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217

运行该类,出现如下界面

An example of using the ServiceDiscovery APIs. This example is driven by entering commands at the prompt:

add <name> <description>: Adds a mock service with the given name and description
delete <name>: Deletes one of the mock services with the given name
list: Lists all the currently registered services
random <name>: Lists a random instance of the service with the given name
quit: Quit the example

> list
There are no registered instances.
> add reg  testing
reg added
> list
1 type(s)
reg
	 testing: http://foo.com:35438
> delete reg
Removed a random instance of: reg
> list
There are no registered instances.
> random reg2
No instances named: reg2
> list
1 type(s)
reg2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注意,delete的时候,可能需要等到时间轮询到才会删除,执行命令可能不会理解被删除。

三、示例2

通过模拟真实使用方式示例,即,定义一个serviceInstance、定义不同的服务提供方并注册至zookeeper、供消费方进行消费。模式是生产者-消费者模式。
本示例以来示例1的pom.xml和部分的文件,此处不再赘述。

1、InstanceDetails


import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.Data;

/**
 * @author alanchan
 *
 */
@Data
public class InstanceDetails {
	public static final String ROOT_PATH = "/service";
	
	//该服务拥有哪些方法
	public Map<String, Service> services = new HashMap<>();

	//服务描述
	private String serviceDescription;

	public InstanceDetails() {
		this.serviceDescription = "";
	}

	public InstanceDetails(String serviceDescription) {
		this.serviceDescription = serviceDescription;
	}

	@Data
	public static class Service {
		//方法名称
		private String methodName;

		//方法描述
		private String description;

		//方法所需要的参数列表
		private List<String> params;

	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

2、ProviderService

可以注册很多的服务。


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.zookeeper_curator.App;
import org.zookeeper_curator.Constant;

public class ProviderService {

	public static void main(String[] args) throws Exception {
		CuratorFramework client = App.createWithOptions(Constant.zkServerAddress, Constant.retryPolicy,
				Constant.CONNECTION_TIMEOUT, Constant.SESSION_TIMEOUT);
		client.start();
		client.blockUntilConnected();

		// 该服务中所有的接口
		Map<String, InstanceDetails.Service> services = new HashMap<>();

		// 添加订单服务接口
		InstanceDetails.Service addOrderService = new InstanceDetails.Service();
		addOrderService.setDescription("添加订单");
		addOrderService.setMethodName("addOrder");
		ArrayList<String> addOrderParams = new ArrayList<>();
		addOrderParams.add("createTime");
		addOrderParams.add("state");
		addOrderService.setParams(addOrderParams);

		services.put("addOrder", addOrderService);

		// 添加删除订单服务接口
		InstanceDetails.Service delOrderService = new InstanceDetails.Service();
		delOrderService.setDescription("删除订单");
		delOrderService.setMethodName("delOrder");
		ArrayList<String> delOrderParams = new ArrayList<>();
		delOrderParams.add("orderId");
		delOrderService.setParams(delOrderParams);

		services.put("delOrder", delOrderService);

		// 服务的其他信息
		InstanceDetails payload = new InstanceDetails();
		payload.setServiceDescription("订单服务");
		payload.setServices(services);

		// 服务构造器
		ServiceInstanceBuilder<InstanceDetails> serviceInstanceBuilder = ServiceInstance.builder();

		// 将订单服务添加到 ServiceInstance
		ServiceInstance<InstanceDetails> orderService = serviceInstanceBuilder
				.address("127.0.0.1")
				.port(8082)
				.name("OrderService")
				.payload(payload)
				.uriSpec(new UriSpec("{scheme}://{address}:{port}"))
				.build();

		// 构建 ServiceDiscovery 用来注册服务
		ServiceDiscovery<InstanceDetails> serviceDiscovery = ServiceDiscoveryBuilder
				.builder(InstanceDetails.class)
				.client(client)
				.serializer(new JsonInstanceSerializer<InstanceDetails>(InstanceDetails.class))
				.basePath(InstanceDetails.ROOT_PATH)
				.build();

		// 服务注册
		serviceDiscovery.registerService(orderService);
		serviceDiscovery.start();

		System.out.println("第一台服务注册成功......");

		TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);

		serviceDiscovery.close();
		client.close();
	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

3、ConsumerService


import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.zookeeper_curator.App;
import org.zookeeper_curator.Constant;

/**
 * @author alanchan
 *
 */
public class ConsumerService {

	public static void main(String[] args) throws Exception {
		CuratorFramework client = App.createWithOptions(Constant.zkServerAddress, Constant.retryPolicy,
				Constant.CONNECTION_TIMEOUT, Constant.SESSION_TIMEOUT);
		client.start();
		client.blockUntilConnected();

		ServiceDiscovery<InstanceDetails> serviceDiscovery = ServiceDiscoveryBuilder
				.builder(InstanceDetails.class)
				.client(client)
				.basePath(InstanceDetails.ROOT_PATH)
				.serializer(new JsonInstanceSerializer<>(InstanceDetails.class))
				.build();
		serviceDiscovery.start();

		// 根据名称获取服务
		Collection<ServiceInstance<InstanceDetails>> services = serviceDiscovery.queryForInstances("OrderService");
		 System.out.println(services.toString());

		for (ServiceInstance<InstanceDetails> service : services) {
			// 获取请求的scheme 例如:http://127.0.0.1:8080
			String uriSpec = service.buildUriSpec();
			// 获取服务的其他信息
			InstanceDetails payload = service.getPayload();

			// 服务描述
			String serviceDesc = payload.getServiceDescription();
			// 获取该服务下的所有接口
			Map<String, InstanceDetails.Service> allService = payload.getServices();
			Set<Map.Entry<String, InstanceDetails.Service>> entries = allService.entrySet();

			for (Map.Entry<String, InstanceDetails.Service> entry : entries) {
				System.out.println(serviceDesc + uriSpec + "/" + service.getName() + "/" + entry.getKey()
						+ " 该方法需要的参数为:" + entry.getValue().getParams().toString());
			}
		}
		System.out.println("---------------------");
		Thread.sleep(3 * 1000);

	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

4、验证

该示例验证需要先启动ProviderService,再启动ConsumerService服务。
启动ProviderService后,控制台简单输出:
第一台服务注册成功…
启动ConsumerService服务后,控制台简单输出:

[ServiceInstance{name='OrderService', id='b6014a82-b924-4004-8790-27211457a23f', address='127.0.0.1', port=8082, sslPort=null, payload=InstanceDetails(services={delOrder=InstanceDetails.Service(methodName=delOrder, description=删除订单, params=[orderId]), addOrder=InstanceDetails.Service(methodName=addOrder, description=添加订单, params=[createTime, state])}, serviceDescription=订单服务), registrationTimeUTC=1659926704836, serviceType=DYNAMIC, uriSpec=org.apache.curator.x.discovery.UriSpec@6c2ac0dc, enabled=true}]
订单服务http://127.0.0.1:8082/OrderService/delOrder 该方法需要的参数为:[orderId]
订单服务http://127.0.0.1:8082/OrderService/addOrder 该方法需要的参数为:[createTime, state]
---------------------
  • 1
  • 2
  • 3
  • 4

如果启动多个ProviderService后(本例启动2个),每个控制台简单输出:
第一台服务注册成功…
启动ConsumerService服务后,控制台简单输出:

[ServiceInstance{name='OrderService', id='f79b7fb0-4979-4b32-a330-da028583fbf8', address='127.0.0.1', port=8082, sslPort=null, payload=InstanceDetails(services={delOrder=InstanceDetails.Service(methodName=delOrder, description=删除订单, params=[orderId]), addOrder=InstanceDetails.Service(methodName=addOrder, description=添加订单, params=[createTime, state])}, serviceDescription=订单服务), registrationTimeUTC=1682233116512, serviceType=DYNAMIC, uriSpec=org.apache.curator.x.discovery.UriSpec@6c2ac0dc, enabled=true}, ServiceInstance{name='OrderService', id='89e1f334-eae0-4116-8e83-dec65cfca8ea', address='127.0.0.1', port=8082, sslPort=null, payload=InstanceDetails(services={delOrder=InstanceDetails.Service(methodName=delOrder, description=删除订单, params=[orderId]), addOrder=InstanceDetails.Service(methodName=addOrder, description=添加订单, params=[createTime, state])}, serviceDescription=订单服务), registrationTimeUTC=1682232987649, serviceType=DYNAMIC, uriSpec=org.apache.curator.x.discovery.UriSpec@6c2ac0dc, enabled=true}]
订单服务http://127.0.0.1:8082/OrderService/delOrder 该方法需要的参数为:[orderId]
订单服务http://127.0.0.1:8082/OrderService/addOrder 该方法需要的参数为:[createTime, state]
订单服务http://127.0.0.1:8082/OrderService/delOrder 该方法需要的参数为:[orderId]
订单服务http://127.0.0.1:8082/OrderService/addOrder 该方法需要的参数为:[createTime, state]
  • 1
  • 2
  • 3
  • 4
  • 5
文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览126567 人正在系统学习中
注:本文转载自blog.csdn.net的一瓢一瓢的饮 alanchan的文章"https://blog.csdn.net/chenwewi520feng/article/details/130320669"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top