tomcat源码分析之connector

最近看了tomcat的源码,想写点总结。

tomcat的模块划分可以用下面的图视之:
[img]http://dl.iteye.com/upload/attachment/353493/f4853009-afe4-3e53-8c0f-b7101af3ba39.jpg[/img]
从上面的图可以看出,在客户端访问tomcat的时候有一层叫做connector的东西,这其实是处理来自于客户端的协议,左边的coyote connector是对HTTP/1.1协议处理,右边的jk connector是对AJP/1.3协议做处理。

以下就针对coyote connector做一下源代码分析。

首先我们看两个相关的类图:
[img]http://dl.iteye.com/upload/attachment/353495/40b16321-823d-34a7-b1a4-40c4e62bb599.jpg[/img]
[img]http://dl.iteye.com/upload/attachment/353497/2103cf0c-7dd1-3649-a469-bb655a49ea8d.jpg[/img]
对上面的类图做一下简单说明:
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(),就是初始化和启动的方法。

下面看几个流程图。

先看一下tomcat启动时的load流程:
[img]http://dl.iteye.com/upload/attachment/353499/a7331fbc-2f82-3d7b-83ee-49a69d2938dd.jpg[/img]
tomcat启动时的load从Bootstrap这个类的load方法开始,一步一步的初始化,在初始化Http11Protocol的时候会把Http11ConnectionHandler注入到JIoEndpoint,并调用JIoEndpoint的初始化方法,就是用DefaultServerSocketFactory去创建ServerSocket。

再来看tomcat启动时的start流程:
[img]http://dl.iteye.com/upload/attachment/353501/4f95c516-9188-3be3-9a2c-d69d0087e415.jpg[/img]
tomcat启动时的start从是紧接着上面的load,load完后从Bootstrap这个类的start开始一步一步的start,在Http11Protocol调用start的时候会调用JIoEndpoint的start方法,这个方法会new一个WorkerStack,并会new一个Acceptor线程,放入到Thread中,用Thread的start方法启动线程。

下面看一下上面启动的线程里如何运作,Acceptor线程其实是一个循环接受socket的类,我们还是来看一下流程图:
[img]http://dl.iteye.com/upload/attachment/353503/97082db1-631e-3c2c-bd54-ac8b353af680.jpg[/img]
在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线程类似,只是不循环,也不回收。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值