WebFlux+HTTP2连接测试

环境

JDK的最低版本是8
Ubuntu 18
Spring Boot 2.1.0.RELEASE
底层使用OpenSLL

在这里插入图片描述

代码

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-transport-native-epoll</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.netty/netty-tcnative-boringssl-static -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-tcnative-boringssl-static</artifactId>
            <version>2.0.19.Final</version>
        </dependency>
    </dependencies>

Http2App.java

@SpringBootApplication
public class Http2App {
    public static void main(String[] args) throws Exception {
        new SpringApplicationBuilder(Http2App.class)
                .web(WebApplicationType.REACTIVE)
                .run(args);
    }

}

服务器启动

reactor.netty.tcp.TcpServerBind类的bind方法初始化SSL环境。
通过reactor.netty.channel.BootstrapHandlers类的finalizeHandler方法绑定初始handler。

最重要的handler是io.netty.handler.ssl.SslHandler。
它的主要功能是提供对SSL、TLS和StartTLS支持:

  • 开始握手
  • 握手,一旦开始以后就是自动的
  • 关闭SSL session(向对端发送close_notify消息),SSL session关闭以后就不可用了,你得增加新的
  • 重新开始一个SSL session,你要先在ChannelPipeline里删除已经关闭的SslHandler。然后再插入一个带有SSLEngine的SslHandler,然后开始握手
  • 实现StartTLS。StartTLS一般分三步:
    • 客户端发送StartTLS请求
    • 服务器发送StartTLS响应
    • 客户端开始SSL握手

服务器启动的时候,reactor.netty.http.server.HttpServerBind类apply方法,还完成了Http1OrH2Initializer的初始化工作。

				return BootstrapHandlers.updateConfiguration(b,
						NettyPipeline.HttpInitializer,
						new Http1OrH2Initializer(conf.decoder.maxInitialLineLength,
								conf.decoder.maxHeaderSize,
								conf.decoder.maxChunkSize,
								conf.decoder.validateHeaders,
								conf.decoder.initialBufferSize,
								conf.minCompressionSize,
								compressPredicate(conf.compressPredicate, conf.minCompressionSize),
								conf.forwarded,
								conf.cookieEncoder,
								conf.cookieDecoder));


注册了reactor.netty.http.server.HttpServerBind$Http1OrH2Codec
Http1OrH2Codec最终注册了流处理器Http2StreamBridgeHandler和Http2StreamFrameToHttpObjectCodec。

增加sslHandler

reactor.netty.tcp.SslProvider$SslSupportConsumer类的accept方法生成sslHandler

    sslHandler = sslProvider.getSslContext().newHandler(channel.alloc());

上面的方法,调用的是io.netty.handler.ssl.ReferenceCountedOpenSslContext类的下面的方法。其中,jdkCompatibilityMode是false

    @Override
    protected final SslHandler newHandler(ByteBufAllocator alloc, boolean startTls) {
        return new SslHandler(newEngine0(alloc, null, -1, false), startTls);
    }

握手过程

在这里插入图片描述

具体的通信过程,由OpenSSL负责。netty-tcnative-boringssl-static主要通过io.netty.internal.tcnative.SSL类完成原生调用。

握手成功,由reactor.netty.tcp.SslProvider$SslReadHandler类处理SslHandshakeCompletionEvent事件。

				if (handshake.isSuccess()) {
					ctx.fireChannelActive();
				}
				else {
					ctx.fireExceptionCaught(handshake.cause());
				}

执行reactor.netty.http.server.HttpServerBind$Http1OrH2Codec类的configurePipeline方法。

p.addLast(NettyPipeline.HttpCodec, http2MultiplexCodecBuilder.build());

请求处理

reactor.netty.http.server.Http2StreamBridgeHandler类的channelRead方法处理Http2HeadersFrame消息。

reactor.netty.http.server.HttpToH2Operations类的onInboundNext方法,处理Http2DataFrame和Http2HeadersFrame消息。
reactor.netty.http.server.HttpServerOperations类的onInboundNext方法处理HttpRequest和HttpContent消息。

猜你喜欢

转载自blog.csdn.net/weixin_43364172/article/details/83658373