Guava Service框架和tomcat Lifecycle比较
Healthy Mind Lv3

Guava从 15就开始支持,服务启动关闭的等服务生命周期管理的 脚手架 Service、ServiceManager类

​ 整个框架结构图:

​ 关于这个模块和tomcat 里的各个服务的组件的抽象 Lifecycle、LifecycleListener 很类似,不过在tomcat 中没有 ServiceManager类做统一管理

​ 如果需要做Java 应用服务,可以使用 Guava Service相关抽象进行编码。

​ 平时使用 继承 AbstractIdleService 类即可 代码示例:

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
package com.trs.guava;

import com.google.common.base.Throwables;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Service;

/**
* @Description
* @DATE 2021.5.10 15:45
* @Author yangjie
**/

public class GuavaServiceTest {

public static void main(String[] args) {
Service bootstrap = new GuavaBootstrap();
// Service bootstrap = new AbcBootstrap();
try {
bootstrap.startAsync();
} catch (Exception e) {
e.printStackTrace();
Throwables.throwIfUnchecked(e);
}
bootstrap.addListener(new Service.Listener() {
@Override
public void starting() {
System.out.println("启动服务");
}

@Override
public void running() {
System.out.println("运行服务");
}

@Override
public void stopping(Service.State from) {
System.out.println("停止服务");
}

@Override
public void terminated(Service.State from) {
super.terminated(from);
}

@Override
public void failed(Service.State from, Throwable failure) {
super.failed(from, failure);
}
}, MoreExecutors.directExecutor());
}
}

这里的 Listener 可以添加多个,最好写在服务启动之前,在服务启动之前可以做 连接池的初始化,环境,参数校验等工作,在停止服务后,拒绝新的请求或者任务处理。,当然也可像 tomcat 对 Connector 连接器复杂的组件 进行 组件化抽象。

在tomcat 中 ServiceManager 是不存在这个类的,tomcat 是以数组的方式进行多个组件一键启动的在类

org.apache.catalina.core.StandardService的方法

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
@Override
protected void startInternal() throws LifecycleException {

if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);

// Start our defined Container first
if (engine != null) {
synchronized (engine) {
engine.start();
}
}

synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}

mapperListener.start();

// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}

在Guava中我们可以直接使用 类 com.google.common.util.concurrent.ServiceManager 的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@CanIgnoreReturnValue
public ServiceManager startAsync() {
for (Service service : services) {
State state = service.state();
checkState(state == NEW, "Service %s is %s, cannot start it.", service, state);
}
for (Service service : services) {
try {
state.tryStartTiming(service);
service.startAsync();
} catch (IllegalStateException e) {
// This can happen if the service has already been started or stopped (e.g. by another
// service or listener). Our contract says it is safe to call this method if
// all services were NEW when it was called, and this has already been verified above, so we
// don't propagate the exception.
logger.log(Level.WARNING, "Unable to start Service " + service, e);
}
}
return this;
}