Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

前面介绍过 Tomcat 的层次结构,

1
2
3
4
5
6
7
8
9
10
11
<Server>
<Service>
<Connector />
<Connector />
<Engine>
<Host>
<Context />
</Host>
</Engine>
</Service>
</Server>

参考这个 xml,而对于这些组件中,有一类有相同的基类,也就是这次要介绍的 ContainerBase,

包括 engine,host,context 还有 wrapper ,都是同样的容器组件,
而他们共同实现的接口就是 Container ,
主要包含了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static final String ADD_CHILD_EVENT = "addChild";


/**
* The ContainerEvent event type sent when a valve is added
* by <code>addValve()</code>, if this Container supports pipelines.
*/
public static final String ADD_VALVE_EVENT = "addValve";


/**
* The ContainerEvent event type sent when a child container is removed
* by <code>removeChild()</code>.
*/
public static final String REMOVE_CHILD_EVENT = "removeChild";


/**
* The ContainerEvent event type sent when a valve is removed
* by <code>removeValve()</code>, if this Container supports pipelines.
*/
public static final String REMOVE_VALVE_EVENT = "removeValve";

这几个事件类型,

1
2
3
4
5
6
7
8
9
10
11
12
13
public Pipeline getPipeline();

public Container getParent();

public void addChild(Container child);

public Container[] findChildren();

public int getStartStopThreads();

public void setStartStopThreads(int startStopThreads);


包括 pipeline 和获取 parent,添加 child 跟查找 child,然后设置线程池的线程数等
而对于 ContainerBase
也包含了 Lifecycle 的常规方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
protected void initInternal() throws LifecycleException {
reconfigureStartStopExecutor(getStartStopThreads());
super.initInternal();
}


private void reconfigureStartStopExecutor(int threads) {
if (threads == 1) {
// Use a fake executor
if (!(startStopExecutor instanceof InlineExecutorService)) {
startStopExecutor = new InlineExecutorService();
}
} else {
// Delegate utility execution to the Service
Server server = Container.getService(this).getServer();
server.setUtilityThreads(threads);
startStopExecutor = server.getUtilityExecutor();
}
}

初始化方法主要就是之前讲过的线程池
后面就开始 startInternal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Override
protected synchronized void startInternal() throws LifecycleException {

// Start our subordinate components, if any
logger = null;
getLogger();
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).start();
}
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).start();
}

// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
results.add(startStopExecutor.submit(new StartChild(child)));
}

MultiThrowable multiThrowable = null;

for (Future<Void> result : results) {
try {
result.get();
} catch (Throwable e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
if (multiThrowable == null) {
multiThrowable = new MultiThrowable();
}
multiThrowable.add(e);
}

}
if (multiThrowable != null) {
throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
multiThrowable.getThrowable());
}

// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}

setState(LifecycleState.STARTING);

// Start our thread
if (backgroundProcessorDelay > 0) {
monitorFuture = Container.getService(ContainerBase.this).getServer()
.getUtilityExecutor().scheduleWithFixedDelay(
new ContainerBackgroundProcessorMonitor(), 0, 60, TimeUnit.SECONDS);
}
}

这里包括了 cluster 的启动和 realm 的启动,然后将 child 子组件添加到线程池里启动,然后循环 get 结果,接下去就是 pipeline 的启动,设置开始中状态,后面是 ContainerBackgroundProcessor 的启动
然后是停止方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Override
protected synchronized void stopInternal() throws LifecycleException {

// Stop our thread
if (monitorFuture != null) {
monitorFuture.cancel(true);
monitorFuture = null;
}
threadStop();

setState(LifecycleState.STOPPING);

// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle &&
((Lifecycle) pipeline).getState().isAvailable()) {
((Lifecycle) pipeline).stop();
}

// Stop our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
results.add(startStopExecutor.submit(new StopChild(child)));
}

boolean fail = false;
for (Future<Void> result : results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStopFailed"), e);
fail = true;
}
}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStopFailed"));
}

// Stop our subordinate components, if any
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).stop();
}
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).stop();
}
}

