前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何mock固定QPS的接口

如何mock固定QPS的接口

作者头像
FunTester
发布2020-05-27 16:19:49
7840
发布2020-05-27 16:19:49
举报
文章被收录于专栏:FunTesterFunTester

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

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

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

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

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

使用Demo

代码语言:javascript
复制
        HttpServer server = getServer(8088)

        server.get(urlOnly("/aaa")).response(qps(textRes("faun"), 10))

        server.response("haha")

        MocoServer drive = run(server)


        waitForKey("fan")

        drive.stop()

封装方法

代码语言:javascript
复制
/**
 * 创建固定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实现类

代码语言:javascript
复制
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()
    }

}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Demo
  • 封装方法
  • ResponseHandler实现类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档