操作系统内核-TCP-调优实战-三次握手-宕机场景模拟演示

本文模拟三种宕机场景,分别演示实际测试效果和TCP调优实践。

程序准备

客户端

org.example.client.Main

package org.example.client;

import com.sun.corba.se.impl.ior.OldJIDLObjectKeyTemplate;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.AttributeKey;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import static java.lang.System.out;

// 按两次 Shift 打开“随处搜索”对话框并输入 `show whitespaces`,
// 然后按 Enter 键。现在,您可以在代码中看到空格字符。
public class Main {

    private static final ExecutorService worker = Executors.newSingleThreadExecutor();

    private static AtomicInteger countConnection = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException {

        int requests = Integer.parseInt(args[0]);

        int connections = args.length > 1 ? Integer.parseInt(args[1]) : 1;

        int threads = args.length > 2 ? Integer.parseInt(args[2]) : 1;

        AtomicInteger count = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(requests);
        CountDownLatch latchConnection = new CountDownLatch(connections);


        NioEventLoopGroup group = new NioEventLoopGroup(threads);
        Bootstrap bootstrap = new Bootstrap()
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new MyChannelInboundHandlerAdapter() {

                    @Override
                    public void channelRegistered(ChannelHandlerContext ctx)
                            throws Exception {
                          Object count =  ctx.channel().attr(AttributeKey.valueOf("count")).get();
                          ctx.channel().attr(AttributeKey.valueOf("count")).set(count);
                          out.println( "第" +count + "个channelRegistered: channel注册到NioEventLoop");
                    }

                    @Override
                    public void channelUnregistered(ChannelHandlerContext ctx)
                            throws Exception {
                        Object count =  ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println( "第" + count + "个channelUnregistered: channel取消和NioEventLoop的绑定");
                        latchConnection.countDown();
                        super.channelUnregistered(ctx);
                    }

                    @Override
                    public void channelActive(ChannelHandlerContext ctx)
                            throws Exception {
                        Object count =  ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println( ctx.channel() + ": channel准备就绪, 第"+ count +"个连接建立成功");
                        latchConnection.countDown();
                        super.channelActive(ctx);
                    }

                    @Override
                    public void channelInactive(ChannelHandlerContext ctx)
                            throws Exception {
                        Object count =ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println( ctx.channel() + ": channel被关闭, 第" + count + "个连接关闭");
                        super.channelInactive(ctx);
                    }

                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg)
                            throws Exception {
                        Object count =ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println( "第" + count + "个channelRead: channel中有可读的数据");
                        super.channelRead(ctx, msg);
                    }

                    @Override
                    public void channelReadComplete(ChannelHandlerContext ctx)
                            throws Exception {
                        Object count =ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println( "第" + count + "个channelReadComplete: channel读数据完成");
                        super.channelReadComplete(ctx);
                    }

                    @Override
                    public void handlerAdded(ChannelHandlerContext ctx)
                            throws Exception {
                        int count = countConnection.incrementAndGet();
                        ctx.channel().attr(AttributeKey.valueOf("count")).set(count);
                        out.println("第" + count + "个handlerAdded: handler被添加到channel的pipeline");
                        super.handlerAdded(ctx);
                    }

                    @Override
                    public void handlerRemoved(ChannelHandlerContext ctx)
                            throws Exception {
                        Object count =ctx.channel().attr(AttributeKey.valueOf("count")).get();
                        out.println("第" + count + "个handlerRemoved: handler从channel的pipeline中移除");
                        super.handlerRemoved(ctx);
                    }
                });

        ChannelFuture[] channels = new ChannelFuture[connections];

        long connectStart = System.currentTimeMillis();
        for (int i = 0; i < connections; i++) {
//            channels[i] = bootstrap.connect("192.168.253.148", 7070);
            channels[i] =  bootstrap.connect("192.168.254.196", 7070)
                    ;
        }

        latchConnection.await();

        long connectEnd = System.currentTimeMillis();



        long start = System.currentTimeMillis();

//        for (int i = 0; i < connections; i++) {
//            if( count.incrementAndGet() <= requests ) {
//                channels[i].writeAndFlush("request");
//            }
//        }

//        latch.await();

        long end = System.currentTimeMillis();

        for (int i = 0; i < connections; i++) {
            channels[i].channel().close()
                    .sync();
        }

        long closeEnd = System.currentTimeMillis();


        group.shutdownGracefully();

        Thread.sleep(2000);
//        long delta = end - start;
//        out.println("总计" + requests + "次请求, 耗时" + delta + "毫秒");
//        out.println("QPS " + requests * 1000L / delta + "次/秒");
        out.println( connections + "个连接建立, 耗时" + (connectEnd - connectStart) + "毫秒");
        out.println("总计" + connections + "个连接, 耗时" + (closeEnd - connectStart) + "毫秒");

        System.exit(0);
    }
}

org.example.client.MyChannelInboundHandlerAdapter

package org.example.client;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInboundHandlerAdapter;

@ChannelHandler.Sharable
public class MyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {


    public MyChannelInboundHandlerAdapter()
    {
        System.out.println("MyChannelInboundHandlerAdapter created");
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>NettyTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.112.Final</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!-- 主动声明插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <!-- 绑定生命周期 -->
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <!-- 设置依赖的存放路径 -->
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
</project>

src/main/resources/logback.xml

<configuration debug="false">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="${logLevel:-info}">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

运行参数

java -Djava.net.preferIPv4Stack=true -Dio.netty.leakDetectionLevel=advanced -Xmx2048m -Xms2048m -cp NettyTest-1.0-SNAPSHOT.jar:lib/*  org.example.client.Main  1 1

场景1 进程宕机

关键代码修改

客户端测试结果

tcpdump分析

场景2 局域网操作系统宕机

关键代码修改

客户端测试结果

tcpdump分析

场景3 广域网操作系统宕机

关键代码修改

客户端测试结果

tcp_syn_retries = 2

tcpdump分析

场景4 广域网操作系统宕机-调优后

调优

客户端测试结果

tcpdump分析

猜你喜欢

转载自blog.csdn.net/shumeizwb/article/details/140752489