也是类似的,只不过停止顺序和刚才开始的顺序反了一下

因为服务器续费即使是这次双十一还是太贵了,之前在 tx 买的三年 2c4g 3m 的一台服务器,原来价格是三年 800+,现在续费三年要 3700,因为之前还买了其他的服务器,所以感觉再这么贵地续一个有点不划算就考虑迁移了服务器
主要是分为四块内容,先大致记录下,后续会慢慢展开讲
第一部分就是 headscale 的迁移,本身 headscale 的部署其实还好,原来的服务器是因为权限搞得几个文件都有问题,这次就按着第一次已经修改好的文件进行部署就好了,问题不大,可以参考 Headscale初体验以及踩坑记 ,主要的一点是要考虑 derper 的部署,以及客户端认证逻辑
第二部分是 traefik 以及背后的 gitea,WordPress 的迁移,这个的部署方式都是使用 docker-compose 的,已经算比较方便了的,但是要注意两点,第一个是对于这些有状态的需要先停止 docker-compose ,然后在进行数据迁移,第二步数据迁移可能就需要使用到 docker 命令,执行 mysqldump

1
docker exec -it  mysql_server【docker容器名称/ID】 mysqldump -uroot -p123456【数据库密码】 test_db【数据库名称】 > /opt/sql_bak/test_db.sql【导出表格路径】

然后再在新的 mysql 容器中先 cp 到容器内,然后在 docker 内用 mysql 命令连接 mysql-server 以后用 source 将 sql 导进来
而像 traefik 本身其实是无状态的,只需要配置文件没有什么机器依赖就好,还有就是证书的更新,最后就是域名解析问题,修改解析就好
第三部分是 rustdesk 的迁移,这个其实就按官方文档来跑两个容器就好,hbbr 跟 hbbs 就好了,一个是 relay,一个是 id 服务器,不过这里有个问题我目前没看到怎么识别是否已经用到了这个,有种部署了但是不知道有没有用的尴尬,有知道的可以指导下
第四部分是 qinglong 的部署,这个也挺简单了,就是有个小问题,如果部署的订阅链接有 github 的就可以去站长的 ping 连接速度看看,自己配个 hosts 就会比较方便,不然经常容易拉不下来,还有就是要注意安全,至少要改强密码

线程池在 Tomcat 中也是非常重要的工具,这里我们简单介绍下 Tomcat 中的线程池,在 container 的启动过程中
org.apache.catalina.core.ContainerBase#initInternal

1
2
3
4
5
@Override
protected void initInternal() throws LifecycleException {
reconfigureStartStopExecutor(getStartStopThreads());
super.initInternal();
}

这里先会获取线程数,

1
2
3
4
@Override
public int getStartStopThreads() {
return startStopThreads;
}

默认的 ContainerBase 的设置线程数是 1

1
private int startStopThreads = 1;

那就会按照 org.apache.catalina.core.ContainerBase#reconfigureStartStopExecutor 来设置线程池类型

1
2
3
4
5
6
7
8
9
10
11
12
13
private void reconfigureStartStopExecutor(int threads) {
if (threads == 1) {
// Use a fake executor
if (!(startStopExecutor instanceof InlineExecutorService)) {
startStopExecutor = new InlineExecutorService();
}
} else {
// Delegate utility execution to the Service
Server server = Container.getService(this).getServer();
server.setUtilityThreads(threads);
startStopExecutor = server.getUtilityExecutor();
}
}

此时线程池类型是 null 也就会走到上一个分支中,new 一个 InlineExecutorService 出来
前面的这些其实是在 StandardEngine 初始化过程中,也就是 initInternal 时候进行的
然后具体的使用是在 startInternal 开始方法中,

1
2
3
4
5
6
// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
results.add(startStopExecutor.submit(new StartChild(child)));
}

会获取当前 StandardEngine 的子组件提交给线程池进行启动
而这个 StartChild 也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static class StartChild implements Callable<Void> {

private Container child;

public StartChild(Container child) {
this.child = child;
}

@Override
public Void call() throws LifecycleException {
child.start();
return null;
}
}

