聊聊reactor-netty的AccessLogHandlerH2

天大地大妈咪最大 提交于 2019-12-02 15:20:36

本文主要研究一下reactor-netty的AccessLogHandlerH2

AccessLogHandlerH2

reactor-netty-0.8.5.RELEASE-sources.jar!/reactor/netty/http/server/AccessLogHandlerH2.java

final class AccessLogHandlerH2 extends ChannelDuplexHandler {
	static final String H2_PROTOCOL_NAME = "HTTP/2.0";

	AccessLog accessLog = new AccessLog();

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		if (msg instanceof Http2HeadersFrame){
			final Http2HeadersFrame requestHeaders = (Http2HeadersFrame) msg;
			final SocketChannel channel = (SocketChannel) ctx.channel()
			                                                 .parent();
			final Http2Headers headers = requestHeaders.headers();

			accessLog = new AccessLog()
			        .address(channel.remoteAddress().getHostString())
			        .port(channel.localAddress().getPort())
			        .method(headers.method())
			        .uri(headers.path())
			        .protocol(H2_PROTOCOL_NAME);
		}
		super.channelRead(ctx, msg);
	}

	@Override
	public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
		boolean lastContent = false;
		if (msg instanceof Http2HeadersFrame) {
			final Http2HeadersFrame responseHeaders = (Http2HeadersFrame) msg;
			final Http2Headers headers = responseHeaders.headers();
			lastContent = responseHeaders.isEndStream();

			accessLog.status(headers.status())
			         .chunked(true);
		}
		if (msg instanceof Http2DataFrame) {
			final Http2DataFrame data = (Http2DataFrame) msg;
			lastContent = data.isEndStream();

			accessLog.increaseContentLength(data.content().readableBytes());
		}
		if (lastContent) {
			ctx.write(msg, promise)
			   .addListener(future -> {
			       if (future.isSuccess()) {
			           accessLog.log();
			       }
			   });
			return;
		}
		ctx.write(msg, promise);
	}
}

AccessLogHandlerH2是HTTP2的access log的实现,具体针对Http2HeadersFrame及Http2DataFrame进行了判断

HttpServerBind

reactor-netty-0.8.5.RELEASE-sources.jar!/reactor/netty/http/server/HttpServerBind.java

final class HttpServerBind extends HttpServer
		implements Function<ServerBootstrap, ServerBootstrap> {

	//......
		
	static void addStreamHandlers(Channel ch, ConnectionObserver listener, boolean readForwardHeaders,
			ServerCookieEncoder encoder, ServerCookieDecoder decoder) {
		if (ACCESS_LOG) {
			ch.pipeline()
			  .addLast(NettyPipeline.AccessLogHandler, new AccessLogHandlerH2());
		}
		ch.pipeline()
		  .addLast(new Http2StreamBridgeHandler(listener, readForwardHeaders, encoder, decoder))
		  .addLast(new Http2StreamFrameToHttpObjectCodec(true));

		ChannelOperations.addReactiveBridge(ch, ChannelOperations.OnSetup.empty(), listener);

		if (log.isDebugEnabled()) {
			log.debug(format(ch, "Initialized HTTP/2 pipeline {}"), ch.pipeline());
		}
	}

	//......

HttpServerBind的addStreamHandlers静态方法用于判断是否开启access log,开启的话会创建AccessLogHandlerH2并添加到pipeline;Http1OrH2CleartextCodec的initChannel方法以及Http2StreamInitializer的initChannel方法均调用到了此方法

小结

  • AccessLogHandlerH2是HTTP2的access log的实现,具体针对Http2HeadersFrame及Http2DataFrame进行了判断
  • HttpServerBind的addStreamHandlers静态方法用于判断是否开启access log,开启的话会创建AccessLogHandlerH2并添加到pipeline
  • Http1OrH2CleartextCodec的initChannel方法以及Http2StreamInitializer的initChannel方法均调用到了此方法

doc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!