tomcat在处理每个连接时,Acceptor角色负责将socket上下文封装为一个任务SocketProcessor然后提交给线程池处理。在BIO和APR模式下,每次有新请求时,会创建一个新的SocketProcessor实例(在之前的tomcat对keep-alive的实现逻辑里也介绍过可以简单的通过SocketProcessor与SocketWrapper实例数对比socket的复用情况);而在NIO里,为了追求性能,对SocketProcessor也做了cache,用完后将对象状态清空然后放入cache,下次有新的请求过来先从cache里获取对象,获取不到再创建一个新的。
这个cache是一个ConcurrentLinkedQueue,默认最多可缓存200个对象(见SocketProperties)。可以通过socket.processorCache来设置这个缓存的大小,注意这个参数是NIO特有的。
接下来在SocketProcessor执行过程中,真正的业务逻辑是通过一个org.apache.coyote.Processor的接口来封装的,默认这个Processor的实现是org.apache.coyote.http11.Http11Processor。我们看一下SocketProcessor.process(…)方法的大致逻辑:
public SocketState process(SocketWrapper<S> wrapper, SocketStatus status) {
...
// 针对长轮询或upgrade情况
Processor<S> processor = connections.get(socket);
...
if (processor == null) {
// 1) 尝试从回收队列里获取对象
processor = recycledProce