就是调用子组件的 start 方法,
在 org.apache.tomcat.util.threads.InlineExecutorService 的父类,java.util.concurrent.AbstractExecutorService 中先会把 Callable 包装成 FutureTask

1
2
3
4
5
6
7
8
9
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}

然后进行执行,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void execute(Runnable command) {
synchronized (lock) {
if (shutdown) {
throw new RejectedExecutionException();
}
taskRunning = true;
}
command.run();
synchronized (lock) {
taskRunning = false;
if (shutdown) {
terminated = true;
lock.notifyAll();
}
}
}

这个就是我们 startStopExecutor 的主要作用,帮我们启动子组件
对于 Container 来说启动的就是 host,而其实 host 也是继承了 ContainerBase 的,后面可以再继续介绍下


org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer 的时候会调用

1
this.webServer = factory.getWebServer(getSelfInitializer());

就会调用到之前说到的

1
2
3
4
5
6
7
8
9
10
11
12
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}

private void selfInitialize(ServletContext servletContext) throws ServletException {
prepareWebApplicationContext(servletContext);
registerApplicationScope(servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}

而这里有个
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#getServletContextInitializerBeans
获取初始化所需要的 bean

1
2
3
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
return new ServletContextInitializerBeans(getBeanFactory());
}

里面就是 new 了这个 org.springframework.boot.web.servlet.ServletContextInitializerBeans#ServletContextInitializerBeans

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public ServletContextInitializerBeans(ListableBeanFactory beanFactory,
Class<? extends ServletContextInitializer>... initializerTypes) {
this.initializers = new LinkedMultiValueMap<>();
this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes)
: Collections.singletonList(ServletContextInitializer.class);
// 这里是添加 ServletContextInitializer
addServletContextInitializerBeans(beanFactory);
// filter 是在这里
addAdaptableBeans(beanFactory);
List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
.flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
.collect(Collectors.toList());
this.sortedList = Collections.unmodifiableList(sortedInitializers);
logMappings(this.initializers);
}

具体来看看 org.springframework.boot.web.servlet.ServletContextInitializerBeans#addAdaptableBeans

1
2
3
4
5
6
7
8
9
10
11
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
// 这里把 Servlet 作为 RegistrationBean
addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
// 这里把 Filter 作为 RegistrationBean
addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,
new ServletListenerRegistrationBeanAdapter());
}
}

里面是这两段逻辑,先从 beanfactory 里获取到该类型的 bean,然后包装成 RegistrationBean,添加到 initializers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected <T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type,
RegistrationBeanAdapter<T> adapter) {
addAsRegistrationBean(beanFactory, type, type, adapter);
}

private <T, B extends T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type,
Class<B> beanType, RegistrationBeanAdapter<T> adapter) {
List<Map.Entry<String, B>> entries = getOrderedBeansOfType(beanFactory, beanType, this.seen);
for (Entry<String, B> entry : entries) {
String beanName = entry.getKey();
B bean = entry.getValue();
if (this.seen.add(bean)) {
// One that we haven't already seen
RegistrationBean registration = adapter.createRegistrationBean(beanName, bean, entries.size());
int order = getOrder(bean);
registration.setOrder(order);
this.initializers.add(type, registration);
if (logger.isTraceEnabled()) {
logger.trace("Created " + type.getSimpleName() + " initializer for bean '" + beanName + "'; order="
+ order + ", resource=" + getResourceDescription(beanName, beanFactory));
}
}
}
}

然后再回到第一段,其中的循环里面,因为 ServletContextInitializerBeans 继承了 AbstractCollection 并且实现了 iterator 接口

1
2
3
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}

在 for 循环中会把 Initializer 排序后的 sortedList 返回 iterator,也就是前面把 filter 包装成的 RegistrationBean

1
2
3
public Iterator<ServletContextInitializer> iterator() {
return this.sortedList.iterator();
}

然后调用了 onStartup 方法,

1
2
3
4
5
6
7
8
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
if (!isEnabled()) {
logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
return;
}
register(description, servletContext);
}

