zoukankan      html  css  js  c++  java
  • 如何mock固定QPS的接口

    在做接口测试的时候,经常会遇到一些接口去调用其他服务接口,或者调用第三方接口。在进行压测的时候就会遇到问题,因为很难隔离掉其他服务和第三方接口的性能变化情况,虽然单独维护一套压测环境可以解决服务调用的问题,但是这需要很多资源和精力投入,并不一定适合每个团队。至于第三方就更难掌握,能够提供一些性能数据就很不错了。

    为此我们需要用到mock一个固定QPS的接口这样的功能。我的解决方案是基于moco API,利用本身提供的功能做一些尝试,很不幸失败了,在花费一个小时左右翻阅官方文档和实现Demo以及自己尝试发现这条路走不通。

    只能无奈放弃,然后自己拓展这个功能了。采取的方案是JDK中的Semaphore类控制流量,然后通过创建自定义ResponseHandler来完成接口的限流,思路是拿到令牌的请求线程休眠一段时间再去释放令牌完成响应。

    经过我的测试误差都在10%以内,如果是测试方案设计得好,误差应该是5%以内,这里有几条规律:

    • 请求线程越多,误差越小
    • 请求次数越多,误差越小
    • 系统充分预热,误差越小

    测试过程,改天录个视频给大家分享。

    使用Demo

            HttpServer server = getServer(8088)
    
            server.get(urlOnly("/aaa")).response(qps(textRes("faun"), 10))
    
            server.response("haha")
    
            MocoServer drive = run(server)
    
    
            waitForKey("fan")
    
            drive.stop()
    

    封装方法

    
    /**
     * 创建固定QPS的ResponseHandler,默认QPS=1
     * @param handler
     * @return
     */
        static ResponseHandler qps(ResponseHandler handler) {
            QPSHandler.newSeq(handler, 1000)
        }
    
    /**
     * 创建固定QPS的ResponseHandler
     * @param handler
     * @param gap
     * @return
     */
        static ResponseHandler qps(ResponseHandler handler,int gap) {
            QPSHandler.newSeq(handler, gap)
        }
        
    

    ResponseHandler实现类

    
    package com.fun.moco.support
    
    
    import com.github.dreamhead.moco.ResponseHandler
    import com.github.dreamhead.moco.handler.AbstractResponseHandler
    import com.github.dreamhead.moco.internal.SessionContext
    import com.github.dreamhead.moco.util.Idles
    
    import java.util.concurrent.Semaphore
    import java.util.concurrent.TimeUnit
    
    import static com.google.common.base.Preconditions.checkArgument 
    /**
     * 固定QPS的接口实现类
     */
    class QPSHandler extends AbstractResponseHandler {
    
    
        private static final Semaphore semaphore = new Semaphore(1, true);
        /**
         * 访问间隔
         */
        private final int gap
    
        private final ResponseHandler handler
    
        private QPSHandler(ResponseHandler handler, int gap) {
            this.gap = gap
            this.handler = handler
        }
    
        public static ResponseHandler newSeq(final ResponseHandler handler, int gap) {
            checkArgument(handler != null, "responsehandler 不能为空!");
            return new QPSHandler(handler, gap);
        }
    
    
    /**
     * 具体实现,这里采用微秒,实验证明微秒更准确
     * @param context
     */
        @Override
        void writeToResponse(SessionContext context) {
            semaphore.acquire()
            Idles.idle(gap * 1000, TimeUnit.MICROSECONDS)
            handler.writeToResponse(context)
            semaphore.release()
        }
    
    }
    
    

    • 郑重声明:“FunTester”首发,欢迎关注交流,禁止第三方转载。更多原创文章:FunTester十八张原创专辑,合作请联系Fhaohaizi@163.com

    热文精选

  • 相关阅读:
    World Cup
    Eva's Problem
    Number-guessing Game
    WisKey的眼神
    Vowel Counting
    The 3n + 1 problem
    超级楼梯
    母牛的故事
    素数回文
    画8
  • 原文地址:https://www.cnblogs.com/FunTester/p/12970934.html
Copyright © 2011-2022 走看看