如何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
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南