概述
Http2UpgradeHandler按照HTTP/2协议规范处理http/2 stream,处理流程如下:
- 解析HTTP2-Setting头部域
- 处理客户端发送的连接前言(connection preface)
- 发送连接前言给客户端
- 在Endpoint的WorkThread线程池中,处理stream
Http2UpgradeHandler#init()方法
不了解从何处开始调用Http2UpgradeHandler#init()的朋友可参阅tomcat9.0源码分析之NioEndpoint(二)—— Http11Processor
传入的参数是UpgeadeProcessorInternal
@Override
public void init(WebConnection webConnection) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.init", connectionId, connectionState.get()));
}
if (!connectionState.compareAndSet(ConnectionState.NEW, ConnectionState.CONNECTED)) {
return;
}
// Init concurrency control if needed
if (protocol.getMaxConcurrentStreamExecution() < localSettings.getMaxConcurrentStreams()) {
streamConcurrency = new AtomicInteger(0);
queuedRunnable = new ConcurrentLinkedQueue<>();
}
parser = getParser(connectionId);
Stream stream = null;
socketWrapper.setReadTimeout(protocol.getReadTimeout());
socketWrapper.setWriteTimeout(protocol.getWriteTimeout());
//如果UpgeadeProcessorInternal不为null
if (webConnection != null) {
// HTTP/2 started via HTTP upgrade.
// The initial HTTP/1.1 request is available as Stream 1.
try {
// Process the initial settings frame
//处理setting frame
stream = getStream(1, true);
//读取请求头的Http2-setting参数
String base64Settings = stream.getCoyoteRequest().getHeader(HTTP2_SETTINGS_HEADER);
byte[] settings = Base64.decodeBase64(base64Settings);
// Settings are only valid on stream 0
FrameType.SETTINGS.check(0, settings.length);
for (int i = 0; i < settings.length % 6; i++) {
int id = ByteUtil.getTwoBytes(settings, i * 6);
long value = ByteUtil.getFourBytes(settings, (i * 6) + 2);
remoteSettings.set(Setting.valueOf(id), value);
}
} catch (Http2Exception e) {
throw new ProtocolException(
sm.getString("upgradeHandler.upgrade.fail", connectionId));
}
}
// Send the initial settings frame
//发送setting frame
writeSettings();
// Make sure the client has sent a valid connection preface before we
// send the response to the original request over HTTP/2.
try {
//读取HTTP/2的连接前言
parser.readConnectionPreface();
} catch (Http2Exception e) {
String msg = sm.getString("upgradeHandler.invalidPreface", connectionId);
if (log.isDebugEnabled()) {
log.debug(msg);
}
throw new ProtocolException(msg);
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.prefaceReceived", connectionId));
}
// Send a ping to get an idea of round trip time as early as possible
try {
pingManager.sendPing(true);
} catch (IOException ioe) {
throw new ProtocolException(sm.getString("upgradeHandler.pingFailed"), ioe);
}
//如果UpgeadeProcessorInternal不为null
if (webConnection != null) {
//处理stream
processStreamOnContainerThread(stream);
}
}
Http2UpgradeHandler#processStreamOnContainerThread()方法
创建StreamProcessor,在Endpoint的WorkThread线程池中,调用StreamProcessor处理Stream
private void processStreamOnContainerThread(Stream stream) {
StreamProcessor streamProcessor = new StreamProcessor(this, stream, adapter, socketWrapper);
streamProcessor.setSslSupport(sslSupport);
processStreamOnContainerThread(streamProcessor, SocketEvent.OPEN_READ);
}
void processStreamOnContainerThread(StreamProcessor streamProcessor, SocketEvent event) {
StreamRunnable streamRunnable = new StreamRunnable(streamProcessor, event);
if (streamConcurrency == null) {
socketWrapper.execute(streamRunnable);
} else {
//如果该条tcp连接的流并发 小于协议设置的最大流并发
if (getStreamConcurrency() < protocol.getMaxConcurrentStreamExecution()) {
increaseStreamConcurrency();
//直接放入Endpoint的workThread线程池中执行
socketWrapper.execute(streamRunnable);
} else {
//否则放入queuedRunnable队列
queuedRunnable.offer(streamRunnable);
}
}
}
SocketWrapperBase#execute()方法
在 AbstractEndpoin的WorkThread线程池中,处理SreamRunnable
/**
* Transfers processing to a container thread.
*
* @param runnable The actions to process on a container thread
*
* @throws RejectedExecutionException If the runnable cannot be executed
*/
public void execute(Runnable runnable) {
Executor executor = endpoint.getExecutor();
if (!endpoint.isRunning() || executor == null) {
throw new RejectedExecutionException();
}
executor.execute(runnable);
}
AbstractEndpoint的WorkThread线程池
略,可参阅 tomcat 9.0源码分析之NioEndpoint —— Reactor多线程模型实现
StreamRunnable的run()方法逻辑
调用StreamProcessor#process()方法处理SocketEvent
class StreamRunnable implements Runnable {
private final StreamProcessor processor;
private final SocketEvent event;
public StreamRunnable(StreamProcessor processor, SocketEvent event) {
this.processor = processor;
this.event = event;
}
@Override
public void run() {
processor.process(event);
}
}
StreamProcessor
StreamProcessor的继承关系如下:
StreamProcessor#process()方法
final void process(SocketEvent event) {
try {
// FIXME: the regular processor syncs on socketWrapper, but here this deadlocks
synchronized (this) {
// HTTP/2 equivalent of AbstractConnectionHandler#process() without the
// socket <-> processor mapping
ContainerThreadMarker.set();
SocketState state = SocketState.CLOSED;
try {
state = process(socketWrapper, event);
if (state == SocketState.CLOSED) {
if (!getErrorState().isConnectionIoAllowed()) {
ConnectionException ce = new ConnectionException(sm.getString(
"streamProcessor.error.connection", stream.getConnectionId(),
stream.getIdentifier()), Http2Error.INTERNAL_ERROR);
stream.close(ce);
} else if (!getErrorState().isIoAllowed()) {
StreamException se = stream.getResetException();
if (se == null) {
se = new StreamException(sm.getString(
"streamProcessor.error.stream", stream.getConnectionId(),
stream.getIdentifier()), Http2Error.INTERNAL_ERROR,
stream.getIdAsInt());
}
stream.close(se);
}
}
} catch (Exception e) {
String msg = sm.getString("streamProcessor.error.connection",
stream.getConnectionId(), stream.getIdentifier());
if (log.isDebugEnabled()) {
log.debug(msg, e);
}
ConnectionException ce = new ConnectionException(msg, Http2Error.INTERNAL_ERROR);
ce.initCause(e);
stream.close(ce);
} finally {
ContainerThreadMarker.clear();
}
}
} finally {
handler.executeQueuedStream();
}
}
AbstractProcessorLight#process()方法
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
throws IOException {
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> 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
//StreamProcessor的isUpgrade()方法总是返回false
} 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);
} else {
// Default to closing the socket if the SocketEvent passed in
// is not consistent with the current state of the Processor
state = SocketState.CLOSED;
}
if (getLog().isDebugEnabled()) {
getLog().debug("Socket: [" + socketWrapper +
"], Status in: [" + status +
"], State out: [" + state + "]");
}
if (state != SocketState.CLOSED && isAsync()) {
state = asyncPostProcess();
if (getLog().isDebugEnabled()) {
getLog().debug("Socket: [" + socketWrapper +
"], State after async post processing: [" + state + "]");
}
}
if (dispatches == null || !dispatches.hasNext()) {
// Only returns non-null iterator if there are
// dispatches to process.
dispatches = getIteratorAndClearDispatches();
}
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}