How to fix the QPS interface by mock ing

When doing interface testing, we often encounter some interfaces to call other service interfaces, or call third-party interfaces. Problems will be encountered during the pressure test, because it is difficult to isolate the performance changes of other services and third-party interfaces. Although maintaining a set of pressure test environment alone can solve the problem of service invocation, it requires a lot of resources and energy investment, which is not necessarily suitable for each team. As for the third party, it is more difficult to master. It is good to provide some performance data.

So we need to use a fixed QPS interface of mock. My solution is based on moco API Unfortunately, I failed to make some attempts to use the functions provided by myself. I spent an hour or so to read the official documents and implement Demo, and I tried to find that this path would not work.

We can only give up and expand this function ourselves. The solution is to control the traffic by Semaphore class in JDK, and then limit the flow of the interface by creating a user-defined ResponseHandler. The idea is to get the token request thread to sleep for a period of time and then release the token to complete the response.

After my test, the error is within 10%. If the test plan is well designed, the error should be within 5%. Here are several rules:

  • More request threads, less error
  • The more requests, the less error
  • The system is fully preheated, and the smaller the error is

During the test, I will record a video for you to share.

Using Demo

        HttpServer server = getServer(8088)

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


        MocoServer drive = run(server)



Encapsulation method

 * Create the ResponseHandler of fixed QPS, default QPS=1
 * @param handler
 * @return
    static ResponseHandler qps(ResponseHandler handler) {
        QPSHandler.newSeq(handler, 1000)

 * Create the ResponseHandler of fixed QPS
 * @param handler
 * @param gap
 * @return
    static ResponseHandler qps(ResponseHandler handler,int gap) {
        QPSHandler.newSeq(handler, gap)

ResponseHandler implementation class


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 
 * Interface implementation class of fixed QPS
class QPSHandler extends AbstractResponseHandler {

    private static final Semaphore semaphore = new Semaphore(1, true);
     * Access interval
    private final int gap

    private final ResponseHandler handler

    private QPSHandler(ResponseHandler handler, int gap) { = gap
        this.handler = handler

    public static ResponseHandler newSeq(final ResponseHandler handler, int gap) {
        checkArgument(handler != null, "responsehandler Cannot be empty!");
        return new QPSHandler(handler, gap);

 * We use microseconds here. Experiments show that microseconds are more accurate
 * @param context
    void writeToResponse(SessionContext context) {
        Idles.idle(gap * 1000, TimeUnit.MICROSECONDS)


  • Solemnly declare that "FunTester" is launched, welcome to pay attention to communication and prohibit third party reprint. More original articles: FunTester 18 original albums , please contact .

Hot text selection

Tags: Programming github Java less JDK

Posted on Tue, 26 May 2020 21:19:00 -0700 by shyish