我之前分享了Java和Go語言版本的gRPC接口的服務端和客戶端的開發(fā),使用的基本都是基礎(chǔ)的原聲API,舊文如下:
- Grpc服務開發(fā)和接口測試初探【Java】 2022-04-20
- gRPC服務開發(fā)和接口測試初探【Go】 2022-05-07
- gRPC三種客戶端類型實踐【Java版】 2022-05-11
經(jīng)過一段時間的摸索和嘗試,我覺得又可以了,今天給大家分享一下三種Java客戶端的性能測試實踐,其中主要是com.funtester.fungrpc.HelloServiceGrpc#newBlockingStub的性能測試實踐。因為在實際的業(yè)務測試中這個用的最多,還有阻塞的客戶端對于性能測試的指標統(tǒng)計和監(jiān)控比較友好,對于多接口串聯(lián)的業(yè)務測試來說更貼近HTTP接口的測試,這樣能讓很多用例思路直接復用。
基于以上,下面開始正題。
PS:本篇文章只做性能測試實踐,不會測試各類狀況下極限性能,所以硬件配置和軟件參數(shù)就不單獨分享了。
服務端
依舊采用了之前的fun_grpc項目的SDK內(nèi)容。服務端代碼如下:
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(); }}
實際業(yè)務處理類:
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 responseObserver) { HelloResponse response = HelloResponse.newBuilder() .setMsg(“你好 ” + request.getName()+ Time.getDate()) .build(); SourceCode.sleep(1.0); logger.info(“用戶{}來了”,request.getName()); responseObserver.onNext(response); responseObserver.onCompleted(); }}
業(yè)務上休眠了1s,然后返回響應內(nèi)容。
客戶端
客戶端實際使用相對簡單,這里就不再分享了,有興趣的可以讀一讀文章開頭的三篇文章。
靜態(tài)模型
首先分享一下靜態(tài)模型的內(nèi)容,所謂靜態(tài)內(nèi)容指的是用例執(zhí)行之前就設(shè)定好了執(zhí)行的整個過程,用例執(zhí)行過程除了終止以外沒有其他干預措施。
線程模型
下面是基于靜態(tài)線程模型的性能測試用例:
package com.funtest.grpcimport com.funtester.base.constaint.FixedThreadimport com.funtester.frame.SourceCodeimport com.funtester.frame.execute.Concurrentimport com.funtester.fungrpc.HelloRequestimport com.funtester.fungrpc.HelloServiceGrpcimport io.grpc.ManagedChannelimport io.grpc.ManagedChannelBuilderclass 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, “靜態(tài)線程模型”).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模型
下面是基于靜態(tài)QPS模型的壓測用例。
package com.funtest.grpcimport com.funtester.base.event.FunCountimport com.funtester.frame.SourceCodeimport com.funtester.frame.execute.FunEventConcurrentimport com.funtester.fungrpc.HelloRequestimport com.funtester.fungrpc.HelloServiceGrpcimport io.grpc.ManagedChannelimport io.grpc.ManagedChannelBuilderclass 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, “靜態(tài)QPS模型”) def test= { helloServiceBlockingStub.executeHi(requst) } new FunEventConcurrent(test,count).start() managedChannel.shutdown() }}
以上是兩個常用的靜態(tài)模型的演示,還有其他的動態(tài)模型這里就不演示了。
動態(tài)模型
下面到了喜聞樂見的動態(tài)模型的part,動態(tài)模型值得是用例執(zhí)行時都是以固定的最小壓力值(通常為1個QPS或者1個線程)啟動,然后再用例執(zhí)行過程中不斷調(diào)整(調(diào)整步長、增減)用例的壓力。
動態(tài)線程模型
由于動態(tài)模型是不限制用例運行時間,所以取消了關(guān)閉channel的方法。
package com.funtest.grpcimport com.funtester.base.constaint.FunThreadimport com.funtester.frame.SourceCodeimport com.funtester.frame.execute.FunConcurrentimport com.funtester.fungrpc.HelloRequestimport com.funtester.fungrpc.HelloServiceGrpcimport io.grpc.ManagedChannelimport io.grpc.ManagedChannelBuilderimport java.util.concurrent.atomic.AtomicIntegerclass FunThreadModel extends SourceCode { static int times static HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub static HelloRequest requst static AtomicInteger index = new AtomicInteger(0) static def desc = “動態(tài)線程模型” 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() } }}
動態(tài)QPS模型
動態(tài)QPS模型是我現(xiàn)在最常用的模型,優(yōu)勢多多,除了某些強用戶綁定需求外,動態(tài)QPS模型都是第一選擇。
package com.funtest.grpcimport com.funtester.frame.SourceCodeimport com.funtester.frame.execute.FunQpsConcurrentimport com.funtester.fungrpc.HelloRequestimport com.funtester.fungrpc.HelloServiceGrpcimport io.grpc.ManagedChannelimport io.grpc.ManagedChannelBuilderclass 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阻塞客戶端四種模型的性能測試全部內(nèi)容了,歡迎繼續(xù)關(guān)注FunTester。
「BUG挖掘機·性能征服者·頭頂鍋蓋」