Service是定义Hadoop中服务生命周期的一个接口。Service内部定义了服务的状态及生命周期,在服务被构造后,其一个生命周期内的状态为NOTINITED未初始化--INITED已初始化--已启动STARTED--已停止STOPPED,而这一生命周期内服务状态的变化,是随着如下方法链的调用而变化的:init()--start()--stop(),服务构造后整体方法调用及状态转移如下图所示:
下面,我们来看下Service的源码分析,先看下其内部定义的服务状态,如下:
/**
* Service states
* 服务状态
*/
public enum STATE {
/** Constructed but not initialized */
// 服务实例已经构造但是还没有初始化
NOTINITED(0, "NOTINITED"),
/** Initialized but not started or stopped */
// 服务实例已经初始化但还没有启动或停止
INITED(1, "INITED"),
/** started and not stopped */
// 服务实例已经启动但没有停止
STARTED(2, "STARTED"),
/** stopped. No further state transitions are permitted */
// 服务实例已经停止,不允许进一步的状态转换
STOPPED(3, "STOPPED");
/**
* An integer value for use in array lookup and JMX interfaces.
* Although {@link Enum#ordinal()} could do this, explicitly
* identify the numbers gives more stability guarantees over time.
*/
private final int value;
/**
* A name of the state that can be used in messages
*/
private final String statename;
private STATE(int value, String name) {
this.value = value;
this.statename = name;
}
/**
* Get the integer value of a state
* @return the numeric value of the state
*/
public int getValue() {
return value;
}
/**
* Get the name of a state
* @return the state's name
*/
@Override
public String toString() {
return statename;
}
}
STATE是一个枚举类,代表了服务生命周期内各阶段的状态,分别为:
1、NOTINITED--0:服务实例已经构造但是还没有初始化;
2、INITED--1:服务实例已经初始化但还没有启动或停止;
3、STARTED--2:服务实例已经启动但没有停止;
4、STOPPED--3:服务实例已经停止,不允许进一步的状态转换。
接下来,我们再看下导致服务状态变更的各个方法,如下:
1、初始化服务init(): NOTINITED-->INITED/STOPPED
/**
* Initialize the service.
* 初始化服务
*
* The transition MUST be from {@link STATE#NOTINITED} to {@link STATE#INITED}
* unless the operation failed and an exception was raised, in which case
* {@link #stop()} MUST be invoked and the service enter the state
* {@link STATE#STOPPED}.
*
* 初始化后,服务状态由NOTINITED转换到INITED,除非异常发生导致服务初始化操作失败,
* 在这种情况下,stop()方法应该被调用,并且服务状态进入STOPPED。
*
* @param config the configuration of the service
* @throws RuntimeException on any failure during the operation
初始化后,服务状态由NOTINITED转换到INITED,除非异常发生导致服务初始化操作失败,在这种情况下,stop()方法应该被调用,并且服务状态进入STOPPED。
2、启动服务start():INITED-->STARTED/STOPPED
/**
* Start the service.
* 启动服务
*
* The transition MUST be from {@link STATE#INITED} to {@link STATE#STARTED}
* unless the operation failed and an exception was raised, in which case
* {@link #stop()} MUST be invoked and the service enter the state
* {@link STATE#STOPPED}.
*
* 服务启动后,服务状态由INITED转换到STARTED,除非异常发生导致服务启动操作失败,
* 在这种情况下,stop()方法应该被调用,并且服务状态进入STOPPED。
*
* @throws RuntimeException on any failure during the operation
*/
服务启动后,服务状态由INITED转换到STARTED,除非异常发生导致服务启动操作失败,在这种情况下,stop()方法应该被调用,并且服务状态进入STOPPED。
3、停止服务stop():NOTINITED/INITED/STARTED-->STOPPED
/**
* Stop the service. This MUST be a no-op if the service is already
* in the {@link STATE#STOPPED} state. It SHOULD be a best-effort attempt
* to stop all parts of the service.
* 停止服务。如果服务已经处于STOPPED状态,这必须是一个空操作。它应该尽力试图停止服务的所有部分。
*
* The implementation must be designed to complete regardless of the service
* state, including the initialized/uninitialized state of all its internal
* fields.
* 实现者必须被设计为完成这个操作,而不管服务的状态,包括其内部所有字段初始化/未初始化的状态。
*
* @throws RuntimeException on any failure during the stop operation
*/
void stop();
停止服务。如果服务已经处于STOPPED状态,这必须是一个空操作。它应该尽力试图停止服务的所有部分。实现者必须被设计为完成这个操作,而不管服务的状态,包括其内部所有字段初始化/未初始化的状态。
为了兼顾Java7闭包条款,Service接口还提供了close()方法,实际上就是调用stop()方法,代码如下:
/**
* A version of stop() that is designed to be usable in Java7 closure
* clauses.
* 适用于Java7闭包条款的stop()版本,实际上就是调用stop()方法。
*
* Implementation classes MUST relay this directly to {@link #stop()}
* 实现类必须直接传递给stop()方法。
*
* @throws IOException never
* @throws RuntimeException on any failure during the stop operation
*/
void close() throws IOException;
Service的另外一大块内容,就是对于服务状态变更时间的监听,并提供了注册监听器与注销监听器的方法,如下:
1、注册监听器registerServiceListener()
/**
* Register a listener to the service state change events.
* If the supplied listener is already listening to this service,
* this method is a no-op.
* 注册一个监听器到服务状态变更事件。
* 如果提供的监听器已经监听此服务,这种方法是一个空操作。
* @param listener a new listener
*/
void registerServiceListener(ServiceStateChangeListener listener);
2、注销监听器unregisterServiceListener()
/**
* Unregister a previously registered listener of the service state
* change events. No-op if the listener is already unregistered.
* 注销之前的一个注册到服务状态变更事件的监听器。
* 如果监听器已经注销,这种方法是一个空操作。
* @param listener the listener to unregister.
*/
void unregisterServiceListener(ServiceStateChangeListener listener);
还有,Service还提供了获取服务失败时发生的第一个异常和当时状态的方法,如下:
/**
* Get the first exception raised during the service failure. If null,
* no exception was logged
* 获取服务失败时发生的第一个异常
* @return the failure logged during a transition to the stopped state
*/
Throwable getFailureCause();
/**
* Get the state in which the failure in {@link #getFailureCause()} occurred.
* 获取服务失败发生的第一个异常时的服务状态
* @return the state or null if there was no failure
*/
STATE getFailureState();
既然是一个服务,Service还提供了阻塞等待服务停止的waitForServiceToStop()方法,如下:
/**
* Block waiting for the service to stop; uses the termination notification
* object to do so.
* 阻塞,等待服务停止;通过终止通知对象实现。
*
* This method will only return after all the service stop actions
* have been executed (to success or failure), or the timeout elapsed
* This method can be called before the service is inited or started; this is
* to eliminate any race condition with the service stopping before
* this event occurs.
* @param timeout timeout in milliseconds. A value of zero means "forever"
* @return true iff the service stopped in the time period
*/
boolean waitForServiceToStop(long timeout);
其它诸如获取服务名、获取当前服务状态、获取服务启动时间、查询是否服务是在一个特定的状态、获取生命周期历史的一个快照、获取远程依赖服务的正在停止服务的阻塞者等方法不再一一介绍,读者可自行查询,下面只把代码贴出:
/**
* Get the name of this service.
* 获取服务名
* @return the service name
*/
String getName();
/**
* Get the configuration of this service.
* 获取服务的配置信息
* This is normally not a clone and may be manipulated, though there are no
* guarantees as to what the consequences of such actions may be
* @return the current configuration, unless a specific implentation chooses
* otherwise.
*/
Configuration getConfig();
/**
* Get the current service state
* 获取当前服务状态
* @return the state of the service
*/
STATE getServiceState();
/**
* Get the service start time
* 获取服务启动时间
* @return the start time of the service. This will be zero if the service
* has not yet been started.
*/
long getStartTime();
/**
* Query to see if the service is in a specific state.
* 查询是否服务是在一个特定的状态
* In a multi-threaded system, the state may not hold for very long.
* 在多线程系统中,服务状态可能不会保持很长时间。
* @param state the expected state
* @return true if, at the time of invocation, the service was in that state.
*/
boolean isInState(STATE state);
/**
* Get a snapshot of the lifecycle history; it is a static list
* 获取生命周期历史的一个快照,它是一个静态列表
* @return a possibly empty but never null list of lifecycle events.
*/
public List<LifecycleEvent> getLifecycleHistory();
/**
* Get the blockers on a service -remote dependencies
* that are stopping the service from being <i>live</i>.
*
* 获取远程依赖服务的正在停止服务的阻塞者
*
* @return a (snapshotted) map of blocker name->description values
*/
public Map<String, String> getBlockers();