就会去执行注册逻辑

Tomcat 中的很多组件都是继承了LifecycleBase这个抽象类的,包括之前讲过的 connector,server,service,context,host 这些组件都是,我们先来看下接口
主体是分为两部分,第一部分是定义状态时间,如 before_init 和 after_init,跟事件监听器的几个方法,添加查询和移除,第二部分是生命周期的相关方法,初始化开始结束与销毁等方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public interface Lifecycle {



public static final String BEFORE_INIT_EVENT = "before_init";

public static final String AFTER_INIT_EVENT = "after_init";

public static final String START_EVENT = "start";

public static final String BEFORE_START_EVENT = "before_start";

public static final String AFTER_START_EVENT = "after_start";

public static final String STOP_EVENT = "stop";

public static final String BEFORE_STOP_EVENT = "before_stop";

public static final String AFTER_STOP_EVENT = "after_stop";

public static final String AFTER_DESTROY_EVENT = "after_destroy";

public static final String BEFORE_DESTROY_EVENT = "before_destroy";

public static final String PERIODIC_EVENT = "periodic";

public static final String CONFIGURE_START_EVENT = "configure_start";

public static final String CONFIGURE_STOP_EVENT = "configure_stop";

public void addLifecycleListener(LifecycleListener listener);

public LifecycleListener[] findLifecycleListeners();

public void removeLifecycleListener(LifecycleListener listener);

public void init() throws LifecycleException;

public void start() throws LifecycleException;

public void stop() throws LifecycleException;

public void destroy() throws LifecycleException;

public LifecycleState getState();

public String getStateName();


/**
* Marker interface used to indicate that the instance should only be used
* once. Calling {@link #stop()} on an instance that supports this interface
* will automatically call {@link #destroy()} after {@link #stop()}
* completes.
*/
public interface SingleUse {
}
}

对应的就是 Lifecycle 的状态,可以在 LifecycleState 中看到,这个枚举有两个字段组成,available 表示该状态下这个对应的组件状态是否可用,另一个就是对应的事件,比如 INITIALIZING 这个 state 对应的 BEFORE_INIT_EVENT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);

private final boolean available;
private final String lifecycleEvent;

private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}

/**
* May the public methods other than property getters/setters and lifecycle
* methods be called for a component in this state? It returns
* <code>true</code> for any component in any of the following states:
* <ul>
* <li>{@link #STARTING}</li>
* <li>{@link #STARTED}</li>
* <li>{@link #STOPPING_PREP}</li>
* </ul>
*
* @return <code>true</code> if the component is available for use,
* otherwise <code>false</code>
*/
public boolean isAvailable() {
return available;
}

public String getLifecycleEvent() {
return lifecycleEvent;
}
}

然后可以看看 Lifecycle 的状态流转示意,下面是从 Lifecycle 的代码注释里拷出来的

Common interface for component life cycle methods. Catalina components may implement this interface (as well as the appropriate interface(s) for the functionality they support) in order to provide a consistent mechanism to start and stop the component. The valid state transitions for components that support Lifecycle are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
           start()
-----------------------------
| |
| init() |
NEW -»-- INITIALIZING |
| | | | ------------------«-----------------------
| | |auto | | |
| | \|/ start() \|/ \|/ auto auto stop() |
| | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
| | | | |
| |destroy()| | |
| --»-----«-- ------------------------«-------------------------------- ^
| | | |
| | \|/ auto auto start() |
| | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
| \|/ ^ | ^
| | stop() | | |
| | -------------------------- | |
| | | | |
| | | destroy() destroy() | |
| | FAILED ----»------ DESTROYING ---«----------------- |
| | ^ | |
| | destroy() | |auto |
| --------»----------------- \|/ |
| DESTROYED |
| |
| stop() |
----»-----------------------------»------------------------------

Any state can transition to FAILED.

Calling start() while a component is in states STARTING_PREP, STARTING or
STARTED has no effect.

Calling start() while a component is in state NEW will cause init() to be
called immediately after the start() method is entered.

Calling stop() while a component is in states STOPPING_PREP, STOPPING or
STOPPED has no effect.

