Tomcat知多少 -- 01. 使用LimitLatch限制最大连接数
1. 概述
在英文中,latch是“门闩”的意思,这跟锁(lock)所要表达的意思接近,获取到latch则可以进入房间,否则只能等待。而我猜测使用latch而不是用lock可能是想表达“轻量级锁”。
LimitLatch实例在初始化时会设置一个资源的上限值,在某一时刻,资源使用未达到上限则可以获取锁并消耗一个资源,资源使用达到上限后,随后到来的请求将进入队列,直到有资源得到释放。
LimitLatch是一个共享性质的锁,这里的共享概念来自于AQS,指的是不同的线程可以同时获取该锁。
实际上,在JDK的JUC包中,还有一个CountDownLatch
存在,两者都是基于AQS框架实现的同步工具类,不过表达的意思却完全不同。
CountDownLatch
表示的行为是“所有线程都到达了某一状态后才执行动作”,LimitLatch
则更像是Semaphore
,用于记录资源的使用。
如上图所示,LimitLatch类的结构并不复杂,它有四个私有成员变量,作用如下:
private final Sync sync; // 同步工具类,Sync是内部类
private final AtomicLong count; // 当前使用资源数目
private volatile long limit; // 总的可用资源数目
private volatile boolean released = false; // 资源是否被全部释放
另外,有两个主要的公有方法:
countUpOrAwait()
用来获取一个资源,如果当前没有资源可以获取,则进入等待队列;countDown()
则用于释放一个资源。
2. LimitLatch在Tomcat中的作用
在Tomcat中,LimitLatch
类用于限制Tomcat可接受的连接数量。
2.1 初始化LimitLatch
在NioEndPoint类中,initializeConnectionLatch()
用于创建LimitLatch实例。
protected LimitLatch initializeConnectionLatch() {
if (maxConnections==-1) return null;
if (connectionLimitLatch==null) {
// 默认的最大连接数是 8 * 1024
connectionLimitLatch = new LimitLatch(getMaxConnections());
}
return connectionLimitLatch;
}
2.2 在Acceptor中使用LimitLatch限制连接数量
如下面代码所示,当超过最大连接数时,Acceptor线程将通过自旋锁等待。
public class Acceptor<U> implements Runnable {
@Override
public void run() {
...
//如果达到了最大连接数则等待
endpoint.countUpOrAwaitConnection();
...
// 从serverSocket中接受一个连接
socket = endpoint.serverSocketAccept();
...
}
}
2.3 当socket被销毁时,占有的锁将被释放
在NioEndPoint
类的destroySocket()
方法中,每当销毁一个socket时就释放一个连接资源。
@Override
protected void destroySocket(SocketChannel socket) {
countDownConnection(); // 实际上调用了LimitLatch的countDown()方法
try {
socket.close();
} catch (IOException ioe) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("endpoint.err.close"), ioe);
}
}
}
-------------------------------------
吾生也有涯,而知也无涯。
吾生也有涯,而知也无涯。