从链接

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. 网络中路由器相关的名词理解LAN,WAN,WLAN

    1. LAN,全称Local Area Network,中文名叫做局域网. LAN是指在某一区域内由多台计算机互联成的计算机组.一般是方圆几千米以内. 局域网可以实现文件管理.应用软件共享.打印机共享 ...

  2. opencpu

    前端通过它调用后端的R语言,对R函数进行一个封装. 网址:https://github.com/jeroenooms/opencpu.js 使用的是opencpu-0.5.js,对它进行了修改. 1. ...

  3. 1028. Hanoi Tower Sequence

    1028. Hanoi Tower Sequence Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Hanoi Tow ...

  4. MYC编译器源码之词法分析

    前文  .NET框架源码解读之MYC编译器 和 MYC编译器源码分析之程序入口 分别讲解了 SSCLI 里示例编译器的架构和程序入口,本文接着分析它的词法分析部分的代码. 词法解析的工作都由Tok类处 ...

  5. 数据帮助类(DataHelper)

    /// <summary> /// 是否为空... /// </summary> /// <param name="str">数据值</p ...

  6. C#时间加减

    DateTime dt =......//减数DateTime dt_n = DateTime.Now;//被减数 long x = dt .ToFileTime();//表示自协调世界时 (UTC) ...

  7. 【C#进阶】委托那些事儿(一)

    一.简单的委托 1.1 委托的声明: C#当中,委托(delegate)是一种方法封装,也即委托对象可以作为一种传递方法的变量来使用. 委托也算是一种类,与类是平级的存在.在类中写delegate对象 ...

  8. WPF 自定义下拉列表

    XAML代码: <Popup x:Name="popupStrategy" StaysOpen="False" PopupAnimation=" ...

  9. 设置oracle主键自增长

    创建test表后,创建序列: CREATE sequence seq_test INCREMENT BY 1 START WITH 1 minvalue 1   成功后,插入一条语句进行测试:   I ...

  10. .net core webapi+EF Core

    .net core webapi+EF Core 一.描述: EF Core必须下载.net core2.0版本 Micorsoft.EntityFrameworkCore:EF框架的核心包Micor ...