QPS是接口每秒处理成功的调用次数,RT是处理一次请求所需要的平均时间,并发量是系统能同时处理的请求数。公式:并发量 = QPS * 平均响应时间。
这3个是比较重要的性能指标,如何测试这几个指标呢,可以用工具jmeter,jmeter原生支持http,但像thrift这种rpc接口就需要自己写jmeter的扩展了,可以参考https://www.jianshu.com/p/455e57ab329a。下面不用工具,用java写了一个,主要思路是启动n个线程并发的不断的调用接口一段时间,然后统计计算成功次数,失败次数和平均响应时间,主要用了并发包里的以下几个工具类:
CyclicBarrier:n个线程都到达await时才开始调用接口,模拟并发的感觉。
CountDownLatch:n个线程都运行结束后,主线程才开始统计计算。
LongAdder:计数器,线程安全,AtomicLong的升级版本,类似HashMap和ConcurrentHashMap的区别。
package com.halloffame.thriftjsoa; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.LongAdder; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TFastFramedTransport; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import thrift.test.ThriftTest; import thrift.test.User; public class TestQpsClient { private static LongAdder successCount = new LongAdder(); //成功次数 private static LongAdder failCount = new LongAdder(); //失败次数 private static LongAdder reponseTimeSum = new LongAdder(); //总响应时间,单位:ms private static int threadNum = 12; //线程数 private static int runTime = 60; //线程运行时间,单位:s //cyclicBarrier目的是让所有线程同时运行,模拟并发请求 private static CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum + 1); private static volatile boolean isFinish = false; //结束线程运行标志变量 //countDownLatch目的是所有线程都结束运行后,主线程才统计 private static CountDownLatch countDownLatch = new CountDownLatch(threadNum); public static void main(String[] args) throws Exception { for (int i = 0; i < threadNum; i++) { ReqThread reqThread = new ReqThread(i); reqThread.start(); } cyclicBarrier.await(); Thread.sleep(runTime * 1000); isFinish = true; countDownLatch.await(); long successLongCount = successCount.longValue(); long failLongCount = failCount.longValue(); long reponseTimeLongSum = reponseTimeSum.longValue(); long totalCount = successLongCount + failLongCount; double avgRepTime = reponseTimeLongSum / totalCount; double qps = successLongCount / runTime; double concurrency = qps * (avgRepTime / 1000); System.out.println("成功调用次数:" + successLongCount); System.out.println("失败调用次数:" + failLongCount); System.out.println("平均响应时间:" + avgRepTime + "毫秒"); System.out.println("QPS:" + qps); System.out.println("并发:" + concurrency); } static class ReqThread extends Thread { private int i; public ReqThread(int i){ this.i = i; } @Override public void run() { try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } while ( !isFinish ) { long startTime = System.currentTimeMillis(); User user = null; TTransport transport = null; try { TSocket socket = new TSocket("localhost", 4567); transport = new TFastFramedTransport(socket); transport.open(); TProtocol tProtocol = new TCompactProtocol(transport); ThriftTest.Client testClient = new ThriftTest.Client(tProtocol); user = testClient.getUser(2); } catch (Exception e) { user = null; e.printStackTrace(); } finally { if (transport != null && transport.isOpen()) { transport.close(); } } long endTime = System.currentTimeMillis(); System.out.println("线程" + i + "调用结果:" + user); reponseTimeSum.add(endTime - startTime); if (user != null) { successCount.increment(); } else { failCount.increment(); } } countDownLatch.countDown(); } } }
在我的机器运行的后阶段出现了异常:java.net.BindException: Address already in use: connect,原因是端口被消耗完,即使socket.close(),端口也不是立即关闭,而是TIME_WAIT状态。可以参考https://blog.csdn.net/ceo158/article/details/9311065增大可分配的tcp连接端口数,减小处于TIME_WAIT状态的连接的生存时间。
代码已经放在GitHub:https://github.com/halloffamezwx/thriftjsoa。
推荐一些文章:
线程安全实现与CLH队列:https://www.jianshu.com/p/0f6d3530d46b。
ThreadLocalMap里弱引用:https://blog.csdn.net/vicoqi/article/details/79743112。
感谢阅读!!!
相关推荐
在"Apache Thrift 初学小讲(五)【代理】"这篇博文中,我们将探讨Thrift如何实现代理服务,这在分布式系统中非常关键,因为代理可以提供负载均衡、安全控制、监控等功能。 1. **接口定义语言(IDL)**:Thrift ...
在本篇初学小讲中,我们将重点关注Thrift在负载均衡方面的应用,这对于构建大型分布式系统至关重要。Thrift通过提供一种高效的数据序列化机制以及RPC(远程过程调用)接口,使得不同编程语言之间可以轻松地进行通信...
在本篇小讲中,我们将探讨如何将Thrift与Spring框架结合,以便于构建微服务架构。 首先,让我们了解Thrift的基本工作原理。Thrift IDL(接口定义语言)允许开发者声明服务方法和数据类型,类似于Java中的接口或C++...
在“Apache Thrift 初学小讲(三)【http】”中,我们将深入探讨Thrift如何与HTTP协议相结合,实现基于HTTP的服务通信。 首先,Thrift 提供了一个名为 `ThriftServlet` 的组件,它是将Thrift服务与Java Servlet容器...
Apache Thrift is an open source cross language serialization and RPC framework. With support for over 15 programming languages, Apache Thrift can play an important role in a range of distributed ...
Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、跨语言的服务。它结合了接口定义语言(IDL)和库,允许开发者定义数据结构和服务接口,然后自动生成多种编程语言的代码,使得不同语言之间可以高效地进行...
Thrift 提供了一个集成的代码生成工具,允许开发者定义数据类型和服务接口,然后自动生成多种编程语言(如 C++ 和 Java)的客户端和服务器端代码,实现高效、可靠的远程过程调用(RPC)。 在 Ubuntu 系统下安装 ...
本例改编自Apache Thrift教程: http://mikecvet.wordpress.com/2010/05/13/apache-thrift-tutorial-the-sequel/ http://chanian.com/2010/05/13/thrift-tutorial-a-php-client/ 原教程使用的是c++ server和...
第二部分-编程Apache Thrift 本部分深入研究Apache Thrift框架的每一层,详细检查传输,协议,类型,服务,服务器和Apache Thrift接口定义语言。 这些章节中的示例使用C ++,Java和Python作为演示语言。 C ++示例...
Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、跨语言的服务。它结合了编译器、协议和库,使得开发人员能够轻松地定义数据类型和服务接口,然后在多种编程语言之间进行高效通信。这个框架最初由Facebook...
Apache Thrift 是一款开源的软件框架,主要用于构建可扩展且跨语言的服务。它结合了编译器和库,能够高效地构建分布式系统。在Java领域,Thrift 提供了一种简洁的方式来实现远程过程调用(RPC)服务。在这个实战源码...
Apache Thrift——可伸缩的跨语言服务开发框架 Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用框架。它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码...
在压缩包文件"thrift-demo"中,可能包含了Thrift的示例代码,这些代码展示了如何定义服务接口,如何生成和使用客户端及服务器端代码,以及如何运行和测试Thrift服务。 总的来说,Apache Thrift是一个强大且实用的...
该项目是《RPC框架实践之:Apache Thrift》博文所对应的实践设计源码,总计包含30个文件,其中Java源文件8个,XML配置文件3个,属性文件2个,以及其他文件如DS_Store、LICENSE和md等。该项目通过SpringBoot整合...
FacebookThrift最初是紧跟Apache Thrift发行的,但现在朝着新的方向发展。 特别是,编译器是从头开始重写的,新的实现具有完全异步的Thrift服务器。 在了解有关这些改进的。 您还可以在原始的Facebook Code 了解...
Apache Thrift是一个开源的软件框架,它用于构建跨语言的服务。这个实例包含了Thrift的使用方法和必要的库文件,帮助开发者在不同的编程语言之间实现高效、简洁的数据通信。Thrift通过定义一种中间表示(IDL,...
Apache Thrift 是一个高效、跨语言的服务开发框架,起源于 Facebook 为了解决大规模系统间通信问题而设计。Thrift 充当着一个中间件的角色,允许开发者定义数据结构和服务接口,然后自动生成不同编程语言的代码,...