队列目的就是存放3分钟内有变化的服务实例,为什么呢,3分钟无变化那就大可不必被拉取一下。如果有注册或者移除实例的操作时,才应该被客户端去拉取。同时,还要清除掉3分钟无变化的服务实例。

    1. 首先,要有一个队列

    队列记录服务实例变更动作

    1. /**
    2. * 最近变更的服务实例的队列
    3. */
    4. private LinkedList<RecentlyChangedServiceInstance> recentlyChangedQueue =
    5. new LinkedList<>();
    1. 其次,建立一个表示“最近变化的服务实例”对象

    这个对象,包含了服务的实例,还有时间戳以及表示实例变更的操作

    1. class RecentlyChangedServiceInstance {
    2. /**
    3. * 服务实例
    4. */
    5. ServiceInstance serviceInstance;
    6. /**
    7. * 服务实例发生变更的时间戳
    8. */
    9. Long changedTimeStamp;
    10. /**
    11. * 变更操作
    12. */
    13. String changedOperation;
    14. public RecentlyChangedServiceInstance(
    15. ServiceInstance serviceInstance,
    16. Long changedTimeStamp,
    17. String changedOperation) {
    18. this.serviceInstance = serviceInstance;
    19. this.changedTimeStamp = changedTimeStamp;
    20. this.changedOperation = changedOperation;
    21. }
    22. }
    1. 还需要建立一个表示操作状态的类

      1. /**
      2. * 服务实例操作
      3. */
      4. class ServiceInstanceOperation {
      5. /**
      6. * 注册
      7. */
      8. public static final String REGISTER = "register";
      9. /**
      10. * 删除
      11. */
      12. public static final String REMOVE = "remove";
      13. }
    2. 为了定时剔除不需要被拉取的实例数据,还应该需要一个监控线程类

      1. /**
      2. * 最近变更队列的监控线程
      3. */
      4. class RecentlyChangedQueueMonitor extends Thread {
      5. @Override
      6. public void run() {
      7. while (true) {
      8. try {
      9. synchronized (instance) {
      10. //遍历queue
      11. RecentlyChangedServiceInstance recentlyChangedServiceInstance = null;
      12. long currentTimeStamp = System.currentTimeMillis();
      13. while ((recentlyChangedServiceInstance = recentlyChangedQueue.peek()) != null) {
      14. //判断如果一个服务实例变更信息已经在队列里存在超过3分钟就从队列中移除
      15. if (currentTimeStamp - recentlyChangedServiceInstance.changedTimeStamp
      16. > RECENTLY_CHANGED_ITEM_EXPIRED_INTERVAL) {
      17. recentlyChangedQueue.pop();
      18. }
      19. }
      20. }
      21. Thread.sleep(RECENTLY_CHANGED_ITEM_CHECK_INTERVAL);
      22. } catch (InterruptedException e) {
      23. e.printStackTrace();
      24. }
      25. }
      26. }
      27. }
    3. 在注册和移除方法中,加上对服务实例变更操作的记录 ```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();
        }