您现在的位置是:首页 >技术教程 >如何用Jmeter压测Netty的Echo服务之自定义Jmeter的Java Sampler网站首页技术教程

如何用Jmeter压测Netty的Echo服务之自定义Jmeter的Java Sampler

不识君的荒漠 2023-07-19 12:00:02
简介如何用Jmeter压测Netty的Echo服务之自定义Jmeter的Java Sampler

前言

如果想要压测一些三方组件,比如MQ,redis什么的,jmeter本身是不支持的。
本文以开发一个压测netty的echo示例,说明如何自定义jmeter的sampler。

开发

本文以idea示例,

新建工程

打开idea新建一个空的maven工程:
在这里插入图片描述

pom依赖

jmeter的核心依赖:

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>5.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>5.5</version>
        </dependency>

三方依赖,比如我要压测netty,开发一个netty客户端,必然要引入netty相关的依赖:

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-handler</artifactId>
            <version>${netty.version}</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-transport-native-epoll</artifactId>
            <version>${netty.version}</version>
        </dependency>

Echo客户端

这部分代码可以从netty的示例里[io.netty.example.echo.EchoClient]拿过来改改就行:

public class EchoClient {

    static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));

    private Channel channel;

    public EchoClient(String host, int port) {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_SNDBUF, 1024 * 1024)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        p.addLast("flushHandler", new FlushConsolidationHandler(1024, true));
                        p.addLast(new EchoClientHandler());
                    }
                });

        // Start the client.
        try {
            channel = b.connect(host, port).sync().channel();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void write(String message) {
        channel.writeAndFlush(message);
    }
}

开发Jmeter的JavaSampler

@Slf4j
public class EchoTest extends AbstractJavaSamplerClient {

    private String label = "echo";

    private String host;

    private int port;

    private String content;

    private AtomicInteger index = new AtomicInteger(0);

    public static EchoClient client;

    public EchoTest() {
        log.info(this.whoAmI() + "	Construct");
    }

    @Override
    public void setupTest(JavaSamplerContext context) {
        // 读取设置的请求参数
        this.setupValues(context);
        // 注意如果client不是静态的类变量,在jmeter指定并发数的时候,每个线程会创建一个client对象,所以如果需要多少个客户端,根据自己场景调整
        if (client == null) {
            synchronized (EchoTest.class) {
                if (client == null) {
                    client = new EchoClient(this.host, this.port);
                }
            }
        }
    }

    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
        SampleResult results = new SampleResult();

        results.setSentBytes(content.length());
        results.setDataType("text");
        // 用来计算一个请求的耗时的
        results.sampleStart();
        try {
            // 除了这行业务代码,其它可以算是模板范式
            client.write(content);

            results.setResponseOK();
            results.setResponseCodeOK();
            results.setSuccessful(true);
        } finally {
            results.sampleEnd();
        }

        results.setSampleLabel(this.label);
        return results;
    }

    private void setupValues(JavaSamplerContext context) {
        this.host = context.getParameter("Host");
        this.port = context.getIntParameter("Port");
        this.content = context.getParameter("Content");
    }

    /**
     * 这个方法就是在Jmeter上设置的请求参数
     */
    @Override
    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("Host", "127.0.0.1");
        params.addArgument("Port", "8007");
        params.addArgument("Content", "输入内容");

        return params;
    }


    private String whoAmI() {
        return Thread.currentThread() + "@" + Integer.toHexString(this.hashCode());
    }
}

关键地方已经加上注释了,其它场景可以照这个模板走就行。

打包

因为有三方依赖,打包的时候需要把这些依赖也打包进行来,因此使用maven-assembly-plugin插件:

    <build>
        <finalName>${artifactId}</finalName>
        <plugins>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

打包命令:

mvn clean package

打包完成,在target目录下生成如下jar包:
在这里插入图片描述

部署

将打包出来的带有*-with-dependencies.jar的jmeter-echo-jar-with-dependencies.jar放到jmeter的lib/ext目录下:
在这里插入图片描述

启动jmeter

如果打的包没问题的话,启动Jmeter,增加Sampler的时候选择Java Request:
在这里插入图片描述
然后选择我们定义的EchoTest:
在这里插入图片描述
运行下看下效果:
在这里插入图片描述
在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。