您的位置:首页 > 运维架构 > Tomcat

Tomcat源码解析(五):Connector连接器的初始化和启动流程

2016-03-15 19:38 633 查看
Connector是Tomcat最核心的组件之一,每个Service服务下存在多个Connector连接器,Connector的处理性能决定了Tomcat服务的性能,此处记录为Tomcat4的连接器工作机制。

Tomcat4中Connector模块的类可以划分以下部分:

1、连接器及其处理器类(HttpConnector和HttpProcessor);

2、表示Http请求类(HttpRequest)及其支持类;

3、表示Http响应类(HttpResponse)及其支持类;

4、外观装饰类(HttpRequestFacade和HttpResponseFacade);

Tomcat中连接器必须实现Connector接口,接口中声明很多方法,其中最重要的如下:

public interface Connector {
// 关联容器
public Container getContainer();

public void setContainer(Container container);

// 所属Service服务
public Service getService();

public void setService(Service service);

// 根据http请求信息构建请求和响应对象
public Request createRequest();
public Response createResponse();

// 初始化
public void initialize() throws LifecycleException;
}
Connector默认Http协议的实现类是HttpConnector,该类同时实现了Runnable接口和LifeCycle接口。

Tomcat4中HttpConnector通过ServerSocket循环接受Http请求连接,实际进一步处理则委托给HttpProcessor对象池处理,而HttpProcessors对象池多线程并行执行多个任务,所以实际性能取决于HttpProcessor对象池的工作机制。

HttpConnector每次接受新的Http请求连接后,将处理工作委托给HttpProcessor对象池,而HttpConnector本身则继续接受下一个请求,使得HttpConnector一直处于循环接受工作状态,无需等待一个请求处理完毕再去接受下一个请求。工作处理流程如图:



HttpConnector的初始化流程

public void initialize()
throws LifecycleException {
// 防止重复初始化
if (initialized)
......
// 记录初始化
this.initialized=true;
Exception eRethrow = null;

// Establish a server socket on the specified port
try {
// 创建ServerSocket实例
serverSocket = open();
} ...
}
HttpConnector的启动流程

1、触发HttpConnector启动事件,通知相关监听器;

2、开启后端线程,循环监听Http请求连接;

3、创建初始处理器对象池;

public void start() throws LifecycleException {
// Validate and update our current state
if (started)
throw new LifecycleException
(sm.getString("httpConnector.alreadyStarted"));
// 监听线程名称
threadName = "HttpConnector[" + port + "]";
// 触发启动事件
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;

// 开启后端线程,ServerSocket循环监听Http请求连接
threadStart();

4000
// 创建初始处理器个数
while (curProcessors < minProcessors) {
if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
break;
HttpProcessor processor = newProcessor();
recycle(processor);// 入栈未使用processors
}
}
可以看出初始默认HttpProcessor处理器个数取决于minProcessor,部分相关属性如下:

// 当前被创建的处理器个数
private int curProcessors = 0;

// 最小处理器个数
protected int minProcessors = 5;

// 最大处理器个数,小于0则无限制
private int maxProcessors = 20;
// 已经被创建处理器集合
private Vector created = new Vector();

// 已经空闲处理器集合
private Stack processors = new Stack();
启动初,HttpProcessor的默认创建规则如下:

// 创建初始处理器个数
while (curProcessors < minProcessors) {
if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
break;
HttpProcessor processor = newProcessor();
recycle(processor);
}
1、默认HttpProcessor个数依据minProcessors创建,如果minProcessors=5,则创建5个HttpProcessor;

2、如果出现maxProcessors大于minProcessors情形,则创建个数依据maxProcessors,如minProcessors=5,maxProcessors=3,则创建3个HttpProcessor;

注意此处的recycle()方法,即回收处理器,只存在两种情形下执行:

1、启动之初,新创建处理器实例,加入空闲处理器队列;

2、处理器执行完请求,变成空闲,则处理器会主动加入空闲队列;

查看下处理器创建方法,newProcessor(),实际则创建实例并启动

private HttpProcessor newProcessor() {
// 创建HttpProcessor实例,传入当前HttpConnector引用
// curProcessors个数+1,并用此curProcessors数字作为HttpProcessorid号
HttpProcessor processor = new HttpProcessor(this, curProcessors++);
if (processor instanceof Lifecycle) {
try {
// 启动当前HttpProcessor,实例开启线程接口处理请求
((Lifecycle) processor).start();
} catch (LifecycleException e) {
log("newProcessor", e);
return (null);
}
}
// 加入已经创建HttpProcessor集合
created.addElement(processor);
return (processor);
}
HttpProcessor的构造方法如下:

public HttpProcessor(HttpConnector connector, int id) {
super();
this.connector = connector;
this.debug = connector.getDebug();
this.id = id;
this.proxyName = connector.getProxyName();
this.proxyPort = connector.getProxyPort();
// 请求和应答对象,可以看出是由connector创建
this.request = (HttpRequestImpl) connector.createRequest();
this.response = (HttpResponseImpl) connector.createResponse();
this.serverPort = connector.getPort();			       // 端口
this.threadName =
"HttpProcessor[" + connector.getPort() + "][" + id + "]";    // 线程名称
}


接下来查看后端线程创建实现具体:

private void threadStart() {

log(sm.getString("httpConnector.starting"));

thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
}
由于当前this已经实现runable接口,所以线程执行工作在当前connector的run方法,主要工作如下:

1、阻塞等待Http请求;

2、为每个请求分配一个HttpProcessor对象;

3、调用HttpProcessor的process()方法处理;

public void run() {
// 循环,直到shutdown
while (!stopped) {
// 监听socket
Socket socket = serverSocket.accept();

// 为socket分配处理器
HttpProcessor processor = createProcessor();
// 如果当前没有空闲处理器
if(processor == null) {
// 忽略请求,不做处理
}
// 执行处理
processor.assign(socket);
}
}


实际HttpConnector工作创建的HttpProcessor的个数在creatProcessor中具体实现,查看如下:

private HttpProcessor createProcessor() {
synchronized (processors) {
// 当前processors集合中存在空闲处理器
if (processors.size() > 0) {
// 则获取返回
return ((HttpProcessor) processors.pop());
}

// 当前处理器个数小于最大处理器个数,则创建新处理器实例
if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {
return (newProcessor());
} else {

// maxProcessors小于0,则无限制创建新实例
if (maxProcessors < 0) {
return (newProcessor());

// curProcessors = maxProcessors,已经不能创建新实例,忽略
} else {
return (null);
}
}
}
}
总结运行中创建规则如下:

1、如果processors(未使用)集合中存在空闲处理器,则出栈获取;

2、当前处理器个数小于最大处理器参数,即curProcessors<maxProcessors,则创建新实例;

3、如果maxProcessors参数小于0,则无限制创建新实例;

4、如果处理器个数等于最大处理器参数,即curProcessors=maxProcessors,则忽略处理,返回null;

实际HttpConnector和HttpProcessor工作机制在后续详细分析。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: