tomcat启动(六)Catalina分析-StandardServer.start()
从链接
Tomcat中组件的生命周期管理公共接口Lifecycle
可以知道调用的是StandardServer.startInternal()
@Override
protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
1、首先用fireLifecycleEvent()方法发送CONFIGURE_START_EVENT=“config_start”事件
这个事件会被NamingContextListener监听器接收,会为StandardServer的属性globalNamingResources设置监听器为this当前类NamingContextListener
然后生成一个NamingContext命名上下文对象(这个上下文对象联系着JNDI Context)
为StandardServer设置private javax.naming.Context globalNamingContext的值
2、
globalNamingResources.start();这里也发送的一个CONFIGURE_START_EVENT=“config_start”事件
设置状态为starting
/**
* Holds and manages the naming resources defined in the J2EE Enterprise
* Naming Context and their associated JNDI context.
*保存并管理J2EE企业命名上下文中定义的命名资源及其关联的JNDI上下文
* @author Remy Maucherat
*/
public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializable, NamingResources
3、services[i].start();
这里调用StandardService.startInternal()
/**
* Start nested components ({@link Executor}s, {@link Connector}s and
* {@link Container}s) and implement the requirements of
* {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*启动嵌套组件StandardThreadExecutor,Connector和StandardEngine
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@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 (container != null) {
synchronized (container) {
container.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);
}
}
}
}
1、container.start();
调用的是StandardEngine.startInternal()
2、executor.start();
执行提交的Runnable任务的对象。这个接口提供了一种将任务提交与每个任务如何运行的机制解耦的方法,包括线程使用的细节,调度等。通常使用Executor而不是显式地创建线程。
StandardThreadExecutor:线程执行类。可以看做线程池对象
3、mapperListener.start();
调用MapperListener.startInternal()
用一个变量Mapper mapper持有Host,为StandardEngine和其子Container设置监听器为当前类MapperListener
4、connector.start();
调用Connector。startInternal()
/**
* Begin processing requests via this Connector.
*开始处理请求
* @exception LifecycleException if a fatal startup error occurs
*/
@Override
protected void startInternal() throws LifecycleException { // Validate settings before starting
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
} setState(LifecycleState.STARTING); try {
protocolHandler.start();
} catch (Exception e) {
String errPrefix = "";
if(this.service != null) {
errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
} throw new LifecycleException
(errPrefix + " " + sm.getString
("coyoteConnector.protocolHandlerStartFailed"), e);
}
}
protocolHandler.start()
这里默认调用的是Http11NioProtocol。start()
先调用构造方法
public Http11NioProtocol() {
endpoint=new NioEndpoint();
cHandler = new Http11ConnectionHandler(this);
((NioEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}

public abstract class AbstractProtocol<S> implements ProtocolHandler,MBeanRegistration
@Override
public void start() throws Exception {
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.start",
getName()));
try {
endpoint.start();
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.startError",
getName()), ex);
throw ex;
}
}
endpoint.start()===>调用的是NioEndpoint.startInternal()
/**
* Start the NIO endpoint, creating acceptor, poller threads.启动端点,创建接收器,轮询线程
*/
@Override
public void startInternal() throws Exception { if (!running) {
running = true;
paused = false; processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool()); // Create worker collection
if ( getExecutor() == null ) {
createExecutor();
} initializeConnectionLatch(); // Start poller threads
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
} startAcceptorThreads();
}
}
上面
1、
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
设置处理器缓存大小:用SynchronizedStack这种LIFO(后进先出)队列存储。默认大小为128,默认处理器缓存最大限制是500。-1是无限制。
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
设置事件缓存大小:默认大小为128,默认事件缓存最大限制是500。-1是无限制。
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
Bytebuffer cache, each channel holds a set of buffers (two, except for SSL holds four)字节缓冲区缓存,每个通道都包含一组缓冲区(两个,SSL除外)
设置通道缓存大小:默认大小为128,默认通道缓存最大限制是500。-1是无限制。
2、
initializeConnectionLatch();初始化LimintLatch connectionLimitLatch变量。这个变量用来统计endpoint处理的连接数,并限制最大连接数
通过使用LimintLatch这个类实现限制最大socket连接数
tomcat默认的最大连接数位10000
/**
* Shared latch that allows the latch to be acquired a limited number of times
* after which all subsequent requests to acquire the latch will be placed in a
* FIFO queue until one of the shares is returned.
*/
共享锁存器允许获取有限次数的锁存器,之后,所有后续获取锁存器的请求将被置于FIFO队列中,直到其中一个共享被返回。
public class LimitLatch
3、Start poller threads启动轮询线程。线程数通过Math.min(2,Runtime.getRuntime().availableProcessors());这个方法获取最小的处理器数量,使用min方法找到最小值
4startAcceptorThreads启动接收器线程。后台线程监听传入的TCP / IP连接,并将其交给适当的处理器。
这里试着描绘大概流程
startAcceptorThreads()方法会创建Acceptor线程对象
开启线程,循环等待ServerSocket.accept()方法接收到新的连接。然后会将这个socket注册到Poller这个轮询线程。生成一个KeyAttachment对象与socket相关联(后面会用到)
由第3步已经开启的轮询线程,当这个socket发送请求时,Poller线程就收到连接请求后会将
调用NioEndpoint.processSocket(KeyAttachment attachment, SocketStatus status, boolean dispatch)方法,这个方法会开启内部类NioEndpoint.SocketProcessor线程的run()方法
其内部执行调用NioEndpoint.Handler.process(SocketWrapper<NioChannel> socket, SocketStatus status)。---调用的是子类AbstractProtocol.AbstractConnectionHandler.process()
。。。省略一大堆复杂调用。。。。。
最后会调用Http11NioProcessor.process(SocketWrapper<S> socketWrapper)方法中调用CoyoteAdapter.service(request, response);将请求传递到context中。
剩余换一章分析。
到这里tomcat就启动完成了。调用线程等待客户端连接。。。
tomcat启动(六)Catalina分析-StandardServer.start()的更多相关文章
- tomcat启动(三)Catalina分析-load方法分析
load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...
- tomcat启动(五)Catalina分析-service.init
上篇写到StandardService.init() 这个方法做什么呢?一起来看看. 这个类也是实现了Lifecycle 如图.这个图中i表示Interface接口.如Lifecycle,Contai ...
- tomcat启动(四)Catalina分析-server的init()方法
上一回load()方法解析讲到xml解析完成. load()内部接下来会获取server getServer().setCatalina(this); 这个server从createStartDige ...
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- Tomcat启动报错:严重: StandardServer.await: create[8005] java.net.BindException: Cannot assign requested address
org.apache.catalina.core.StandardServer await SEVERE: StandardServer.await: create[8005]: ...
- tomcat启动(三)Catalina简要分析
上篇解析Bootstrap到 daemon.setAwait(true); daemon.load(args); daemon.start(); 这三个方法实际是反射调用org.apache.cata ...
- tomcat启动批处理——catalina.bat
这个批处理才是tomcat服务器启动跟关闭的核心脚本.其中包括....(各种变量),此节将详细讲解这个批处理的逻辑. 先看看第一部分脚本: ****************************** ...
- Tomcat启动脚本catalina.sh
1 - 概述脚本catalina.sh用于启动和关闭tomcat服务器,是最关键的脚本另外的脚本startup.sh和shutdown.sh都是使用不同的参数调用了该脚本该脚本的使用方法如下(引自该脚 ...
- ubuntu下tomcat启动巨慢分析
在一个ubuntu14新环境部署tomcat,通过CI启动一个应用时,启动耗时达到15分钟之久.仔细看tomcat输出的耗时统计日志发现如下日志: Creation of SecureRandom i ...
随机推荐
- HDU1459 非常可乐(BFS) 2016-07-24 15:00 165人阅读 评论(0) 收藏
非常可乐 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶 ...
- python 的几种启动方式
python 的几种启动方式 (1)利用Win的操作系统的:命令行工具 cmd.exe Win + R 调出运行对话框,然后输入cmd,即可调出“命令提示符对话框” 或者 在菜单中店家附件中的命令提 ...
- 老刘 Yii2 源码学习笔记之 Module 类
关系类图 从上图可以看出 Application 类继承了 Module,在框架中的是非常重要角色. 加载配置 public function setModules($modules) { forea ...
- N个不同球取出M个的组合个数求解
Technorati 标签: 组合,概率 从N个不同的球中取出M个,一共有多少种取法? 这个问题是组合数据的基本问题,考虑拿出球是否放回,拿出去的球是否有序,它有4种变体: 不放回,有序: 不放回,无 ...
- TransactionScope事务使用
using (System.Transactions.TransactionScope T_Scope = new System.Transactions.TransactionScope()) { ...
- ASP.NET Core 装X利器SignalR:电子画板
电子画板开发需求 教师端需求: 教师登录后能创建房间(教室) 学生加入房间后有通知提醒 教师能够解散房间 基本的画板功能 学生端需求: 能够切换不同在线的房间 能够收到新建房间的通知 能够收到房间 ...
- 关于win10 链接安卓设备报错winusb.sys未经签名的解决办法
很简单,各位,我找了一个签过名的winusb.sys替换原来的文件即可. 操作系统win10 64位专业版(更新到最新版本了) 网盘地址 安装好以后,就没有那个惊叹号咯!
- 文本比较算法Ⅱ——Needleman/Wunsch算法的C++实现【求最长公共子串(不需要连续)】
算法见:http://www.cnblogs.com/grenet/archive/2010/06/03/1750454.html 求最长公共子串(不需要连续) #include <stdio. ...
- Java基础学习篇---------static
一.static的使用 1.使用static定义的属性往往通过类名直接调用,它的属性(方法)不属于某一个的对象的.所以对象没有创建之前就可以对static的属性的调用,方法亦如此. 2.static ...
- 【文文殿下】ExBSGS
无需逆元版本: #include<cstdio> #include<cassert> #include<cmath> #include<map> typ ...