前文提要
为了搞懂Http请求是如何转换成Request给Servlet调用的,上篇我们了解到请求时由Acceptor接收,通过添加PollerEvent栈的方式把SocketChannel分发给Poller处理。Poller根据SocketChannel的SelectionKey类型,执行Worker。此时Worker得到的参数是NioSocketWrapper,它包含着请求的参数和Tomcat的网络参数。
下面我们继续探讨NioSocketWrapper经过哪些处理转换为Request。
NioSocketWrapper -> SocketProcessor -> ConnectionHandler -> Http11Processor
Worker
源码是这样介绍SocketProcessor
的:
* This class is the equivalent of the Worker, but will simply use in an
* external Executor thread pool.
*
所以说SocketProcessor
是Worker一个实现形式。
SocketProcessor执行时,会先判断是否已经完成TCP三次握手,如果已完成则获取Handle执行process( )。处理完成后的socketWrapper会被置为null,方便之后的请求复用。
NioEndpoint.SocketProcessor.java
:
@Override
protected void doRun() {
NioChannel socket = socketWrapper.getSocket();
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
try {
int handshake = -1;
...
//检查三次握手是否已经完成
try {
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// Process the request from this socket
if (event == null) {
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
close(socket, key);
}
}
}
} finally {
socketWrapper = null;
event = null;
//return to cache
if (running && !paused) {
processorCache.push(this);
}
}
}
ConnectionHandler
ConnectionHandler是AbstractProtocol的内部类。值得注意的是,ConnectionHandler实现了AbstractEndpoint.Handler接口。所以Http11NioProtocol协议下的ConnectionHandler是ConnectionHandler
①从NioSocketWrapper获取NioChannel,将后者作为key尝试从Map中提取Processor。换句话来说,每个NioChannel都有相应的Processor为它处理请求。
②如果这个NioChannel是第一次请求,则为它创建一个Processor。为它注册请求信息RequestInfo。
③Processor执行process
AbstractProtocol.ConnectionHandler
:
@Override
public SocketState process(SocketWrapperBase wrapper, SocketEvent status) {
...
S socket = wrapper.getSocket();
Processor processor = connections.get(socket);
...
if (processor == null) {
processor = recycledProcessors.pop();
}
if (processor == null) {
processor = getProtocol().createProcessor();
register(processor);
}
...
connections.put(socket, processor);
...
do {
state = processor.process(wrapper, status);
...
} while ( state == SocketState.UPGRADING);
...
}
Processor
在ConnectionHandler执行getProtocol( ).createProcessor。在Http11NioProtocol协议下会调用AbstractHttp11Protocol的createProcessor( )
AbstractHttp11Protocol.java
:
@Override
protected Processor createProcessor() {
Http11Processor processor = new Http11Processor(this, adapter);
return processor;
}
追根溯源,看看Http11Processor的构造器:
Http11Processor.java
:
public Http11Processor(AbstractHttp11Protocol> protocol, Adapter adapter) {
super(adapter);
this.protocol = protocol;
httpParser = new HttpParser(protocol.getRelaxedPathChars(),
protocol.getRelaxedQueryChars());
inputBuffer = new Http11InputBuffer(request, protocol.getMaxHttpHeaderSize(),
protocol.getRejectIllegalHeaderName(), httpParser);
request.setInputBuffer(inputBuffer); // 看见request
...
}
好了,终于看见Request的身影了,但貌似Request在这个构造器里只是在设值,并没有被初始化。继续努力,看看它的父类构造器:
AbstractProcessor.java:
public AbstractProcessor(Adapter adapter) {
this(adapter, new Request(), new Response());
}
protected AbstractProcessor(Adapter adapter, Request coyoteRequest, Response coyoteResponse) {
this.adapter = adapter;
asyncStateMachine = new AsyncStateMachine(this);
request = coyoteRequest;
response = coyoteResponse;
response.setHook(this);
request.setResponse(response);
request.setHook(this);
userDataHelper = new UserDataHelper(getLog());
}
最终,我们在AbstractProcessor的构造器看见了Request初始化的代码。但此时的Request是空对象,并没有获取socket的数据。Request会在Http11Processor设置InputBuffer与socket建立数据通道。然后在Processor执行proecess( )方法时执行。由此可见,Request是属于每个Processor的属性,而一个NioChannel对应一个Processor。因此Request是属于每次请求的一个属性,是线程安全的。
创建完Processor后,AbstractProtocol.ConnectionHandler会执行processor.process( )方法。这是AbstractProcessorLight的方法:
根据SocketEvent的读/写状态,调用子类Processor的service( )
AbstractProcessorLight.java
:
@Override
public SocketState process(SocketWrapperBase> socketWrapper, SocketEvent status)
throws IOException {
SocketState state = SocketState.CLOSED;
Iterator dispatches = null;
do {
if (dispatches != null) {
DispatchType nextDispatch = dispatches.next();
state = dispatch(nextDispatch.getSocketStatus());
} else if (status == SocketEvent.DISCONNECT) {
// Do nothing here, just wait for it to get recycled
} else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
state = dispatch(status);
if (state == SocketState.OPEN) {
// There may be pipe-lined data to read. If the data isn't
// processed now, execution will exit this loop and call
// release() which will recycle the processor (and input
// buffer) deleting any pipe-lined data. To avoid this,
// process it now.
state = service(socketWrapper);
}
} else if (status == SocketEvent.OPEN_WRITE) {
// Extra write event likely after async, ignore
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ){
state = service(socketWrapper);
}
Http11Processor.service( )中会将Request中的inputBuffer真正读取NioChannel里的数据。包括协议行信息,头信息,Body体。byteBuffer.fill( )它是根据协议定下来的指定位置读取信息的。读取之后,现在Request才真正成为有血有肉的本体,可以进入Servlet。
Http11Processor.java
:
@Override
public SocketState service(SocketWrapperBase> socketWrapper)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the I/O
setSocketWrapper(socketWrapper);
inputBuffer.init(socketWrapper);
outputBuffer.init(socketWrapper);
...
if (getErrorState().isIoAllowed()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
getAdapter().service(request, response);
...
}
}
....
}
总结
综合两篇文章可以知道。Http请求 -> Connector -> Protocol -> Acceptor -> Poller -> SocketProcessor -> ConnectionHandler。最终由ConnectionHandler在创建Http11Processor的构造器重new Request对象。因此Request是socket连接的产物,一个请求对应一个Request,是线程安全的。