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

€¶婷姐儿♛
€¶婷姐儿♛
订阅者
262
文章
0
粉丝
测试交流评论152字数 1365阅读4分33秒阅读模式

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

  • Grpc 服务开发和接口测试初探【Java】 2022-04-20
  • gRPC 服务开发和接口测试初探【Go】 2022-05-07
  • gRPC 三种客户端类型实践【Java 版】 2022-05-11

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

基于以上,下面开始正题。文章源自玩技e族-https://www.playezu.com/179643.html

PS:本篇文章只做性能测试实践,不会测试各类状况下极限性能,所以硬件配置和软件参数就不单独分享了。文章源自玩技e族-https://www.playezu.com/179643.html

服务端

依旧采用了之前的 fun_grpc 项目的 SDK 内容。服务端代码如下:文章源自玩技e族-https://www.playezu.com/179643.html

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();
}
}

实际业务处理类:文章源自玩技e族-https://www.playezu.com/179643.html

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,然后返回响应内容。文章源自玩技e族-https://www.playezu.com/179643.html

客户端

客户端实际使用相对简单,这里就不再分享了,有兴趣的可以读一读文章开头的三篇文章。文章源自玩技e族-https://www.playezu.com/179643.html

静态模型

首先分享一下静态模型的内容,所谓静态内容指的是用例执行之前就设定好了执行的整个过程,用例执行过程除了终止以外没有其他干预措施。文章源自玩技e族-https://www.playezu.com/179643.html

线程模型

下面是基于静态线程模型的性能测试用例文章源自玩技e族-https://www.playezu.com/179643.html

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 模型的压测用例。文章源自玩技e族-https://www.playezu.com/179643.html

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 挖掘机·性能征服者·头顶锅盖

  • 性能测试专题
  • Java、Groovy、Go、Python
  • 单测&amp;白盒
  • FunTester 社群风采
  • 测试理论鸡汤
  • 接口功能测试专题
  • FunTester 视频专题
  • 案例分享:方案、BUG、爬虫
  • UI 自动化专题
  • 测试工具专题

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

 
匿名

发表评论

匿名网友
确定

拖动滑块以完成验证