`
halloffame
  • 浏览: 55974 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Apache Thrift 初学小讲(九)【测试接口的QPS】

阅读更多

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

 

感谢阅读!!!

0
0
分享到:
评论

相关推荐

    Apache Thrift 初学小讲(五)【代理】

    在"Apache Thrift 初学小讲(五)【代理】"这篇博文中,我们将探讨Thrift如何实现代理服务,这在分布式系统中非常关键,因为代理可以提供负载均衡、安全控制、监控等功能。 1. **接口定义语言(IDL)**:Thrift ...

    Apache Thrift 初学小讲(七)【负载均衡】

    在本篇初学小讲中,我们将重点关注Thrift在负载均衡方面的应用,这对于构建大型分布式系统至关重要。Thrift通过提供一种高效的数据序列化机制以及RPC(远程过程调用)接口,使得不同编程语言之间可以轻松地进行通信...

    Apache Thrift 初学小讲(六)【spring】

    在本篇小讲中,我们将探讨如何将Thrift与Spring框架结合,以便于构建微服务架构。 首先,让我们了解Thrift的基本工作原理。Thrift IDL(接口定义语言)允许开发者声明服务方法和数据类型,类似于Java中的接口或C++...

    Apache Thrift 初学小讲(三)【http】

    在“Apache Thrift 初学小讲(三)【http】”中,我们将深入探讨Thrift如何与HTTP协议相结合,实现基于HTTP的服务通信。 首先,Thrift 提供了一个名为 `ThriftServlet` 的组件,它是将Thrift服务与Java Servlet容器...

    the programmer's guide to apache thrift

    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 初学小讲(八)【zookeeper实现服务注册与发现】

    Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、跨语言的服务。它结合了接口定义语言(IDL)和库,允许开发者定义数据结构和服务接口,然后自动生成多种编程语言的代码,使得不同语言之间可以高效地进行...

    Apache Thrift 使用说明

    Thrift 提供了一个集成的代码生成工具,允许开发者定义数据类型和服务接口,然后自动生成多种编程语言(如 C++ 和 Java)的客户端和服务器端代码,实现高效、可靠的远程过程调用(RPC)。 在 Ubuntu 系统下安装 ...

    用C#和C++写的Apache Thrift的小范例

    本例改编自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和...

    ThriftBook:《 Apache Thrift程序员指南》中示例的源代码

    第二部分-编程Apache Thrift 本部分深入研究Apache Thrift框架的每一层,详细检查传输,协议,类型,服务,服务器和Apache Thrift接口定义语言。 这些章节中的示例使用C ++,Java和Python作为演示语言。 C ++示例...

    Learning Apache Thrift

    Apache Thrift 是一个开源的软件框架,用于构建可伸缩的、跨语言的服务。它结合了编译器、协议和库,使得开发人员能够轻松地定义数据类型和服务接口,然后在多种编程语言之间进行高效通信。这个框架最初由Facebook...

    Apache Thrift Java实战源码,包含了客户端和服务端源码

    Apache Thrift 是一款开源的软件框架,主要用于构建可扩展且跨语言的服务。它结合了编译器和库,能够高效地构建分布式系统。在Java领域,Thrift 提供了一种简洁的方式来实现远程过程调用(RPC)服务。在这个实战源码...

    Apache Thrift——可伸缩的跨语言服务开发框架

    Apache Thrift——可伸缩的跨语言服务开发框架 Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用框架。它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码...

    Apache Thrift - 可伸缩的跨语言服务开发框架(代码已修正)

    在压缩包文件"thrift-demo"中,可能包含了Thrift的示例代码,这些代码展示了如何定义服务接口,如何生成和使用客户端及服务器端代码,以及如何运行和测试Thrift服务。 总的来说,Apache Thrift是一个强大且实用的...

    基于SpringBoot的Apache Thrift RPC框架实践设计源码

    该项目是《RPC框架实践之:Apache Thrift》博文所对应的实践设计源码,总计包含30个文件,其中Java源文件8个,XML配置文件3个,属性文件2个,以及其他文件如DS_Store、LICENSE和md等。该项目通过SpringBoot整合...

    fbthrift:Facebook的Apache Thrift分支,包括一个新的C ++服务器

    FacebookThrift最初是紧跟Apache Thrift发行的,但现在朝着新的方向发展。 特别是,编译器是从头开始重写的,新的实现具有完全异步的Thrift服务器。 在了解有关这些改进的。 您还可以在原始的Facebook Code 了解...

    thrift实例以及所需jar包

    Apache Thrift是一个开源的软件框架,它用于构建跨语言的服务。这个实例包含了Thrift的使用方法和必要的库文件,帮助开发者在不同的编程语言之间实现高效、简洁的数据通信。Thrift通过定义一种中间表示(IDL,...

    Apache Thrift说明

    Apache Thrift 是一个高效、跨语言的服务开发框架,起源于 Facebook 为了解决大规模系统间通信问题而设计。Thrift 充当着一个中间件的角色,允许开发者定义数据结构和服务接口,然后自动生成不同编程语言的代码,...

Global site tag (gtag.js) - Google Analytics