从链接

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

AbstractProtocol.start()

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()的更多相关文章

  1. tomcat启动(三)Catalina分析-load方法分析

    load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...

  2. tomcat启动(五)Catalina分析-service.init

    上篇写到StandardService.init() 这个方法做什么呢?一起来看看. 这个类也是实现了Lifecycle 如图.这个图中i表示Interface接口.如Lifecycle,Contai ...

  3. tomcat启动(四)Catalina分析-server的init()方法

    上一回load()方法解析讲到xml解析完成. load()内部接下来会获取server getServer().setCatalina(this); 这个server从createStartDige ...

  4. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  5. Tomcat启动报错:严重: StandardServer.await: create[8005] java.net.BindException: Cannot assign requested address

    org.apache.catalina.core.StandardServer await        SEVERE: StandardServer.await: create[8005]:    ...

  6. tomcat启动(三)Catalina简要分析

    上篇解析Bootstrap到 daemon.setAwait(true); daemon.load(args); daemon.start(); 这三个方法实际是反射调用org.apache.cata ...

  7. tomcat启动批处理——catalina.bat

    这个批处理才是tomcat服务器启动跟关闭的核心脚本.其中包括....(各种变量),此节将详细讲解这个批处理的逻辑. 先看看第一部分脚本: ****************************** ...

  8. Tomcat启动脚本catalina.sh

    1 - 概述脚本catalina.sh用于启动和关闭tomcat服务器,是最关键的脚本另外的脚本startup.sh和shutdown.sh都是使用不同的参数调用了该脚本该脚本的使用方法如下(引自该脚 ...

  9. ubuntu下tomcat启动巨慢分析

    在一个ubuntu14新环境部署tomcat,通过CI启动一个应用时,启动耗时达到15分钟之久.仔细看tomcat输出的耗时统计日志发现如下日志: Creation of SecureRandom i ...

随机推荐

  1. VC++ 定制应用程序的外观

    一.在窗口创建之前改变窗口的大小和标题 要改变应用程序窗口的大小可以通过在PreCreatWindowl函数中修改CREATSTRUCT结构体变量成员的值 BOOL CMainFrame::PreCr ...

  2. 基于MATLAB的均值滤波算法实现

    在图像采集和生成中会不可避免的引入噪声,图像噪声是指存在于图像数据中的不必要的或多余的干扰信息,这对我们对图像信息的提取造成干扰,所以要进行去噪声处理,常见的去除噪声的方法有均值滤波.中值滤波.高斯滤 ...

  3. java web前端调试手段

    1.console.log() 2. jQuery.ajax({                     url:"/task1/com/guodiantong/servlet/JsonTo ...

  4. 99 Times--Kate Voegele

    歌手 Kate Voegele 是美国俄亥俄州的一位年轻创作型歌手,她会唱歌.会写歌.特 别擅长弹吉他.还会弹钢琴.她是美国新生代歌手中的佼佼者. 99 Times--Kate Voegele   S ...

  5. 4张图看懂delphi 10生成ipa和在iPhone虚拟器上调试(教程)

    4张图看懂delphi 10生成ipa和在iPhone虚拟器上调试(教程) (2016-02-01 03:21:06) 转载▼ 标签: delphi ios delphi10 教程 编程 分类: 编程 ...

  6. lr中错误解决方法19种

    一.Error -27727: Step download timeout (120 seconds)has expired when downloading resource(s). Set the ...

  7. 解决由AJAX请求时forms认证实效的重新认证问题

    前言: 当用AJAX请求一个资源时,服务器检查到认证过期,会重新返回302,通过HTTP抓包,是看到请求了登录页面的,但是JS是不会进行跳转到登录页面. 使用环境: ASP.NET MVC 4 JQU ...

  8. go基本操作

    看了一段时间的go的知识了,本来是冲着它是系统级的语言去的,同时又有java的的样子.看了这么久,发现这语言挺好的,语法精简,有c的遗传.在面向对象上,也有些许的java风格.写web的时候,这风格和 ...

  9. 实现EventHandler的监测

    的监测", "category":"", "tags":"", "publish":&qu ...

  10. spring boot 使用 HandlerInterceptor

    # 背景 在实际项目中,接口出于安全考虑,都会有验签的计算.目前接触的项目来看基本都是时间戳+干扰因子 然后md5计算的方式.现在学习,写一个简单demo, 其实如果不引入拦截器的话,验签计算全部在c ...