队列目的就是存放3分钟内有变化的服务实例,为什么呢,3分钟无变化那就大可不必被拉取一下。如果有注册或者移除实例的操作时,才应该被客户端去拉取。同时,还要清除掉3分钟无变化的服务实例。
- 首先,要有一个队列
队列记录服务实例变更动作
/**
* 最近变更的服务实例的队列
*/
private LinkedList<RecentlyChangedServiceInstance> recentlyChangedQueue =
new LinkedList<>();
- 其次,建立一个表示“最近变化的服务实例”对象
这个对象,包含了服务的实例,还有时间戳以及表示实例变更的操作
class RecentlyChangedServiceInstance {
/**
* 服务实例
*/
ServiceInstance serviceInstance;
/**
* 服务实例发生变更的时间戳
*/
Long changedTimeStamp;
/**
* 变更操作
*/
String changedOperation;
public RecentlyChangedServiceInstance(
ServiceInstance serviceInstance,
Long changedTimeStamp,
String changedOperation) {
this.serviceInstance = serviceInstance;
this.changedTimeStamp = changedTimeStamp;
this.changedOperation = changedOperation;
}
}
还需要建立一个表示操作状态的类
/**
* 服务实例操作
*/
class ServiceInstanceOperation {
/**
* 注册
*/
public static final String REGISTER = "register";
/**
* 删除
*/
public static final String REMOVE = "remove";
}
为了定时剔除不需要被拉取的实例数据,还应该需要一个监控线程类
/**
* 最近变更队列的监控线程
*/
class RecentlyChangedQueueMonitor extends Thread {
@Override
public void run() {
while (true) {
try {
synchronized (instance) {
//遍历queue
RecentlyChangedServiceInstance recentlyChangedServiceInstance = null;
long currentTimeStamp = System.currentTimeMillis();
while ((recentlyChangedServiceInstance = recentlyChangedQueue.peek()) != null) {
//判断如果一个服务实例变更信息已经在队列里存在超过3分钟就从队列中移除
if (currentTimeStamp - recentlyChangedServiceInstance.changedTimeStamp
> RECENTLY_CHANGED_ITEM_EXPIRED_INTERVAL) {
recentlyChangedQueue.pop();
}
}
}
Thread.sleep(RECENTLY_CHANGED_ITEM_CHECK_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
在注册和移除方法中,加上对服务实例变更操作的记录 ```java /**
- 服务注册
@param serviceInstance */ public synchronized void registry(ServiceInstance serviceInstance) { //将服务实例放入最近变更的队列中 RecentlyChangedServiceInstance recentlyServiceInstance =
new RecentlyChangedServiceInstance(serviceInstance, System.currentTimeMillis(), ServiceInstanceOperation.REGISTER);
//加入队尾 recentlyChangedQueue.offer(recentlyServiceInstance);
//将服务实例放入注册表中 Map
serviceInstanceMap = registry.get(serviceInstance.getServiceName());
//如果获取不到map证明实例一个都没有注册过,就要创建一个实例集合map存放集群实例信息 if (serviceInstanceMap == null) {
serviceInstanceMap = new HashMap<String, ServiceInstance>(); registry.put(serviceInstance.getServiceName(),serviceInstanceMap);
} //如果存在对应的实例集合就把新的实例加入该集合中 serviceInstanceMap.put(serviceInstance.getServiceInstanceId(),
serviceInstance);
System.out.println(“服务实例【”+serviceInstance+”】完成注册”); System.out.println(“注册表”+registry); }
/**
- 移除服务实例
- @param serviceName
@param serviceInstanceId */ public synchronized void remove(String serviceName, String serviceInstanceId) { //获取服务实例 Map
serviceInstanceMap = registry.get(serviceName);
ServiceInstance serviceInstance = serviceInstanceMap.get(serviceInstanceId); //将服务实例变更信息放入队列中 RecentlyChangedServiceInstance recentlyServiceInstance =
new RecentlyChangedServiceInstance(serviceInstance, System.currentTimeMillis(), ServiceInstanceOperation.REMOVE);
//加入队尾 recentlyChangedQueue.offer(recentlyServiceInstance);
//从服务注册表中删除实例 System.out.println(“服务实例从注册表中摘除【”+ serviceName + serviceInstanceId + “】”); serviceInstanceMap.remove(serviceInstanceId); }
6. 提供获取增量注册表方法接口
```java
/**
* 拉取增量注册表
* @return
*/
public LinkedList<ServiceRegistry.RecentlyChangedServiceInstance> fetchDeltaServiceRegistry() {
return registry.getRecntlyChangedQueue();
}