• gRPC三种Java客户端性能测试实践


    我之前分享了Java和Go语言版本的gRPC接口的服务端和客户端的开发,使用的基本都是基础的原声API,旧文如下:

    经过一段时间的摸索和尝试,我觉得又可以了,今天给大家分享一下三种Java客户端的性能测试实践,其中主要是com.funtester.fungrpc.HelloServiceGrpc#newBlockingStub的性能测试实践。因为在实际的业务测试中这个用的最多,还有阻塞的客户端对于性能测试的指标统计和监控比较友好,对于多接口串联的业务测试来说更贴近HTTP接口的测试,这样能让很多用例思路直接复用。

    基于以上,下面开始正题。

    PS:本篇文章只做性能测试实践,不会测试各类状况下极限性能,所以硬件配置和软件参数就不单独分享了。

    服务端

    依旧采用了之前的fun_grpc项目的SDK内容。服务端代码如下:

    package com.funtester.grpc;
    
    import com.funtester.frame.execute.ThreadPoolUtil;
    import io.grpc.Server;
    import io.grpc.ServerBuilder;
    
    import java.io.IOException;
    import java.util.concurrent.ThreadPoolExecutor;
    
    public class Service {
    
        public static void main(String[] args) throws IOException, InterruptedException {
            ThreadPoolExecutor pool = ThreadPoolUtil.createFixedPool(10, "gRPC");
            Server server = ServerBuilder
                    .forPort(12345)
                    .executor(pool)
                    .addService(new HelloServiceImpl())
                    .build();
    
            server.start();
            server.awaitTermination();
        }
    
    }
    
    

    实际业务处理类:

    package com.funtester.grpc;
    
    import com.funtester.frame.SourceCode;
    import com.funtester.fungrpc.HelloRequest;
    import com.funtester.fungrpc.HelloResponse;
    import com.funtester.fungrpc.HelloServiceGrpc;
    import com.funtester.utils.Time;
    import io.grpc.stub.StreamObserver;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
    
        private static final Logger logger = LogManager.getLogger(HelloServiceImpl.class);
    
        @Override
        public void executeHi(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
            HelloResponse response = HelloResponse.newBuilder()
                    .setMsg("你好 " + request.getName()+ Time.getDate())
                    .build();
            SourceCode.sleep(1.0);
            logger.info("用户{}来了",request.getName());
            responseObserver.onNext(response);
            responseObserver.onCompleted();
        }
    
    }
    
    

    业务上休眠了1s,然后返回响应内容。

    客户端

    客户端实际使用相对简单,这里就不再分享了,有兴趣的可以读一读文章开头的三篇文章。

    静态模型

    首先分享一下静态模型的内容,所谓静态内容指的是用例执行之前就设定好了执行的整个过程,用例执行过程除了终止以外没有其他干预措施。

    线程模型

    下面是基于静态线程模型的性能测试用例:

    package com.funtest.grpc
    
    import com.funtester.base.constaint.FixedThread
    import com.funtester.frame.SourceCode
    import com.funtester.frame.execute.Concurrent
    import com.funtester.fungrpc.HelloRequest
    import com.funtester.fungrpc.HelloServiceGrpc
    import io.grpc.ManagedChannel
    import io.grpc.ManagedChannelBuilder
    
    class FixedThreadModel extends SourceCode {
    
        static int times
    
        static HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub
    
        static HelloRequest requst
    
        public static void main(String[] args) {
            ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 12345)
                    .usePlaintext().build()
    
            helloServiceBlockingStub = HelloServiceGrpc.newBlockingStub(managedChannel).withCompression("gzip")
            requst = HelloRequest.newBuilder()
                    .setName("FunTester")
                    .build()
            RUNUP_TIME = 0
            times = 2000
            new Concurrent(new FunTester(), 10, "静态线程模型").start()
    
            managedChannel.shutdown()
    
        }
    
        private static class FunTester extends FixedThread {
    
    
            FunTester() {
                super(null, times, true)
            }
    
            @Override
            protected void doing() throws Exception {
                helloServiceBlockingStub.executeHi(requst)
            }
    
            @Override
            FunTester clone() {
                return new FunTester()
            }
        }
    
    }
    
    

    QPS模型

    下面是基于静态QPS模型的压测用例。

    package com.funtest.grpc
    
    import com.funtester.base.event.FunCount
    import com.funtester.frame.SourceCode
    import com.funtester.frame.execute.FunEventConcurrent
    import com.funtester.fungrpc.HelloRequest
    import com.funtester.fungrpc.HelloServiceGrpc
    import io.grpc.ManagedChannel
    import io.grpc.ManagedChannelBuilder
    
    class FixedQpsModel extends SourceCode {
    
        static HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub
    
        static HelloRequest requst
    
        public static void main(String[] args) {
            ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 12345)
                    .usePlaintext().build()
    
            helloServiceBlockingStub = HelloServiceGrpc.newBlockingStub(managedChannel).withCompression("gzip")
            requst = HelloRequest.newBuilder()
                    .setName("FunTester")
                    .build()
            def count = new FunCount(1, 1, 2, 1000, 10, "静态QPS模型")
    
            def test= {
                helloServiceBlockingStub.executeHi(requst)
            }
            new FunEventConcurrent(test,count).start()
            managedChannel.shutdown()
    
        }
    
    }
    
    

    以上是两个常用的静态模型的演示,还有其他的动态模型这里就不演示了。

    动态模型

    下面到了喜闻乐见的动态模型的part,动态模型值得是用例执行时都是以固定的最小压力值(通常为1个QPS或者1个线程)启动,然后再用例执行过程中不断调整(调整步长、增减)用例的压力。

    动态线程模型

    由于动态模型是不限制用例运行时间,所以取消了关闭channel的方法。

    package com.funtest.grpc
    
    import com.funtester.base.constaint.FunThread
    import com.funtester.frame.SourceCode
    import com.funtester.frame.execute.FunConcurrent
    import com.funtester.fungrpc.HelloRequest
    import com.funtester.fungrpc.HelloServiceGrpc
    import io.grpc.ManagedChannel
    import io.grpc.ManagedChannelBuilder
    
    import java.util.concurrent.atomic.AtomicInteger
    
    class FunThreadModel extends SourceCode {
    
        static int times
    
        static HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub
    
        static HelloRequest requst
    
        static AtomicInteger index = new AtomicInteger(0)
    
        static def desc = "动态线程模型"
    
        public static void main(String[] args) {
            ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 12345)
                    .usePlaintext().build()
    
            helloServiceBlockingStub = HelloServiceGrpc.newBlockingStub(managedChannel).withCompression("gzip")
            requst = HelloRequest.newBuilder()
                    .setName("FunTester")
                    .build()
            new FunConcurrent(new FunTester()).start()
        }
    
        private static class FunTester extends FunThread {
    
    
            FunTester() {
                super(null, desc + index.getAndIncrement())
            }
    
            @Override
            protected void doing() throws Exception {
                helloServiceBlockingStub.executeHi(requst)
            }
    
            @Override
            FunTester clone() {
                return new FunTester()
            }
        }
    
    }
    
    

    动态QPS模型

    动态QPS模型是我现在最常用的模型,优势多多,除了某些强用户绑定需求外,动态QPS模型都是第一选择。

    package com.funtest.grpc
    
    
    import com.funtester.frame.SourceCode
    import com.funtester.frame.execute.FunQpsConcurrent
    import com.funtester.fungrpc.HelloRequest
    import com.funtester.fungrpc.HelloServiceGrpc
    import io.grpc.ManagedChannel
    import io.grpc.ManagedChannelBuilder
    
    class FunQpsModel extends SourceCode {
    
        static HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub
    
        static HelloRequest requst
    
        public static void main(String[] args) {
            ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 12345)
                    .usePlaintext().build()
    
            helloServiceBlockingStub = HelloServiceGrpc.newBlockingStub(managedChannel).withCompression("gzip")
            requst = HelloRequest.newBuilder()
                    .setName("FunTester")
                    .build()
            def test= {
                helloServiceBlockingStub.executeHi(requst)
            }
            new FunQpsConcurrent(test).start()
    
        }
    
    }
    
    

    以上就是常用的gRPC阻塞客户端四种模型的性能测试全部内容了,欢迎继续关注FunTester。

    BUG挖掘机·性能征服者·头顶锅盖

    阅读原文,跳转我的仓库地址

  • 相关阅读:
    转载一篇关于kafka零拷贝(zero-copy)通俗易懂的好文
    kafka的一些核心理论知识
    Kafka知识点(Partitions and Segments)
    kafka: Producer配置和Consumer配置
    kafka: Java实现简单的Producer和Consumer
    SAP抛xml资料到kafka(本机模拟)
    解决方法: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation
    kafka log保存在本机的位置 kafka数据保存的位置
    Kafka: 下载安装和启动
    tomcat错误提示:指定的服务未安装。Unable to open the service 'tomcat9'的原因和解决方法
  • 原文地址:https://www.cnblogs.com/FunTester/p/16450714.html
Copyright © 2020-2023  润新知