Introduction

The classic TCP three-way handshake should be familiar to everyone. The three-way handshake should be the optimal solution. Of course, this is for general situations. So in some special cases, is it possible to improve the speed of TCP connection establishment?

The answer is yes, this is the TCP fast open and netty we are going to talk about today.

TCP fast open

What is TCP fast open?

TCP fast open can also be abbreviated as TFO, which is an extension of the TCP protocol. Why fast open? This is because TFO can bring some data when initializing the connection establishment, so that after the TCP connection is established, the number of interactions with the server can be reduced, thereby reducing the response time under certain circumstances.

Since TFO is so good, why do we rarely see the TFO protocol used?

This is because TFO is defective, because TFO will carry some data information in the sync packet, so when the sync packet is retransmitted, it will cause the receiver to receive duplicate data.

Therefore, if TFO is used, the receiver needs to have the ability to handle duplicate data.

In the programming world, preventing repeated submission of data has a nice name called idempotency, and only servers with idempotency can use TFO.

Turn on TFO

Since TFO is so good, how can TFO be turned on?

The opening of TFO first requires the support of the operating system. If you are a mac system, congratulations, mac already supports TFO by default, and you do not need to do anything.

If you are a Linux system, then you need to view the file /proc/sys/net/ipv4/tcp_fastopen.

tcp_fastopen can have four values, as follows:

0 -- means TFO is not enabled
1 -- Indicates that TFO is enabled, but only valid for the client
2 -- Indicates that TFO is enabled, but only valid for the server side
3 -- Indicates that TFO is enabled, valid for both client and server

Through the above settings, we have enabled TFO support at the operating system layer.

Next, let's take a look at how to use TFO in netty.

netty support for TFO

First, let's see how to enable TFO support on the server side of netty.

Before that, let's review how to suggest a normal netty server:

EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new TFOServerHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口并开始接收连接
            ChannelFuture f = b.bind(port).sync();

In the above code, we see that ServerBootstrap can set the option parameter. ChannelOption contains all the channel parameters that can be set. The corresponding TFO parameter is ChannelOption.TCP_FASTOPEN, so we only need to add it to ServerBootstrap:

sb.option(ChannelOption.TCP_FASTOPEN, 50)

The value of ChannelOption.TCP_FASTOPEN indicates the number of fast-open requests that can be in a waiting state in the socket connection.

For the client, some changes also need to be made. Let's take a look at how the traditional client works:

 EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new TFOClientHandler());
                 }
             });

            // 连接服务器
            ChannelFuture f = b.connect(HOST, PORT).sync();

To support TFO, the client needs to add such an operation:

b.option(ChannelOption.TCP_FASTOPEN_CONNECT, true)

Remember what TFO does? TFO is to send some data in the sync packet. So we need to process the sent data on the client side, that is to say, we need to send a message to the channel before the client and server side establish a connection.

To get a non-connected channel, you can call Bootstrap's register method to get the channel:

Channel channel = b.register().sync().channel();

Then write byteBuf to the channel:

ByteBuf fastOpenData = directBuffer();
            fastOpenData.writeBytes("TFO message".getBytes(StandardCharsets.UTF_8));
            channel.write(fastOpenData);

Finally, establish a connection with the server:

// 连接服务器
            SocketAddress serverAddress =  SocketUtils.socketAddress("127.0.0.1", 8000);
            ChannelFuture f = channel.connect(serverAddress).sync();

Summarize

Such a client and server that supports TFO are completed. Feel free to use it.

Examples of this article can refer to: learn-netty4

This article has been included in http://www.flydean.com/44-netty-tcp-fast-open/

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!


flydean
890 声望433 粉丝

欢迎访问我的个人网站:www.flydean.com