• Guava源码分析——ServiceManager


    ServiceManager类:

         用于监控服务集的管理器,该类提供了诸如startAsync、stopAsync、servicesByState方法来运行、结束和检查服务集,而且,通过监听器机制还能监控状态的改变。
         建议通过此类来管理服务的生命周期,状态转变则通过其它机制来执行。例如,如果服务集通过除startAsync之外的某些机制启动,那么监听器将在合适的时候被唤醒,同时awaitHealthy 也仍将按预期工作。
          
     
     
    服务生命周期State
    NEW
    服务在这个状态下是不活跃的,它的作用和消耗的资源都非常小
    STARTING
    服务在这个状态过渡到RUNNING
    RUNNING
    服务在这个状态下运作
    STOPPING
    服务在这个状态过渡到RUNNING
    TERMINATED
    服务在这个状态下,说明已正常执行
    FAILED
    服务遇到问题,已无法启动或终止
     
     
    ServiceManager主要方法
    void addListener(Listener listener, Executor executor)
    在executor上注册一个监听器
    ServiceManager startAsync()
    启动所有被管理的服务,只有当所有服务的状态为NEW时,调用此方法才不会抛异常
    void awaitHealthy()
    等待服务管理器变得healthy(所有服务的状态都为RUNNING )
    void awaitHealthy(long timeout, TimeUnit unit)
    在一定时间内,等待服务管理器变得healthy(所有服务的状态都为RUNNING )
    ServiceManager stopAsync()
    stop()所有管理的服务

    void awaitStopped()等待所有服务都到达终止状态(所有服务的状态应该为TERMINATED或FAILED)

    void awaitStopped(long timeout, TimeUnit unit)
    在一定时间内,等待所有服务都到达终止状态
    boolean isHealthy()

    如果所有服务的状态为RUNNING,则返回true

    ImmutableMultimap<State, Service> servicesByState()

    获取所有服务的当前状态的快照

    ImmutableMap<Service, Long> startupTimes()

    返回完成启动的服务的加载时间

     
     
    ServiceManager的构建——
        1)创建一个ServiceManagerState;
        2)创建一个Executor ;
        3)根据每一个Service及ServiceManagerState创建相应的ServiceListener;
        4)将每一个ServiceListener注册到Executor 上,此时会调用到每个Service的addListener方法;
        5)为services 添加Service与ServiceListener的键值对。
     
    几个主要函数:
      启动所有服务:
      public ServiceManager startAsync() {
        //验证所有服务的初始状态是否为NEW。
        for (Map.Entry<Service, ServiceListener> entry : services.entrySet()) {
          Service service = entry.getKey();
          State state = service.state();
          checkState(state == State.NEW, "Service %s is %s, cannot start it.", service, 
              state);
        }
        //执行所有服务的start方法。
        for (ServiceListener service : services.values()) {
          service.start();
        }
        return this;
      }
      终止所有服务:
      public ServiceManager stopAsync() {
        for (Service service : services.keySet()) {
          service.stop();
        }
        return this;
      }
    在重写start方法时,可以做一些初始化工作,返回结果为ListenableFuture<State>,调用其get方法时,将在该服务启动后,获得其状态变量(RUNNING,STOPPING或TERMINATED),如果服务启动失败,get方法将抛出ExecutionException异常,同时服务状态将为FAILED。
    在重写stop方法时,返回结果也为ListenableFuture<State>,调用其get方法时,将在该服务结束后,获得其状态变量TERMINATED或抛出ExecutionException异常。
     
     
     
    ServiceManagerState类——ServiceManager的所有可变状态的封装体。
     
             
    ServiceManagerState主要方法
    void serviceFinishedStarting(Service service, boolean currentlyHealthy)
    在服务完成启动时调用
    void serviceTerminated(Service service)
    在服务TERMINATED时调用
    void serviceFailed(final Service service)
    在服务FAILED时调用
    void serviceStopped(Service service)
    在服务TERMINATED或FAILED时调用
    void executeListeners()
    执行queuedListeners中所有的监听器
    void addListener(Listener listener, Executor executor)
    同上
    void awaitHealthy()
    同上
    boolean awaitHealthy(long timeout, TimeUnit unit)
    同上
    void awaitStopped()
    同上
    boolean awaitStopped(long timeout, TimeUnit unit)
    同上
     
    ServiceManager中的方式实际调用的即为以上方法。
     
     主要成员变量:
    1)记录了服务总数(numberOfServices),未启动服务数(unstartedServices)及未终止服务数(unstoppedServices),初始值都为服务总数。
    这些状态的作用体现在两个地方:
    ① 等待所有服务处于健康状态,涉及的条件awaitHealthGuard为:所有服务都已经启动 或 部分服务已终止。
                该条件应用在,等待所有服务处于健康状态的主体函数中:
              public void awaitHealthy() {
                        state.awaitHealthy();
                        checkState(isHealthy(), "Expected to be healthy after starting");
                  }
            主要分两部分:
            首先在state.awaitHealthy()中,通过下面函数,等待所有服务都启动
             private void waitUninterruptibly(Guard guard, boolean signalBeforeWaiting) {
                 //所有服务都已启动 或 部分服务已终止,则直接返回,无需等待;
                  if (!guard.isSatisfied()) {
                      if (signalBeforeWaiting) {
                            signalConditionsOfSatisfiedGuards(null);
                      }
                      incrementWaiters(guard);
                      try {
                            final Condition condition = guard.condition;
                            do {
                                  condition.awaitUninterruptibly();
                            } while (!guard.isSatisfied());//若存在未启动的服务,且没有全部终止,则继续等待;
                      } finally {
                            decrementWaiters(guard);
                      }
                }
          }
                  接着通过isHealthy()函数,判断所有服务处在RUNNING状态。

     ② 判断所有服务是否处于终止状态,需要满足的条件stoppedGuard即为:未终止服务数等于0。

    2)Queue<Runnable> queuedListeners队列保存等待执行的监听器,调用executeListeners()时,会依次将队列中的所有方法执行并移除。
     
    3)List<ListenerExecutorPair> listeners 保存了在状态转变时,需要通知的监听器,应用:
                ① serviceStopped方法被调用时,unstoppedServices减一,添加listeners中的所有监听器的stopped方法至queuedListeners队列。
                ② serviceTerminated方法被调用时,实际调用serviceStopped方法。
                ③ serviceFailed方法被调用时,添加listeners中的所有监听器的failure方法至queuedListeners队列,并调用serviceStopped方法。
                ④ serviceFinishedStarting方法被调用时,unstartedServices减1,如果参数currentlyHealthy为真,且所有服务都已启动且没终止,添加listeners中的所有监听器的 healthy方法至queuedListeners队列。
    添加方法都如下:
             for (final ListenerExecutorPair pair : listeners) {
              queuedListeners.add(new Runnable() {
                @Override public void run() {
                  pair.execute(new Runnable() {
                    @Override public void run() {
                      pair.listener.stopped();
                    }
                  });
                }
              });
            }
      
     
    ServiceListener类:

    封装了另一种服务及其启动时间,同时会根据当前状态调用ServiceManagerState的serviceFinishedStarting ,serviceTerminated ,serviceFailed 方法。

     
     
    DEMO:
    下面从终止服务为例,说下Service及ServiceManager的监听器,也不知道自己这样用对不对....
    我们可以在实现Service接口的类中,重写addListener方法,该方法将在构造服务管理器时,被调用:
    调用处:
    ServiceListener listener = new ServiceListener(service, state);
           service. addListener(listener, executor);
     
    重写的addListener方法:
        @Override
          public void addListener(Listener listener, Executor executor) {
               this.listener =   listener;
               System.out.println(serviceInfo+"注册监听器");
          }
     
    接着重写stop方法,当服务管理器执行stopAsync() 方法时,将依次执行每个服务的stop方法:
        @Override
        public ListenableFuture<State> stop() {
              listener. terminated(state);
            System.out.println(serviceInfo + "终止...");
            return null;
        }
     
    此处我们调用listener的terminated方法:
         @Override public void terminated(State from) {
              logger.info("Service " + service + " has terminated. Previous state was " + from + " state.");
              state.monitor.enter();
              try {
                    if (from == State.NEW) {
                          startTimer();
                          finishedStarting(false);
                    }
                    state.serviceTerminated(service);
              } finally {
                    state.monitor.leave();
                    state.executeListeners();
              }
        }
     
    serviceTerminated方法实际调用的为serviceStopped方法,在该方法中将unstoppedServices(未终止服务数)减一,若所有服务都已终止,则将listeners中所有监听器的stopped方法加入queuedListeners队列中稍后执行。
         private void serviceStopped(Service service) {
              checkState(unstoppedServices > 0, "All services should have already stopped but %s just stopped.", service);
              unstoppedServices--;
              if (unstoppedServices == 0) {
                    checkState(unstartedServices == 0, "All services are stopped but %d services haven't finished starting",  unstartedServices);
                    for (final   ListenerExecutorPair pair : listeners) {
                          queuedListeners.add(new Runnable() {
                                @Override public void run() {
                                        pair.execute(new Runnable() {
                                            @Override public void run() {
                                                  pair.listener.stopped();
                                            }
                                      });
                                }
                          });
                        }
                  listeners.clear();
              }
        }
     
    listeners中的监听器,是通过服务管理器的addListener方法(Service也有addListener方法)添加的,在该方法中会将监听器添加到listeners队列中,当服务状态发生改变时,通知队列中的监听器。
    这些监听器除了有stopped方法,还有healthy及failure方法,通过这几个方法,我们可以监视所有服务的运行状态,在下面的例子中,我们可以看到运行结果中出现"服务运行结束!"字样,说明已检测到所有服务都运行结束。
     
    ServiceImp实现类:
    public class ServiceImp implements Service {
        private State state = NEW;
        private String serviceInfo;
        private Listener listener;
     
        ServiceImp(int num){
            this.serviceInfo = "第"+num+"个任务:";
        }
        @Override
        public ListenableFuture<State> start() {
            System.out.println(serviceInfo+"启动...");
            listener.starting();
            return null;
        }
        @Override
        public State startAndWait() {
            return state;
        }
        @Override
        public boolean isRunning() {
            if(state== RUNNING)
                return true;
            else
                return false;
        }
        @Override
        public State state() {
            return state;
        }
        @Override
        public ListenableFuture<State> stop() {
            listener. terminated(state);
            System.out.println(serviceInfo + "终止...");
            return null;
        }
        @Override
        public State stopAndWait() {
            return state;
        }
        @Override
        public Throwable failureCause() {
            return null;
        }
        @Override
        public void addListener(Listener listener, Executor executor) {
            this.listener =   listener;
            System.out.println(serviceInfo+"注册监听器");
        }
    }

    运行服务:
    public class Server {
        public static void main(String[] args) {
            List<Service> services = Lists.newArrayList();
            for (int num = 0; num < 5; num++) {
                ServiceImp serviceImp = new ServiceImp(num);
                services.add(serviceImp);
            }
            System.out.println("*******构造服务管理器*******");
     
            final ServiceManager serviceManager = new ServiceManager(services);
            serviceManager. addListener(new ServiceManager.Listener() {
                @Override
                public void healthy() {
                    System.out.println("服务运行健康!");
                }
                @Override
                public void stopped() {
                    System.out.println("服务运行结束!");
                }
                @Override
                public void failure(Service service) {
                    System.out.println("服务运行失败!");
                }
            }, MoreExecutors.sameThreadExecutor());
     
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        System.out.println("********终止所有任务********");
                        serviceManager.stopAsync().awaitStopped(10, TimeUnit.SECONDS);
                    } catch (Exception timeout) {
                        System.out.println("timeout");
                    }
                }
            });
     
            System.out.println("********启动所有任务********");
            serviceManager.startAsync();
     
        }
    }

    运行结果:
    *******构造服务管理器*******
    第0个任务:注册监听器
    第1个任务:注册监听器
    第2个任务:注册监听器
    第3个任务:注册监听器
    第4个任务:注册监听器
    ********启动所有任务********
    第0个任务:启动...
    第1个任务:启动...
    第2个任务:启动...
    第3个任务:启动...
    第4个任务:启动...
    ********终止所有任务********
    第0个任务:终止...
    第1个任务:终止...
    第2个任务:终止...
    第3个任务:终止...
    服务运行终止!
    第4个任务:终止...
  • 相关阅读:
    什么是基于注解的容器配置?
    一个线程运行时发生异常会怎样?
    Java 中你怎样唤醒一个阻塞的线程?
    为什么 wait, notify 和 notifyAll 这些方法不在 thread 类里面?
    Java 中 notify 和 notifyAll 有什么区别?
    在 Spring MVC 应用程序中使用 WebMvcTest 注释有什么用处?
    java 中有几种方法可以实现一个线程?
    什么是AOP?
    什么是竞争条件?你怎样发现和解决竞争?
    Mybatis 是如何进行分页的?分页插件的原理是什么?
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3341613.html
Copyright © 2020-2023  润新知