上篇写到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);
}
NioEndpoint这个类解释
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()启动服务

附:
ObjectName代表一个在domain域下的一个对象名称,或者一个正则对象,这个对象可以通过正则上下文来查询

tpOname = new ObjectName(domain + ":" +"type=ThreadPool,name=" + getName());

分为三部分:域名,property list属性列表,属性名key

domain:type=ProtocolHandler,port=
提供底层网络I / O的端点必须与ProtocolHandler实现(ProtocolHandler使用BIO,需要BIO端点等)匹配
 

tomcat启动(五)Catalina分析-service.init的更多相关文章

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

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

  2. tomcat启动(六)Catalina分析-StandardServer.start()

    从链接 Tomcat中组件的生命周期管理公共接口Lifecycle 可以知道调用的是StandardServer.startInternal() @Override protected void st ...

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

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

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

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

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

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

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

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

  7. Tomcat启动脚本catalina.sh

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

  8. ubuntu下tomcat启动巨慢分析

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

  9. tomcat启动(Ⅶ)请求处理--Processor.process(SocketWrapper<S> socketWrapper)

    tomcat启动(六)Catalina分析-StandardServer.start() 上一篇分析到:Http11NioProcessor.process(SocketWrapper<S> ...

随机推荐

  1. systemtap安装

    一.systemtap介绍 SystemTap是一个强大的调试工具,是监控和跟踪运行中的Linux 内核的操作的动态方法,确切的说应该是一门调试语言,因为它有自己的语法,也有解析.编译.运行等过程(准 ...

  2. (最小生成树) 畅通工程再续 -- HDU --1875

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1875 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  3. spring mvc后台如何处理ajax的请求,并返回json

    spring mvc中有一个注解:@ResponseBody,把这个注解放到ajax请求对应的@RequestMapping(xxx)方法上,在方法体内部,把要返回的json赋给一个String类型的 ...

  4. 基于tinyproxy搭建代理服务器

    在我们实际的工作当中,经常会遇到这种情况,我们对线上服务器进行操作时是通过跳板机来进行的,出于安全性及投入资金来考虑非必要情况下除跳板机以外的服务器是没有内网ip的,所以当我们位于内网的服务器需要使用 ...

  5. Win10系统下编译OSG3.4

    环境说明 1.Win10专业版.64位: 2.VS2012旗舰版:QT5.2.0: 3.cmake-3.9.0.64位: 资源准备 1.OSG3.4源码包 http://trac.opensceneg ...

  6. SQL反模式-1

    SQL反模式讲了很多数据库设计中遇到的难题.跟我最近的工作很相关.因此特意拜读了下.本文主要讲解"多值列"和"幼稚的树" 多值列要分成映射表,比如(A,B),其 ...

  7. MySQL远程连接失败,MySQL远程连接出现Using password:YES错误的解决办法

    相信很多实用MYSQL的朋友都遇到过这种问题,就是MySQL使用localhost能够连接成功,但是使用IP连接却出现Using password:YES或者其它的连接错误.今天就把解决方法给大家说一 ...

  8. .Net Core + NGINX跳转登录时端口丢失

    使用.Net Core + NGINX部署到服务器的时候,如果端口不是使用默认的80端口,在跳转到登录页面时,URL中的端口丢失. NGINX的配置如下: server { listen ; loca ...

  9. deepin mysql安装

    1.安装mysql  更新仓库:sudo apt-get update  安装:sudo apt-get install mysql-server mysql-client  问题:安装mysql5. ...

  10. 微信小程序开发教程(一)—介绍和准备

    前言: 因为客户需要,也为了更好的发展我们公司的产品,所以决定扩展移动端.但是由于公司没有原生安卓开发人员,而且开发安卓成本比较高,所以公司一致决定开发微信小程序,也是由于微信小程序最近的火热. 后台 ...