Calling stop() while a component is in state NEW transitions the component
to STOPPED. This is typically encountered when a component fails to start and
does not start all its sub-components. When the component is stopped, it will
try to stop all sub-components - even those it didn’t start.

Attempting any other transition will throw LifecycleException.

The LifecycleEvents fired during state changes are defined in the methods that trigger the changed. No LifecycleEvents are fired if the attempted transition is not valid.
好的项目就是会把这样的示意图画得很好,把状态流转都画得很明确,而不一定要什么好看的作图工具,用字符就可以
而在 LifecycleBase类中是把更细节的实现了,
init方法就是先判断了状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
// 只有状态是 new 才可以执行初始化 init
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}

try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}

在判断状态后就先设置了初始化中这个状态,这里设置的时候是 check 是 false 的,所以直接到设置状态,并且触发事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
throws LifecycleException {

if (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", this, state));
}

if (check) {
// Must have been triggered by one of the abstract methods (assume
// code in this class is correct)
// null is never a valid state
if (state == null) {
invalidTransition("null");
// Unreachable code - here to stop eclipse complaining about
// a possible NPE further down the method
return;
}

// Any method can transition to failed
// startInternal() permits STARTING_PREP to STARTING
// stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
// STOPPING
if (!(state == LifecycleState.FAILED ||
(this.state == LifecycleState.STARTING_PREP &&
state == LifecycleState.STARTING) ||
(this.state == LifecycleState.STOPPING_PREP &&
state == LifecycleState.STOPPING) ||
(this.state == LifecycleState.FAILED &&
state == LifecycleState.STOPPING))) {
// No other transition permitted
invalidTransition(state.name());
}
}

this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}

触发事件调用了 fireLifecycleEvent

1
2
3
4
5
6
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}

会调用所有的 listener 将事件发送出去
而回到上面 init 方法,第二步的 initInternal 就是 Tomcat 的 Lifecycle 中非常核心的一点了
因为上面说到很多组件都是继承了 LifecycleBase 的,实际外部被调用的其实都是 LifecycleBase 的
init,start 等方法,内部是由这个抽象基类去设置前后的状态,以及调用 initInternal ,也就是具体
实现类的实现方法,譬如 connector 的 initInternal 方法,就是真正处理初始化逻辑的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Override
protected void initInternal() throws LifecycleException {

super.initInternal();

if (protocolHandler == null) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
}

// Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
if (service != null) {
protocolHandler.setUtilityExecutor(service.getServer().getUtilityExecutor());
}

// Make sure parseBodyMethodsSet has a default
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}

if (protocolHandler.isAprRequired() && !AprStatus.isInstanceCreated()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
getProtocolHandlerClassName()));
}
if (protocolHandler.isAprRequired() && !AprStatus.isAprAvailable()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
getProtocolHandlerClassName()));
}
if (AprStatus.isAprAvailable() && AprStatus.getUseOpenSSL() &&
protocolHandler instanceof AbstractHttp11JsseProtocol) {
AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
(AbstractHttp11JsseProtocol<?>) protocolHandler;
if (jsseProtocolHandler.isSSLEnabled() &&
jsseProtocolHandler.getSslImplementationName() == null) {
// OpenSSL is compatible with the JSSE configuration, so use it if APR is available
jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
}
}

try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}

start 方法也是类似的,但是更复杂,第一步也是状态判断,是不是已经被启动过了,如果还是 new 状态的话就先调用 init,如果已经 failed 启动失败了就直接调用 stop 结束了,如果是非已初始化和非已停止的状态则是错误的状态转变
如果是正常情况,那就是先设置成 STARTING_PREP,然后调用实现类的 startInternal,如果启动失败了就调用 stop,此时理论上应该是启动中 STARTING 状态,否则就是异常状态转变,剩下的就是状态启动完的状态,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override
public final synchronized void start() throws LifecycleException {

if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {

if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}

return;
}

if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}

try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
handleSubClassException(t, "lifecycleBase.startFail", toString());
}
}

stop 跟 destroy 也类似的

0%