蓝盟IT小贴士,来喽!
在ServerSocketChannel.open ( )中打开ServerSocket,默认绑定到8080端口,默认连接等待队列长度为100,超过100将拒绝服务。 可以通过配置conf/server.xml中Connector的acceptCount属性进行自定义。 使用createExecutor ( )创建Worker线程池。 默认情况下,工作器线程为10个,在Tomcat处理请求时,工作器最多可以启动200个。 可以通过在conf/server.xml中配置Connector的minSpareThreads和maxThreads来自定义这两个属性。 Pollor用于检测准备就绪的套接字。 默认值最多为2个,Math.min(2,runtime.get runtime ( ).available processors ( ) ) 的双曲馀弦值。 可以通过设置pollerThreadCount进行自定义。 Acceptor用于接受新连接。 缺省值为1。 您可以设置和自定义acceptorThreadCount。
Request Process (请求流程)
接受器
在谈到Tomcat请求处理进程Acceptor在启动后被ServerSocketChannel.accept ( )阻止的方法中,当新连接到达时,该方法返回SocketChannel。 在安排套接字之后,将Socket封装到NioChannel中并向Poller注册,但是对该值的引用是:从头开始启动多个Poller线程,在注册时,为每个Poller公平分配连接。 当NioEndpoint将连接分配给Pollers[index]时,下一个连接将通过pollers [ ( index1) % pollers.length ].addevent ( )方法返回到poller的PollerEvent队列 至此,Acceptor的任务完成了。
Poller
谈Tomcat请求处理流程selector.select(1000 )。 Poller启动后,选择器中没有注册的Channel,因此只能在执行此方法时阻止。 所有Poller都共享选择器。 实现类是sun.nio.ch.epollselectonelevents ( )方法,在EPollSelectorImpl中注册通过addEvent ( )方法添加到事件队列的套接字。 socket可读取时,Poller处理的createSocketProcessor ( )方法将socket封装到socket处理器中,socket处理器实现Runnable接口。 worker线程调用其run ( )方法来处理套接字。 execute(SocketProcessor )方法将套接字处理器提交到线程池,并将其放入线程池的workQueue中。 workQueue是BlockingQueue的实例。 至此Poller的任务完成了。
Worker
创建Tomcat请求处理进程worker线程后,尝试运行ThreadPoolExecutor的runWorker ( )方法以从workQueue检索等待处理的任务,但最初workQueue为空,因此worker线程 将新任务添加到workQueue后,workQueue.take ( )方法返回Runnable。 通常是SocketProcessor,worker线程通过调用SocketProcessor的run ( )方法来处理套接字。 createProcessor ( )分析套接字并创建http 11处理器,以将套接字的内容封装到Request中。 此Request是临时使用的类,类名为org.apache.coyote.Request
postParseRequest ( )方法封装Request并处理映射关系(从URL到相应的Host、Context和Wrapper的映射)。 在将Rquest提交到Container进程之前,coyote适配器将org.apache.coyote.Request封装到org.Apache.catalina.connector.request中,然后传递到Container进程 connector.getservice ( ).get mapper ( ).map ( )用于在mapper中查询URL映射关系。 映射关系保存在org.Apache.catalina.connector.request中,Container处理阶段request.getHost ( )使用在此阶段查询的映射主机,request.getContext connector.getservice ( ).get Container ( ).get pipeline ( ).get first ( ).invoke ( )将请求传递给container进程。 container进程也在Worker线程上运行,但由于这是一个相对独立的模块,因此它分为几个部分。