文章目录

0.前记

在之前的文章中, ​​Tomcat​​​启动过程, 通过​​Bootstrap.main​​​方法中, 先获取到3种类加载器, 然后通过​​digester​​​加载​​server.xml​​文件, 然后初始化服务器端的各个组件。

这一篇文章介绍初始化后然后​​Tomcat​​启动的过程。

​Bootstrap.main()​

Tomcat 源码分析 (Tomcat的启动过程) (三)_tomcat

1.通过Catalina.start()启动服务器

Tomcat 源码分析 (Tomcat的启动过程) (三)_单线程_02


通过反射调用​​Catalina.start()​

Tomcat 源码分析 (Tomcat的启动过程) (三)_单线程_03

​LifecycleBase.start()​

Tomcat 源码分析 (Tomcat的启动过程) (三)_单线程_04

  1. 通过组件的状态进行判断, 为状态模式
  2. 留给子类一个扩展的接口​​startInternal​

2.各个组件的启动流程

Tomcat 源码分析 (Tomcat的启动过程) (三)_java_05

​StandardServer.startInternal()​

@Override
protected void startInternal() throws LifecycleException {

fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);

globalNamingResources.start(); // 启动JNDI服务

//启动所有service Start our defined Services
synchronized (servicesLock) {
for (Service service : services) {
service.start(); //启动所有的Service
}
}

if (periodicEventDelay > 0) {
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
() -> startPeriodicLifecycleEvent(), 0, 60, TimeUnit.SECONDS);
}
}

  1. 先是​​globalNamingResources​​开启, 开启JNDI服务
  2. 启动所有是​​service​​服务

​StandardService.startInternal()​

@Override
protected void startInternal() throws LifecycleException {

// Start our defined Container first
if (engine != null) {
synchronized (engine) {
engine.start(); //启动引擎,部署项目
}
}

// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
}
}
}

  1. 开启​​engine​
  2. 开启​​connector​

2.1 开启Engine

​StandardEngine.startInternal()​

@Override //模板方法的实现,定义引擎的启动方法
protected synchronized void startInternal() throws LifecycleException {
// Standard container startup
super.startInternal();
}

​ContainerBase.startInternal()​

@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);
}

}

//启动管道 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);
}
}

  1. 启动集群组件
  2. 启动realm组件
  3. 将虚拟主机Host封装为​​StartChild​​, 这个是一个Callback, 交给了线程池执行。
  4. 启动自己的​​pipline​​管道

2.2 开启Connector

​Connector.startInternal()​

@Override  //连接器启动
protected void startInternal() throws LifecycleException {

// Validate settings before starting
// Connector创建对象的无参构造器默认就指定了使用http11protocolHandler
String id = (protocolHandler != null) ? protocolHandler.getId() : null;
if (id == null && getPortWithOffset() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));
}

setState(LifecycleState.STARTING);

try {
protocolHandler.start(); //协议处理器启动
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}

  1. ​Connector​​​创建对象的无参构造器默认就指定了使用​​http11protocolHandler​
  2. 开启协议处理器​​protocolHandler​

Tomcat 源码分析 (Tomcat的启动过程) (三)_java_06

​AbstractProticol.start()​

@Override
public void start() throws Exception {
if (getLog().isInfoEnabled()) {
getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
logPortOffset();
}

endpoint.start(); //端点启动
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
() -> {
if (!isPaused()) {
startAsyncTimeout();
}
}, 0, 60, TimeUnit.SECONDS);
}

  • 端点启动

​AbstractEndPoint,start()​

Tomcat 源码分析 (Tomcat的启动过程) (三)_开发语言_07

​NioEndpoint.startInternal()​

@Override
public void startInternal() throws Exception {

if (!running) { //开始启动端点
running = true;
paused = false;

if (socketProperties.getProcessorCache() != 0) {
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
}
if (socketProperties.getEventCache() != 0) {
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
}
if (socketProperties.getBufferPool() != 0) {
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
}

//创建worker线程组(干活的人) Create worker collection
if (getExecutor() == null) {
createExecutor(); //默认worker线程池10个线程等待处理
}

initializeConnectionLatch(); //连接限流的,最大处理8192条连接

// 单线程启动poller
//启动一个poller;拉取者?????? Start poller thread
poller = new Poller();
Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
//启动接受者线程
// 单线程启动Accepter 8080
startAcceptorThread();
}
}

Tomcat 源码分析 (Tomcat的启动过程) (三)_开发语言_08

  1. 启动worker线程池, 默认为10个
  2. 单线程启动Poller
  3. 单线程准备一个Acceptor: 通过ServerSocket.accept 一直接受数据

3.Cataliona.await()方法等待数据

Tomcat 源码分析 (Tomcat的启动过程) (三)_ide_09

​StandardServer.await()​

Tomcat 源码分析 (Tomcat的启动过程) (三)_tomcat_10

与底层的​​jdk​​​的​​serverSocket​​​建立了关系, 通过​​accpet​​接收数据