Zookeeper 用户服务注册与发现的 Java 代码实现
下面我将提供一个完整的 Zookeeper 实现服务注册与发现的 Java 代码示例,使用 Apache Curator 框架(Zookeeper 的高级客户端库)。
1. 添加 Maven 依赖
首先,在你的 pom.xml 中添加以下依赖:
<dependencies>
<!-- Curator Framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.2.0</version>
</dependency>
<!-- Curator Recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.2.0</version>
</dependency>
<!-- Zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.0</version>
</dependency>
</dependencies>
2. 服务注册实现
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
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;
import java.util.Collection;
public class ServiceRegistry {
private final ServiceDiscovery<InstanceDetails> serviceDiscovery;
private final CuratorFramework client;
public ServiceRegistry(String zookeeperAddress) throws Exception {
// 创建 Curator 客户端
client = CuratorFrameworkFactory.newClient(
zookeeperAddress,
new ExponentialBackoffRetry(1000, 3)
);
client.start();
// 创建 ServiceDiscovery 实例
JsonInstanceSerializer<InstanceDetails> serializer =
new JsonInstanceSerializer<>(InstanceDetails.class);
serviceDiscovery = ServiceDiscoveryBuilder.builder(InstanceDetails.class)
.client(client)
.basePath("/services")
.serializer(serializer)
.build();
serviceDiscovery.start();
}
public void registerService(String serviceName, String instanceId, String address, int port) throws Exception {
// 创建服务实例
ServiceInstance<InstanceDetails> instance = ServiceInstance.<InstanceDetails>builder()
.name(serviceName)
.id(instanceId)
.address(address)
.port(port)
.uriSpec(new UriSpec("{scheme}://{address}:{port}"))
.payload(new InstanceDetails("V1.0"))
.build();
// 注册服务
serviceDiscovery.registerService(instance);
System.out.println("Service registered: " + instance);
}
public Collection<ServiceInstance<InstanceDetails>> queryForInstances(String serviceName) throws Exception {
return serviceDiscovery.queryForInstances(serviceName);
}
public void close() throws Exception {
serviceDiscovery.close();
client.close();
}
// 服务实例详情类
public static class InstanceDetails {
private String version;
public InstanceDetails() {
}
public InstanceDetails(String version) {
this.version = version;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
}
3. 服务发现实现
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
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 java.util.Collection;
public class ServiceDiscoveryClient {
private final ServiceDiscovery<ServiceRegistry.InstanceDetails> serviceDiscovery;
private final CuratorFramework client;
public ServiceDiscoveryClient(String zookeeperAddress) throws Exception {
// 创建 Curator 客户端
client = CuratorFrameworkFactory.newClient(
zookeeperAddress,
new ExponentialBackoffRetry(1000, 3)
);
client.start();
// 创建 ServiceDiscovery 实例
JsonInstanceSerializer<ServiceRegistry.InstanceDetails> serializer =
new JsonInstanceSerializer<>(ServiceRegistry.InstanceDetails.class);
serviceDiscovery = ServiceDiscoveryBuilder.builder(ServiceRegistry.InstanceDetails.class)
.client(client)
.basePath("/services")
.serializer(serializer)
.build();
serviceDiscovery.start();
}
public Collection<ServiceInstance<ServiceRegistry.InstanceDetails>> discoverServices(String serviceName) throws Exception {
return serviceDiscovery.queryForInstances(serviceName);
}
public void close() throws Exception {
serviceDiscovery.close();
client.close();
}
}
4. 使用示例
服务提供者 (注册服务)
public class ServiceProvider {
public static void main(String[] args) throws Exception {
String zookeeperAddress = "localhost:2181";
String serviceName = "user-service";
String instanceId = "user-service-1";
String address = "192.168.1.100";
int port = 8080;
ServiceRegistry registry = new ServiceRegistry(zookeeperAddress);
registry.registerService(serviceName, instanceId, address, port);
// 保持服务运行
Thread.sleep(Long.MAX_VALUE);
registry.close();
}
}
服务消费者 (发现服务)
public class ServiceConsumer {
public static void main(String[] args) throws Exception {
String zookeeperAddress = "localhost:2181";
String serviceName = "user-service";
ServiceDiscoveryClient discoveryClient = new ServiceDiscoveryClient(zookeeperAddress);
while (true) {
Collection<ServiceInstance<ServiceRegistry.InstanceDetails>> instances =
discoveryClient.discoverServices(serviceName);
System.out.println("Discovered " + instances.size() + " instances:");
for (ServiceInstance<ServiceRegistry.InstanceDetails> instance : instances) {
System.out.println(" - " + instance.getAddress() + ":" + instance.getPort() +
" (Version: " + instance.getPayload().getVersion() + ")");
}
Thread.sleep(5000);
}
// discoveryClient.close(); // 实际应用中应该关闭
}
}
5. 高级功能扩展
服务健康检查
import org.apache.curator.framework.recipes.healthcheck.HealthCheck;
import org.apache.curator.framework.recipes.healthcheck.HealthCheckListener;
public class HealthCheckExample {
public static void addHealthCheck(CuratorFramework client, String servicePath) {
HealthCheck healthCheck = new HealthCheck(client, servicePath);
healthCheck.addListener(new HealthCheckListener() {
@Override
public void isHealthy(boolean healthy) {
if (!healthy) {
System.out.println("Service is unhealthy: " + servicePath);
// 可以在这里触发服务重启或其他恢复操作
}
}
});
healthCheck.start();
}
}
负载均衡
import org.apache.curator.x.discovery.ServiceProvider;
import org.apache.curator.x.discovery.strategies.RoundRobinStrategy;
public class LoadBalancer {
private ServiceProvider<ServiceRegistry.InstanceDetails> serviceProvider;
public LoadBalancer(ServiceDiscovery<ServiceRegistry.InstanceDetails> serviceDiscovery,
String serviceName) throws Exception {
serviceProvider = serviceDiscovery.serviceProviderBuilder()
.serviceName(serviceName)
.providerStrategy(new RoundRobinStrategy<>())
.build();
serviceProvider.start();
}
public ServiceInstance<ServiceRegistry.InstanceDetails> getInstance() throws Exception {
return serviceProvider.getInstance();
}
public void close() throws Exception {
serviceProvider.close();
}
}
注意事项
- 确保 Zookeeper 服务已经启动并运行
- 在生产环境中,应该添加适当的异常处理和重试逻辑
- 考虑使用连接状态监听器来处理连接丢失和重新连接的情况
- 服务注册后应该定期检查健康状态
- 服务下线时应该正确注销服务实例
以上代码提供了一个完整的 Zookeeper 服务注册与发现实现,你可以根据实际需求进行调整和扩展。

7920

被折叠的 条评论
为什么被折叠?



