Tomcat学习之Acceptor
2016-07-25 08:41
555 查看
http://blog.csdn.net/aesop_wubo/article/details/7627772
简介
Acceptor顾名思义就是接收器,用于接收用户请求,这节主要是分析Acceptor的启动和处理请求!首先来看Acceptor的类图
从图中可以看出Acceptor实现了Runnable接口,可以作为一个线程启动,且都是Endpoint的内部类。Acceptor有3种实现JIo、Apr、Nio本节不会介绍他们之间的区别,常用的是JIoEndpoint.Acceptor,后面的例子,如果没有做特别说明指的是JIoEndpoint类里面的接收器。
启动
在tomcat启动的时候会启动Endpoint,会调用它的startInternal方法,来看看这个方法做了哪些事:[java] view
plain copy
print?
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
// Create worker collection
if (getExecutor() == null) {
createExecutor();
}
initializeConnectionLatch();
startAcceptorThreads();
// Start async timeout thread
Thread timeoutThread = new Thread(new AsyncTimeout(),
getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
1、初始化一个闭锁,这个闭锁用于控制连接的,每释放一个连接,闭锁就调用countDown方法一次。getMaxConnections方法返回10000,也就是默认连接数为10000
[java] view
plain copy
print?
protected LimitLatch initializeConnectionLatch() {
if (maxConnections==-1) return null;
if (connectionLimitLatch==null) {
connectionLimitLatch = new LimitLatch(getMaxConnections());
}
return connectionLimitLatch;
}
2、启动带有接收器的线程
[java] view
plain copy
print?
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
(1)getAcceptorThreadCount:在endpoint初始化时,调用AbstractEndpoint.init方法,紧接着调用bind方法,实现是在子类实现的,看看JIOEndpoint类的
bind方法
[java] view
plain copy
print?
public void bind() throws Exception {
// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
......
}
所以在基于JIO的实现方式getAcceptorThreadCount默认为1,也就是默认只有一个线程上有接收器
(2)然后创建count个线程,每个线程上都带有一个接收器,并把这些线程设置为后台线程,最后启动这些线程
处理请求
下面看看启动这些线程后,这些线程做了哪些事?由于org.apache.tomcat.util.net.AbstractEndpoint.Acceptor实现了runnable接口,启动这些线程,也就是运行
org.apache.tomcat.util.net.AbstractEndpoint.Acceptor实现类的run方法,还是以JIO的实现方式为例来看,以下代码省略了很多异常处理
[java] view
plain copy
print?
public void run() {
while (running) {
while (paused && running) {
Thread.sleep(50);
}
countUpOrAwaitConnection();
socket = serverSocketFactory.acceptSocket(serverSocket);
if (running && !paused && setSocketOptions(socket)) {
if (!processSocket(socket)) {
countDownConnection();
......
}
} else {
countDownConnection();
}
}
}
1、整体来看是一个while循环,只要服务器没有被关闭,这个while循环会一直运行,当没有请求到来时,这些线程就会sleep
2、获取一个接连,底层调用的是AQS的sync.acquireSharedInterruptibly(1)方法,有可能需要阻塞
3、如果有请求到来就会调用serverSocketFactory.acceptSocket方法,该方法不细讲,底层调用的就是socket.accept()方法
4、方法调用成功就会分享一个线程来处理这次请求,处理请求的代码在processSocket方法中完成,后面会细讲这个方法
5、如果在处理的过程中或者在acceptSocket的过程中有异常都会调用countDownConnection方法减少连接数,如果socket还打开就关闭socket
参考资料
Tomcat性能调校之连接器模块JIO、APR和NIO相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树