Tomcat處理請求流程
- Connector元件的Acceptor監聽客戶端套接字連線並接收Socket。
- 將連線交給執行緒池Executor處理,開始執行請求響應任務。
- Processor元件讀取訊息報文,解析請求行、請求體、請求頭,封裝成Request物件。
- Mapper元件根據請求行的URL值和請求頭的Host值匹配由哪個Host容器、Context容器、Wrapper容器處理請求。
- CoyoteAdaptor元件負責將Connector元件和Engine容器關聯起來,把生成的Request物件和響應物件Response傳遞到Engine容器中,呼叫 Pipeline。
- Engine容器的管道開始處理,管道中包含若干個Valve、每個Valve負責部分處理邏輯。執行完Valve後會執行基礎的 Valve--StandardEngineValve,負責呼叫Host容器的Pipeline。
- Host容器的管道開始處理,流程類似,最後執行 Context容器的Pipeline。
- Context容器的管道開始處理,流程類似,最後執行 Wrapper容器的Pipeline。
- Wrapper容器的管道開始處理,流程類似,最後執行 Wrapper容器對應的Servlet物件的 處理方法
Connector
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Connector用於接收請求並將請求封裝成Request和Response來具體處理。最底層使用的是 Socket。Request和Response封裝後交給Container(Servlet的容器)處理請求,Container處理後返回給Connector,最後由Socket返回給客戶端。
結構
Connector中具體是用 ProtocolHandler處理請求的,代表不同的連線型別。Http11Protocol使用普通Socket連線,Http11NioProtocol使用NioSocket連線。
ProtocolHandler中有三個重要的元件:
- Endpoint:處理底層的Socket網路連線;
- Processor:將Endpoint接收的Socket封裝成Request;
- Adapter:將封裝後的Request交給Container處理;
Endpoint的抽象類 AbstractEndpoint定義了 Acceptor和 AsyncTimeout兩個內部類 和 Handler介面。
- Acceptor:監聽請求;
- AsyncTimeout:檢查非同步Request請求的超時;
- Handler:處理接收的Socket,內部呼叫 Processor進行處理;
public class Connector extends LifecycleMBeanBase {
public Connector() { this(null); }
public Connector(String protocol) {
// 根據 server.xml 中 Connector 屬性 protocol 的值找合適的 className
// 此處返回 org.apache.coyote.http11.Http11NioProtocol
// 賦值給 ProtocolHandler
setProtocol(protocol);
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
// 反射生成 Http11NioProtocol 時,在建構函式中 生成了 NioEndpoint。
p = (ProtocolHandler) clazz.getConstructor().newInstance();
} finally {
this.protocolHandler = p;
}
// 設定編碼集
if (Globals.STRICT_SERVLET_COMPLIANCE) {
uriCharset = StandardCharsets.ISO_8859_1;
} else {
uriCharset = StandardCharsets.UTF_8;
}
}
// 初始化操作
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// 初始化是配置 CoyoteAdapter(Connector 作為引數)
adapter = new CoyoteAdapter(this);
// 協議處理器繫結 介面卡
protocolHandler.setAdapter(adapter);
// 執行 協議處理器初始化操作
protocolHandler.init();
}
// 使用此 聯結器處理 請求
@Override
protected void startInternal() {
// 驗證埠
if (getPort() < 0) { }
// 設定生命週期狀態值
setState(LifecycleState.STARTING);
// 呼叫 協議處理器 start 方法
protocolHandler.start();
}
}
Http11NioProtocol
主要包含 NioEndpoint元件和 Http11NioProcessor元件。啟動時由NioEndpoint元件啟動埠監聽,連線到來被註冊到NioChannel佇列中,由Poller輪詢器負責檢測Channel的讀寫事件,並在建立任務後放入執行緒池中,執行緒池進行任務處理。
public class Http11NioProtocol extends AbstractHttp11JsseProtocol<NioChannel> {
// 建立了 NioEndpoint 類
public Http11NioProtocol() {
// 最終呼叫 AbstractProtocol 類
super(new NioEndpoint());
}
}
// 父類 AbstractProtocol
public abstract class AbstractProtocol implements ProtocolHandler,MBeanRegistration {
@Override
public void init() throws Exception {
// endpointName---"http-nio-8080": http-nio + 8080 組成。
String endpointName = getName();
// 去掉 雙引號
endpoint.setName(endpointName.substring(1, endpointName.length()-1));
// domain == catalina
endpoint.setDomain(domain);
// Endpoint的初始化操作
// serverSocketChannel 繫結埠
endpoint.init();
}
@Override
public void start() throws Exception {
// Endpoint 的 start 方法,重點
// 建立 Executor、最大連線、開啟 Poller thread
endpoint.start();
// 非同步超時 執行緒,
asyncTimeout = new AsyncTimeout();
Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
int priority = endpoint.getThreadPriority();
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
priority = Thread.NORM_PRIORITY;
}
timeoutThread.setPriority(priority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
// AsyncTimeout 實現 Runnable 介面
protected class AsyncTimeout implements Runnable {
private volatile boolean asyncTimeoutRunning = true;
// 後臺執行緒檢查非同步請求並在沒有活動時觸發超時。
@Override
public void run() {
// 死迴圈,直到接收到 shutdown 命令
while (asyncTimeoutRunning) {
Thread.sleep(1000);
long now = System.currentTimeMillis();
for (Processor processor : waitingProcessors) {
processor.timeoutAsync(now);
}
// 迴圈,直到 Endpoint pause
while (endpoint.isPaused() && asyncTimeoutRunning) {
Thread.sleep(1000);
}
}
}
}
NioEndpoint
NioEndpoint是非阻塞IO的一個抽象,包含了:
- LimitLatch:連線數控制器。
- Acceptor:套接字連線並註冊到Channel佇列中。
- Poller:輪詢檢查事件列表。
- SocketProcessor:任務定義器。
- Executor:負責處理套接字。
// AbstractEndpoint
public void init() throws Exception {
if (bindOnInit) {
bind();
bindState = BindState.BOUND_ON_INIT;
}
}
public final void start() throws Exception {
// 判斷是否繫結過
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
// NioEndpoint
@Override
public void bind() throws Exception {
// 繫結 設定的埠
if (!getUseInheritedChannel()) {
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
serverSock.socket().bind(addr,getAcceptCount());
} else {
// Retrieve the channel provided by the OS
Channel ic = System.inheritedChannel();
if (ic instanceof ServerSocketChannel) {
serverSock = (ServerSocketChannel) ic;
}
}
// 設定 阻塞模式
serverSock.configureBlocking(true); //mimic APR behavior
// 初始化 聯結器、輪詢器 預設執行緒數
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
pollerThreadCount = 1;
}
setStopLatch(new CountDownLatch(pollerThreadCount));
// 是否初始化 ssl
initialiseSsl();
selectorPool.open();
}
// 開啟 NIO endpoint, 建立 acceptor, poller 執行緒.
@Override
public void startInternal() throws Exception {
// 設定 running 狀態
if (!running) {
running = true;
paused = false;
// 預設 DEFAULT_SIZE:128 500
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
if ( getExecutor() == null ) {
createExecutor();
}
// 初始化 連線數控制器,預設最大連線數 10000
initializeConnectionLatch();
// 開啟 poller 執行緒, 預設 2
// 檢測到 事件後,交給 processor 處理
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i],
getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
// 開啟 Acceptor 執行緒
startAcceptorThreads();
}
}
// AbstractEndpoint
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
// 開啟 Acceptor 執行緒
for (int i = 0; i < count; i++) {
// NioEndpoint 中實現
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
連線數控制器-------LimitLatch
處理流程圖:
NIO模式下,Tomcat預設把閥門大小設定為 10000,可在 server.xml Connector節點下配置 maxConnections 屬性修改。在連線數到達最大值後,仍可以接收客戶端連線,直到作業系統接收佇列被塞滿。預設100,可在 Connector節點下 配置 acceptCount 屬性修改。
SocketChannel接收器--------Acceptor
Acceptor主要監聽是否有客戶端發來的連線並接收該連線,accept操作是阻塞的。此時返回 SocketChannel物件。Acceptor接收 SocketChannel 物件後要把它設定成非阻塞(後面對客戶端連線才去非阻塞模式處理),接著設定套接字屬性,封裝成非阻塞通道物件。(NioChannel--HTTP、SecureNioChannel--HTTPS),最後將非阻塞通道物件註冊到通道佇列由 Poller 負責檢測事件。
// NioEndpoint
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// 死迴圈,知道收到 shutdown 命令
while (running) {
// Loop if endpoint is paused
while (paused && running) {
state = AcceptorState.PAUSED;
Thread.sleep(50);
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
// 超過最大 連線,等待狀態
countUpOrAwaitConnection();
// 接收從server來的下一個socket連線
SocketChannel socket = serverSock.accept();
// 正確接收 socket,重置 errorDelay
errorDelay = 0;
// Configure the socket
if (running && !paused) {
// 把 socket 交給合適的 處理器處理
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
}
}
state = AcceptorState.ENDED;
}
}
protected boolean setSocketOptions(SocketChannel socket) {
// 處理 socket
try {
// 設定 非阻塞模式
socket.configureBlocking(false);
Socket sock = socket.socket();
socketProperties.setProperties(sock);
NioChannel channel = nioChannels.pop();
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
// 判斷是否開啟 SSL 型別,生成不同型別的 Channel
if (isSSLEnabled()) {
channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
} else {
channel = new NioChannel(socket, bufhandler);
}
} else {
channel.setIOChannel(socket);
channel.reset();
}
// 獲取 Poller,註冊 成 Event 事件。
getPoller0().register(channel);
} catch (Throwable t) {
// 出錯了,就返回,進行 關閉 socket 處理
return false;
}
return true;
}
輪詢器----Poller
需要同時對很多連線進行管理,通過不斷遍歷事件列表,對對應連線的相應事件作出處理。Poller內部依賴 JDK的Selector物件進行輪詢,Selector會選擇出待處理的事件,每輪詢一次就選出若干需要處理的NioChannel,在NIO模式下,每次讀取的資料時不確定的,每次讀取的資料可能有請求頭和請求行,每次只能嘗試去解析報文,如果解析不成功則等待下次輪詢讀取更多資料後再次嘗試,如果解析成功則做一些邏輯處理後對客戶端響應,這些處理工作在任務定義器中定義。
// 在 NioEndpoint startInternal方法中
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
// NioEndpoint 類中定義
public class Poller implements Runnable {
private final SynchronizedQueue<PollerEvent> events =
new SynchronizedQueue<>();
private volatile boolean close = false;
private Selector selector;
@Override
public void run() {
// 死迴圈,直到呼叫 destory 法
while (true) {
boolean hasEvents = false;
try {
if (!close) {
// 在 Acceptor 收到請求封裝成 Socket 註冊到 event 中
// 在輪詢時從Event中取,進行處理
hasEvents = events();
if (wakeupCounter.getAndSet(-1) > 0) {
//if we are here, means we have other stuff to do
//do a non blocking select
keyCount = selector.selectNow();
} else {
keyCount = selector.select(selectorTimeout);
}
wakeupCounter.set(0);
}
if (close) {
events();
timeout(0, false);
try {
selector.close();
} catch (IOException ioe) {
log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
}
break;
}
} catch (Throwable x) {
continue;
}
//either we timed out or we woke up, process events first
if ( keyCount == 0 ) hasEvents = (hasEvents | events());
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
// Walk through the collection of ready keys and dispatch
// any active event.
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
// 另一個執行緒呼叫了 cancelledKey 方法,attachment 可能為null
// 移除次事件,否則進行處理事件
if (attachment == null) {
iterator.remove();
} else {
iterator.remove();
processKey(sk, attachment);
}
}
// 處理超時情況
timeout(keyCount,hasEvents);
}
getStopLatch().countDown();
}
protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
try {
if ( close ) {
cancelledKey(sk);
} else if ( sk.isValid() && attachment != null ) {
if (sk.isReadable() || sk.isWritable() ) {
if ( attachment.getSendfileData() != null ) {
processSendfile(sk,attachment, false);
} else {
unreg(sk, attachment, sk.readyOps());
boolean closeSocket = false;
// Read goes before write
if (sk.isReadable()) {
// 在父類中定義
if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
if (!closeSocket && sk.isWritable()) {
if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
closeSocket = true;
}
}
if (closeSocket) {
cancelledKey(sk);
}
}
}
} else {
//invalid key
cancelledKey(sk);
}
} catch ( CancelledKeyException ckx ) {
cancelledKey(sk);
}
}
}
// AbstractEndpoint
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
// 從 棧中取一個
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
// 沒有就新建一個
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
// 判斷是否有 Executor,最終都是呼叫 Processor 的 run方法。
Executor executor = getExecutor();
// 見SocketProcessor
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
} catch (RejectedExecutionException ree) {
return false;
}
return true;
}
任務定義器---SocketProcessor
// 在上面的操作中,執行 run 方法時,
// SocketProcessorBase
@Override
public final void run() {
synchronized (socketWrapper) {
if (socketWrapper.isClosed()) {
return;
}
doRun();
}
}
// 在 NioEndpoint 類中實現
@Override
protected void doRun() {
NioChannel socket = socketWrapper.getSocket();
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
int handshake = -1;
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// 處理請求
if (event == null) {
// 呼叫 Handler 轉交給 Processor 去處理 process 方法,
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
close(socket, key);
}
}
socketWrapper = null;
event = null;
//return to cache
if (running && !paused) {
processorCache.push(this);
}
}
// AbstractProtocol
protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
@Override
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
if (wrapper == null) {
return SocketState.CLOSED;
}
S socket = wrapper.getSocket();
// 根據Socket獲取具體協議的處理器
Processor processor = connections.get(socket);
// 如果process==null,嘗試其它協議、新建等
// SSL 支援
processor.setSslSupport(
wrapper.getSslSupport(getProtocol().getClientCertProvider()));
// process 和 connection 關聯
connections.put(socket, processor);
SocketState state = SocketState.CLOSED;
do {
// 處理
state = processor.process(wrapper, status);
} while ( state == SocketState.UPGRADING);
// Make sure socket/processor is removed from the list of current
connections.remove(socket);
release(processor);
return SocketState.CLOSED;
}
}
// AbstractProcessorLight(公共父類)
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
throws IOException {
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
// 根據 SocketEvent 所處的 狀態執行不同操作。
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) {
state = service(socketWrapper);
}
} else if (status == SocketEvent.OPEN_WRITE) {
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ){
state = service(socketWrapper);
} else {
state = SocketState.CLOSED;
}
if (state != SocketState.CLOSED && isAsync()) {
state = asyncPostProcess();
}
if (dispatches == null || !dispatches.hasNext()) {
dispatches = getIteratorAndClearDispatches();
}
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}
// 呼叫具體協議的service方法處理請求
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper) {
// 判斷狀態
while (!getErrorState().isError() && keepAlive && !isAsync()
&& upgradeToken == null &&
sendfileState == SendfileState.DONE && !endpoint.isPaused()) {
// 解析request請求頭
try {
if (!inputBuffer.parseRequestLine(keptAlive)) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
if (endpoint.isPaused()) {
response.setStatus(503);
setErrorState(ErrorState.CLOSE_CLEAN, null);
} else {
keptAlive = true;
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
if (!inputBuffer.parseHeaders()) {
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
socketWrapper.setReadTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); break;
} catch (Throwable t) {
// 400 - Bad Request
response.setStatus(400);
setErrorState(ErrorState.CLOSE_CLEAN, t);
// 日誌呼叫處
getAdapter().log(request, response, 0);
}
// Has an upgrade been requested?
Enumeration<String> connectionValues = request.getMimeHeaders().values("Connection");
boolean foundUpgrade = false;
while (connectionValues.hasMoreElements() && !foundUpgrade) {
foundUpgrade = connectionValues.nextElement().toLowerCase(
Locale.ENGLISH).contains("upgrade");
}
if (foundUpgrade) {
// Check the protocol
String requestedProtocol = request.getHeader("Upgrade");
UpgradeProtocol upgradeProtocol = httpUpgradeProtocols.get(requestedProtocol);
if (upgradeProtocol != null) {
if (upgradeProtocol.accept(request)) {
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
response.setHeader("Connection", "Upgrade");
response.setHeader("Upgrade", requestedProtocol);
action(ActionCode.CLOSE, null);
getAdapter().log(request, response, 0);
InternalHttpUpgradeHandler upgradeHandler =
upgradeProtocol.getInternalUpgradeHandler(
getAdapter(), cloneRequest(request));
UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, null, null);
action(ActionCode.UPGRADE, upgradeToken);
return SocketState.UPGRADING;
}
}
}
if (!getErrorState().isError()) {
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
// 500 - Internal Server Error
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
getAdapter().log(request, response, 0);
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
// 通過 CoyotAdapte 處理 request
if (!getErrorState().isError()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
// 處理 request,見 CoyoteAdapter 解析
getAdapter().service(request, response);
if(keepAlive && !getErrorState().isError() && !isAsync() &&
statusDropsConnection(response.getStatus())) {
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
} catch (InterruptedIOException e) {
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
} catch (HeadersTooLargeException e) {
if (response.isCommitted()) {
setErrorState(ErrorState.CLOSE_NOW, e);
} else {
response.reset();
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, e);
response.setHeader("Connection", "close");
}
} catch (Throwable t) {
// 500 - Internal Server Error
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
getAdapter().log(request, response, 0);
}
}
// Finish the handling of the request
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync()) {
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (getErrorState().isError()) {
response.setStatus(500);
}
if (!isAsync() || getErrorState().isError()) {
request.updateCounters();
if (getErrorState().isIoAllowed()) {
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
}
if (!disableUploadTimeout) {
int soTimeout = endpoint.getConnectionTimeout();
if(soTimeout > 0) {
socketWrapper.setReadTimeout(soTimeout);
} else {
socketWrapper.setReadTimeout(0);
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
sendfileState = processSendfile(socketWrapper);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
}
CoyoteAdapter
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
// request == null,新建並關聯
if (request == null) {
// Create objects
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
// Link objects
request.setResponse(response);
response.setRequest(request);
// Set as notes
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
// Set query string encoding
req.getParameters().setQueryStringCharset(connector.getURICharset());
}
// 設定請求頭,告知網站是用何種語言或框架編寫的
// 預設false,Servlet/4.0 JSP/2.3xxxxxxxxxxxxxx
if (connector.getXpoweredBy()) {
response.addHeader("X-Powered-By", POWERED_BY);
}
boolean async = false;
boolean postParseSuccess = false;
req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
try {
// 請求對映、解析引數等操作。
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService()
.getContainer()
.getPipeline()
.isAsyncSupported());
// 由 Pipeline 處理流程,見Pipeline篇
connector.getService()
.getContainer()
.getPipeline()
.getFirst()
.invoke(request, response);
}
// 非同步處理
if (request.isAsync()) {
// 省略
} else {
request.finishRequest();
response.finishResponse();
}
} finally {
// 處理訪問日誌,見日誌篇
if (!async && postParseSuccess) {
Context context = request.getContext();
if (context != null) {
context.logAccess(request, response,
System.currentTimeMillis() - req.getStartTime(), false);
}
}
req.getRequestProcessor().setWorkerThreadName(null);
// 回收 request and response
if (!async) {
request.recycle();
response.recycle();
}
}
}