在微服务架构中,Zookeeper 主要用于以下几个关键领域:
以下是详细的步骤和代码示例,展示如何在微服务架构中使用 Zookeeper。
Zookeeper 可以帮助微服务实例在启动时注册自己,并让其他服务能够发现并调用这些服务。
服务实例在启动时,将自身信息注册到 Zookeeper:
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
public class ServiceRegistry {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String REGISTRY_PATH = "/services";
private ZooKeeper zooKeeper;
public ServiceRegistry() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Received event: " + event);
}
});
}
public void registerService(String serviceName, String serviceAddress) throws KeeperException, InterruptedException {
String servicePath = REGISTRY_PATH + "/" + serviceName;
if (zooKeeper.exists(servicePath, false) == null) {
zooKeeper.create(servicePath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
String addressPath = servicePath + "/address-";
String registeredPath = zooKeeper.create(addressPath, serviceAddress.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("Registered service at: " + registeredPath);
}
public static void main(String[] args) {
try {
ServiceRegistry serviceRegistry = new ServiceRegistry();
serviceRegistry.registerService("example-service", "localhost:8080");
// Keep the application running
Thread.sleep(Long.MAX_VALUE);
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
服务消费者从 Zookeeper 获取可用的服务提供者列表:
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class ServiceDiscovery {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String REGISTRY_PATH = "/services";
private ZooKeeper zooKeeper;
public ServiceDiscovery() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Received event: " + event);
}
});
}
public List<String> discoverServices(String serviceName) throws KeeperException, InterruptedException {
String servicePath = REGISTRY_PATH + "/" + serviceName;
return zooKeeper.getChildren(servicePath, false);
}
public String getServiceAddress(String serviceName, String addressNode) throws KeeperException, InterruptedException {
String addressPath = REGISTRY_PATH + "/" + serviceName + "/" + addressNode;
byte[] data = zooKeeper.getData(addressPath, false, null);
return new String(data, StandardCharsets.UTF_8);
}
public static void main(String[] args) {
try {
ServiceDiscovery serviceDiscovery = new ServiceDiscovery();
List<String> services = serviceDiscovery.discoverServices("example-service");
System.out.println("Discovered services: " + services);
if (!services.isEmpty()) {
String address = serviceDiscovery.getServiceAddress("example-service", services.get(0));
System.out.println("Service address: " + address);
}
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
Zookeeper 可以存储和管理微服务系统的配置信息,确保所有服务共享一致的配置。
首先,在 Zookeeper 中创建一个节点用于存储配置信息:
zkCli.sh
create /microservice-config ""
create /microservice-config/database ""
然后,将配置信息存储到 Zookeeper 中:
set /microservice-config/database "jdbc:mysql://localhost:3306/mydb"
以下是一个从 Zookeeper 获取配置信息的代码示例。
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ConfigManager {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String CONFIG_PATH = "/microservice-config/database";
private ZooKeeper zooKeeper;
public ConfigManager() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Received event: " + event);
}
});
}
public String getDatabaseConfig() throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData(CONFIG_PATH, false, null);
return new String(data, StandardCharsets.UTF_8);
}
public static void main(String[] args) {
try {
ConfigManager configManager = new ConfigManager();
String databaseConfig = configManager.getDatabaseConfig();
System.out.println("Database config: " + databaseConfig);
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
Zookeeper 可以实现分布式锁、Leader 选举等功能,确保微服务之间的协调操作。
以下是一个简单的分布式锁的代码示例。
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
public class DistributedLock {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String LOCK_PATH = "/microservice-lock";
private ZooKeeper zooKeeper;
private String lockNodePath;
public DistributedLock() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Received event: " + event);
}
});
}
public boolean acquireLock() throws KeeperException, InterruptedException {
try {
lockNodePath = zooKeeper.create(LOCK_PATH, "lock".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("Acquired lock: " + lockNodePath);
return true;
} catch (KeeperException.NodeExistsException e) {
System.out.println("Lock already acquired by another process");
return false;
}
}
public void releaseLock() throws KeeperException, InterruptedException {
if (lockNodePath != null) {
zooKeeper.delete(lockNodePath, -1);
System.out.println("Released lock: " + lockNodePath);
}
}
public static void main(String[] args) {
try {
DistributedLock distributedLock = new DistributedLock();
if (distributedLock.acquireLock()) {
// Perform operations while holding the lock
Thread.sleep(5000);
distributedLock.releaseLock();
}
// Keep the application running
Thread.sleep(Long.MAX_VALUE);
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
以下是一个简单的 Leader 选举的代码示例。
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
public class LeaderElection implements Watcher {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String LEADER_PATH = "/microservice-leader";
private ZooKeeper zooKeeper;
public LeaderElection() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, this);
}
public void volunteerForLeader() throws KeeperException, InterruptedException {
try {
zooKeeper.create(LEADER_PATH, "leader".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("I am the leader");
} catch (KeeperException.NodeExistsException e) {
System.out.println("Another node is already the leader");
}
}
public void watchLeader() throws KeeperException, InterruptedException {
zooKeeper.exists(LEADER_PATH, true);
}
@Override
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(LEADER_PATH)) {
try {
volunteerForLeader();
} catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
LeaderElection leaderElection = new LeaderElection();
leaderElection.volunteerForLeader();
leaderElection.watchLeader();
// Keep the application running
Thread.sleep(Long.MAX_VALUE);
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
Zookeeper 可以监控微服务实例的健康状态,提供服务治理功能。
以下是一个简单的健康检查的代码示例。
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
public class HealthCheck {
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String HEALTH_PATH = "/microservice-health";
private ZooKeeper zooKeeper;
private String healthNodePath;
public HealthCheck() throws IOException {
this.zooKeeper = new ZooKeeper(ZK_ADDRESS, SESSION_TIMEOUT, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Received event: " + event);
}
});
}
public void registerHealth(String serviceName, String healthStatus) throws KeeperException, InterruptedException {
String servicePath = HEALTH_PATH + "/" + serviceName;
if (zooKeeper.exists(servicePath, false) == null) {
zooKeeper.create(servicePath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
String healthPath = servicePath + "/status";
if (zooKeeper.exists(healthPath, false) == null) {
zooKeeper.create(healthPath, healthStatus.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} else {
zooKeeper.setData(healthPath, healthStatus.getBytes(), -1);
}
}
public static void main(String[] args) {
try {
HealthCheck healthCheck = new HealthCheck();
healthCheck.registerHealth("example-service", "healthy");
// Keep the application running
Thread.sleep(Long.MAX_VALUE);
} catch (IOException | KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
}
Zookeeper 在微服务架构中的主要应用包括:
通过以上方法,可以在微服务架构中使用 Zookeeper 实现高效稳定的服务发现、配置管理、分布式协调和健康检查。根据实际情况和需求,选择适合你的实现方法并进行实施。