1. Connector组件的Acceptor监听客户端套接字连接并接收Socket。
  2. 将连接交给线程池Executor处理,开始执行请求响应任务。
  3. Processor组件读取消息报文,解析请求行、请求体、请求头,封装成Request对象。
  4. Mapper组件根据请求行的URL值和请求头的Host值匹配由哪个Host容器、Context容器、Wrapper容器处理请求。
  5. CoyoteAdaptor组件负责将Connector组件和Engine容器关联起来,把生成的Request对象和响应对象Response传递到Engine容器中,调用 Pipeline。
  6. Engine容器的管道开始处理,管道中包含若干个Valve、每个Valve负责部分处理逻辑。执行完Valve后会执行基础的 Valve--StandardEngineValve,负责调用Host容器的Pipeline。
  7. Host容器的管道开始处理,流程类似,最后执行 Context容器的Pipeline。
  8. Context容器的管道开始处理,流程类似,最后执行 Wrapper容器的Pipeline。
  9. 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();
}
}
}

Tomcat处理请求流程的更多相关文章

  1. tomcat匹配请求流程(原创)

    tomcat8.0.36 配置Connector属性allowTrace为true时,允许TRACE方法,默认禁止. tomcat8.0.36有一个BUG,该BUG在8.0.37里被修复,就是一个解析 ...

  2. 6张图说清楚Tomcat原理及请求流程

    前言 很多东西在时序图中体现的已经非常清楚了,没有必要再一步一步的作介绍,本文以图为主,然后对部分内容加以简单解释. 绘制图形使用的工具是 PlantUML + Visual Studio Code ...

  3. 使用反向代理的http的请求流程

    此文章主要为刚接触反向代理的小伙伴梳理请求流程,以便更好的理解反向代理是何时工作的 流程 由于浏览器是有缓存的,所以本地的hosts文件的信息也会在浏览器端缓存 当客户端发起一个新的请求(例如:输入的 ...

  4. 如何安装部署和优化Tomcat?(Tomcat部署和优化与压测,虚拟主机配置,Tomcat处理请求的过程)

    文章目录 前言 一:Tomcat安装部署 1.1:Tomcat简介 1.2:Tomcat核心组件 1.3:Tomcat处理请求的过程 1.3.1:请求过程基本解释 1.3.2:请求过程详细解释 1.4 ...

  5. servlet单例模式以及servlet的请求流程

    ​ 目录 一.servlet 单例模式: 二.servlet的请求流程: ★ 流程: ★ 详细过程如下: 一.servlet 单例模式: tomcat服务器,通过Java的反射机制来自动调用servl ...

  6. Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例

    前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...

  7. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  8. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  9. MVC视图请求流程视图

    /*         *视图请求流程         *当接受到home/index请求时         *先去找viewstart.cshtml视图,再去加载index.cshtml视图      ...

随机推荐

  1. 并发模型之Master-Worker设计模式

    一.Master-Worker设计模式 Master-Worker模式是常用的并行设计模式.它的核心思想是,系统有两个进程协议工作:Master进程和Worker进程.Master进程负责接收和分配任 ...

  2. NOI 2016 区间 解题报告

    题目描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...

  3. 为什么推荐用ui-router替代ngRoute

    初学angularjs,第一个实例是官网的phoneCat,里面路由用的是ngRoute,后来看到别的用ui-router,觉得好奇,ui-route是什么呢?百度一些,得到如下解释: ui-rout ...

  4. MySQL数据库(11)----使用子查询实现多表查询

    子查询指的是用括号括起来,并嵌入另一条语句里的那条 SELECT 语句.下面有一个示例,它实现的是找出与考试类别('T')相对应的所有考试事件行的 ID,然后利用它们来查找那些考试的成绩: SELEC ...

  5. Qt Quick程序的发布

    要将程序发布出去,首先需要使用release方式编译程序,然后将生成的.exe可执行文件和需要的库文件发在一起打包进行发布. 要确定需要哪些动态库文件,可以直接双击.exe文件,提示缺少那个dll文件 ...

  6. Android深入四大组件(六)Service的启动过程

    前言 此前我用较长的篇幅来介绍Android应用程序的启动过程(根Activity的启动过程),这一篇我们接着来分析Service的启动过程.建议阅读此篇文章前,请先阅读Android深入四大组件(一 ...

  7. JDK配置步骤

    1.安装jkd1.6.0以上版本. 2.安装结束后,运行cmd.键入: java -version判断JDK是否安装成功,如下图所示. 3.首先需要到官网上下载JDK这款软件,本人下载的是jdk-6u ...

  8. Frequently Used Algo

    1. 链表 链表逆转 class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; w ...

  9. python字典的排序

    # -*- coding:UTF-8 -*- def dict_sort(): # 按照value的值从大到小的顺序进行排序 dic = {'a': 31, 'bc': 5, 'c': 3, 'asd ...

  10. linux 三大利器 grep sed awk sed

    sed主要内容和原理介绍 sed 流处理编辑器 sed一次处理一行内容,读入一行处理一行 sed不改变文件内容(除非重定向) sed 命令行格式 $ sed [options] 'command' f ...