tomcat启动(五)Catalina分析-service.init
上篇写到StandardService.init()
这个方法做什么呢?一起来看看。
这个类也是实现了Lifecycle
如图。这个图中i表示Interface接口。如Lifecycle,Container,Executor
C表示Class类 如StandardService
C上有一个小A表示Abstract Class抽象类 如LifecycleBase,WebappClassLoaderBase
感觉用这个图来表示继承关系很好,但这个不能显示出实现关系。要用类图才可以。
public class StandardService extends LifecycleMBeanBase implements Service
跑题了。。
StandardService和StandardServer一样也是继承自LifecycleMBeanBase
在StandardService没有init方法。
调用的其实是LifecycleBase这个类的init方法,然后会调用StandardService.initInternal()
主要作用:
Invoke a pre-startup initialization. This is used to allow connectors to bind to restricted ports under Unix operating environments.
调用预启动初始化。这用于允许connectors绑定到Unix操作环境下的受限端口。
执行LifecycleMBeanBase.initInternal()向MBeanServer类进行MBean(service)组件注册
在这个StandardService的initInternal方法中会先判断container是否为空,
如果不为空则执行container.init()注册container组件(这里的Container是:StandardEngine)
1、初始化所有Executors
其实就是为Executor指定domain,
然后使用StandardThreadExecutor.initInteral()方法
向MBeanServer注册Executor组件(跟server和service调用init()过程一样)
这里的Executor加载的是org.apache.catalina.core.StandardThreadExecutor类
public interface Executor extends java.util.concurrent.Executor, Lifecycle
//这里可以略过。。。。
An object that executes submitted Runnable tasks. This interface provides a
way of decoupling task submission from the mechanics of how each task will be
run, including details of thread use, scheduling, etc. An Executor is normally
used instead of explicitly creating threads. For example, rather than invoking
new Thread(new(RunnableTask())).start() for each of a set of tasks, you might
use:
执行提交Runnable任务的对象。该接口提供了一种将任务提交从每个任务的运行机制分解的
方法,包括线程使用,调度等的细节。通常使用执行程序,而不是显式创建线程。例如,您可以
使用以下各项来调用每个新任务
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
... However, the Executor interface does not strictly require that execution be
asynchronous. In the simplest case, an executor can run the submitted task
immediately in the caller's thread:
Executor接口并不严格要求执行是异步的。在最简单的情况下,执行程序可以立即在调用者的线程中运行提交的任务:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}}
More typically, tasks are executed in some thread other than the caller's
thread. The executor below spawns a new thread for each task.
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}}
Many Executor implementations impose some sort of limitation on how and
when tasks are scheduled. The executor below serializes the submission of
tasks to a second executor, illustrating a composite executor.
更通常地,任务在除调用者的线程之外的一些线程中执行。下面的执行器为每个任务生成一个新的线程。
class SerialExecutor implements Executor {
final Queue tasks = new ArrayDeque();
final Executor executor;
Runnable active; SerialExecutor(Executor executor) {
this.executor = executor;
} public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (active == null) {
scheduleNext();
}
} protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}}
The Executor implementations provided in this package implement
ExecutorService, which is a more extensive interface. The ThreadPoolExecutor
class provides an extensible thread pool implementation. The Executors class
provides convenient factory methods for these Executors.
Memory consistency effects: Actions in a thread prior to submitting a Runnable
object to an Executor happen-before its execution begins, perhaps in another
thread.
此包中提供的Executor实现来实现ExecutorService,它是一个更广泛的接口。
ThreadPoolExecutor类提供了一个可扩展的线程池实现。
Executors类为这些Executors执行人员提供了方便的工厂方法。
内存一致性效果:在将Runnable对象提交给执行程序之前,线程中的操作会在其执行开始之前发生,也许在另一个线程中。
2 、初始化Mapper Listener。调用MapperListener.init()方法,跟上面server,service,executor一样注册组件
3 初始化自定义connectors连接器 Initialize our defined Connectors。
同上调用connector.init()注册connector组件
但在connector.initInteral()方法被重写了
代码不长就贴出来吧
@Override
protected void initInternal() throws LifecycleException { super.initInternal(); // Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter); // Make sure parseBodyMethodsSet has a default
if( null == parseBodyMethodsSet ) {
setParseBodyMethods(getParseBodyMethods());
} if (protocolHandler.isAprRequired() &&
!AprLifecycleListener.isAprAvailable()) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerNoApr",
getProtocolHandlerClassName()));
} try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException
(sm.getString
("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}
初始化CoyoteAdapter
Implementation of a request processor which delegates委托 the processing to a Coyote processor
执行将处理委托给CoyoteAdapter的请求处理器
ProtocolHandler protocolHandler端口处理程序
摘要协议实现,包括线程等。ProtocolHandler 处理器是单线程的,
特定于基于流的协议,不适合像JNI这样的Jk协议。这是由CoyoteAdapter实现的主要接口。
adapter是由coyote servlet container.实现的主要接口。
这个ProtocolHandler是一个接口,调用的ProtocolHandler.init()方法的类是org.apache.coyote.http11.Http11NioProtocol
Note:这里不是用Http11Protocol进行处理,我这个tomcat8.0版本是使用Http11NioProtocol处理器
在Connector构造方法中通过protocolHandlerClassName这个变量来生成处理程序实例
connecto被创建会先设置端口处理程序setProtocol()
这里处理http协议请求的有两个处理器
Http11AprProtocol和Http11NioProtocol前者需要安装复杂环境,后者为默认处理器
/**
* Coyote Protocol handler class name.
* Defaults to the Coyote HTTP/1.1 protocolHandler.
*/
protected String protocolHandlerClassName =
"org.apache.coyote.http11.Http11NioProtocol";
public Connector(String protocol) {
setProtocol(protocol); Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.newInstance();//生成实例 } public void setProtocol(String protocol) { if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11NioProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpNioProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
} }
初始化protocolHandler也就是调用Http11NioProtocol的init方法
public abstract class AbstractProtocol<S> implements ProtocolHandler , MBeanRegistration
有上面可以知道AbstractProtocol实现的ProtocolHandler
--》实际调用
@Override
public void init() throws Exception {
// SSL implementation needs to be in place before end point is
// initialized
必须在end point被初始化之前创建SSL
sslImplementation = SSLImplementation.getInstance(sslImplementationName);
super.init();
}
// Component not pre-registered so register it注册protocolHandler组件
Registry.getRegistry(null, null).registerComponent(this, oname,
null);
//创建thread pool线程池的MBean的名称
tpOname = new ObjectName(domain + ":" +
"type=ThreadPool,name=" + getName());
getName()获得的名字是prefix-address-port
//注册线程池组件
Registry.getRegistry(null, null).registerComponent(endpoint,
tpOname, null);
//Name of MBean for the Global Request Processor.
//注册GlobalRequestProcessor全局请求处理器组件
rgOname=new ObjectName(domain +
":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry(null, null).registerComponent(
getHandler().getGlobal(), rgOname, null );
String endpointName = getName();
endpoint.setName(endpointName.substring(, endpointName.length()-));
这里从1开始length-1结束是为了去掉首尾双引号
endpoint.init();
这里执行endpoint是执行的NioEndpoint.init()方法-------在Http11NioProtocol构造方法中设置
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);
}
NIO tailored thread pool, providing the following services:
•Socket acceptor thread
•Socket poller thread
•Worker threads pool
When switching to Java 5, there's an opportunity to use the virtual machine's
thread pool.
NIO定制的线程池,提供以下服务:
•套接字线程
•套接字轮询线程
•工作线程池
切换到Java 5时,有机会使用虚拟机的线程池。
NioEndpoint.init()没有重写父类的方法----调用
public final void init() throws Exception {
testServerCipherSuitesOrderSupport();
if (bindOnInit) {
bind();
bindState = BindState.BOUND_ON_INIT;
}
}
parameter:bindOnInit:默认为true
Controls when the Endpoint binds the port.控制endpoint绑定端口
true
, the default binds the port on init()
and unbinds it on destroy()
.
If set to false
the port is bound on start()
and unbound on stop()
.
NioEndpoint.bind()
/**
* Initialize the endpoint.
*/
@Override
public void bind() throws Exception {
面向流的listening socket的可选通道,新创建的服务器套接字通道已打开但尚未绑定。
调用未绑定服务器套接字通道的accept方法的尝试将导致抛出NotYetBoundException。
可以通过调用此类定义的bind方法来绑定服务器套接字通道
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
//实现了ip套接字地址
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
serverSock.socket().bind(addr,getBacklog());
serverSock.configureBlocking(true); //mimic APR behavior
serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout()); // Initialize thread count defaults for acceptor, poller
初始化线程计数器
if (acceptorThreadCount == 0) {
// FIXME: Doesn't seem to work that well with multiple accept threads
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
//minimum one poller thread
pollerThreadCount = 1;
}
stopLatch = new CountDownLatch(pollerThreadCount); // Initialize SSL if needed
if (isSSLEnabled()) {
SSLUtil sslUtil = handler.getSslImplementation().getSSLUtil(this); sslContext = sslUtil.createSSLContext();
sslContext.init(wrap(sslUtil.getKeyManagers()),
sslUtil.getTrustManagers(), null); SSLSessionContext sessionContext =
sslContext.getServerSessionContext();
if (sessionContext != null) {
sslUtil.configureSessionContext(sessionContext);
}
// Determine which cipher suites and protocols to enable
enabledCiphers = sslUtil.getEnableableCiphers(sslContext);
enabledProtocols = sslUtil.getEnableableProtocols(sslContext);
} if (oomParachute>0) reclaimParachute(true);
selectorPool.open();
}
到这里在Catalina.load()方法中调用的server.init()已经执行完成。
接下来将调用Catalina.start()方法来调用server.start()启动服务
tpOname = new ObjectName(domain + ":" +"type=ThreadPool,name=" + getName());
分为三部分:域名,property list属性列表,属性名key
tomcat启动(五)Catalina分析-service.init的更多相关文章
- tomcat启动(四)Catalina分析-server的init()方法
上一回load()方法解析讲到xml解析完成. load()内部接下来会获取server getServer().setCatalina(this); 这个server从createStartDige ...
- tomcat启动(六)Catalina分析-StandardServer.start()
从链接 Tomcat中组件的生命周期管理公共接口Lifecycle 可以知道调用的是StandardServer.startInternal() @Override protected void st ...
- tomcat启动(三)Catalina分析-load方法分析
load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- 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 ...
- tomcat启动(Ⅶ)请求处理--Processor.process(SocketWrapper<S> socketWrapper)
tomcat启动(六)Catalina分析-StandardServer.start() 上一篇分析到:Http11NioProcessor.process(SocketWrapper<S> ...
随机推荐
- PAT甲 1048. Find Coins (25) 2016-09-09 23:15 29人阅读 评论(0) 收藏
1048. Find Coins (25) 时间限制 50 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Eva loves t ...
- 用Lucene实现分组,facet功能,FieldCache
假如你像用lucene来作分组,比如按类别分组,这种功能,好了你压力大了,lucene本身是不支持分组的. 当你想要这个功能的时候,就可能会用到基于lucene的搜索引擎solr. 不过也可以通过编码 ...
- Banana
Banana 除了有香蕉的意思外,还表示 喜剧演员
- Grafana展示DNS解析延时
首先一个完整的监控肯定会包含三个部分:1.数据收集部分.2.数据存储部分.3.数据展示部分,今天我也是从这三个方面来实现这个监控的. 数据收集(SHELL 脚本) 没有想到比较好的方法来采集数 ...
- java 反射应用
场景需求最近的一次解析数据包中,因为协议有改变,本来的定长的包,现在变为不定长的.举个例子,本来协议中规定,一个包中,有8个标签,但是每次上来的,不一定都有8个,没有的话,硬件过来的都是0.同时里面也 ...
- vs2017新建.netcore相关项目提示"未检测到任何.NET Core SDK"或打开.net core 相关项目Web层总是未能正常加载
近来vs2017出现一个非常怪的现象,之前新建.net core相关项目好好的,现在出现问题,如下: 解决办法,是更新vs2017,界面如下:
- c# 调用短信平台接口,给手机发送短信
项目上要做个发手机短信的功能.网上找找了,用的微米的短信接口. 注册后,获得UID和UID key,C#代码中需要这个 调用代码很简单 ", con = "[微米]您的验证码是:6 ...
- [TJOI2013]攻击装置(网络流,最小割)
前言 网络流被hbx吊起来打 Solution 考虑一下这个走法是不是和象棋中马的走法一模一样(废话) 那么显然我每一次移动是走三次,如果将棋盘二分图染色一下,不就是每一次只能走到另一个颜色的吗? 然 ...
- Python 使用 os 模块遍历目录/获取当前文件的路径
1.列出指定目录下所包含的目录 item = os.listdir("/Users/jinchengxie/go") 返回的是一个列表, 里面包含了指定目录下所包含的所有的目录 2 ...
- Spring配置项<context:annotation-config>的解释说明
今天在闲逛CSDN论坛时,看到一位博主写的一篇关于<Spring中IOC的Annotation的实现>的文章, 于是点击进去看了下, 发现在说明中对Spring配置文件中的有些配置节点模凌 ...