在客户端访问tomcat的时候有一层叫做connector的东西,这其实是处理来自于客户端的协议,左边的coyote connector是对HTTP/1.1协议处理,右边的jk connector是对AJP/1.3协议做处理。以下就针对coyote connector做一下源代码分析。
对上面的类图做一下简单说明:
JIoEndpoint:提供监听线程Acceptor接受socket并且创建一个新的Worker线程处理connection,处理完放入WorkerStack。
WorkerStack:含有一个存放Worker线程的数组。
Acceptor:Server socket acceptor thread。
Worker:线程类,并调用Http11ConnectionHandler处理socket。
Executor:执行线程,线程作为参数传入
SocketProcessor:线程类,类似于Worker,也是调用Http11ConnectionHandler处理socket。
Http11Processor:真正的Processes http requests类。涉及到http协议中一些参数的实现,比如长连接。并且继承了ActionHook,可以对ActionCode代表的事件做相应的处理,即修改http协议中的参数。
Http11ConnectionHandler:从队列ConcurrentLinkedQueue<Http11Processor>中取出Http11Processor对socket处理。
Http11Protocol:继承了ProtocolHandler,是处理协议的总的处理器。从名字就可以看出这一点。
其实例变量包括Http11ConnectionHandler,JIoEndpoint,ServerSocketFactory,SSLImplementation,Adapter,有两个重要的方法init()和start(),就是初始化和启动的方法。
下面看一下上面启动的线程里如何运作,Acceptor线程其实是一个循环接受socket的类,我们还是来看一下流程图:
在Acceptor线程的run方法里,对每一个socket会产生一个Worker线程,在启动这个Worker线程后,这个线程的run方法会调用await方法其实是先让这个线程处于wait状态。再说上面的Acceptor线程这时会调用assign方法,其实是用notifyAll()去解开Worker线程的wait状态。当然由于是线程并没有一定的先后,以上也许是先assign,后await也有可能,这时就不会产生wait状态了。在处理完socket后,会把此Worker线程回收到WorkerStack中,下次可以从其中拿而不用新创建,但是当很多请求的时候,Worker不够用了,也需要创建新的Worker线程。WorkerStack中Worker数组的最大值默认是200。由于Worker线程中的run方法是处在一个不断的循环中,当下一次循环的时候又将进入wait状态,等待唤醒。因此在WorkerStack中的Worker线程就是一个个处于wait状态的线程。以上的这种请求处理方式就是用一个线程循环的去接受,再创建线程或从线程数组中获取线程去处理请求。
其实tomcat可以配置线程池的,在代码中也是这样判断的:如果没有线程池就创建WorkerStack,后面用Worker线程处理socket;如果有线程池时就使用线程池,看代码executor.execute(new SocketProcessor(socket));就是创建一个SocketProcessor线程去处理socket,SocketProcessor中的run方法和Worker线程类似,只是不循环,也不回收。