Thread-safe class application performance testing

Recently doing a pressure test callback interface after successful payment, the scene is a user purchase VIP, as follows:

testing scenarios

After successful payment user, will end on the back-end request to renew VIP opening and operation.

Interface processing logic

First, the signature verification interface parameters are correct, then locked to judge the order information and status, the user adds VIP treatment time transaction, the lock is released after successful. Locks are distributed locks for users and orders, scheme is used redis.

Document Interface

Interface Basic Information

  1. Interface name purchase a membership or membership renewals
  2. Request Url / api / member / createOrRenewMember
  3. JSON request parameter string down into inspection process to check, request, See endorsement example

Request parameter

{
    "sign": "CGvmkLeGtDv/Om8RbY52pMKNMi/xdLYAgRhIxC3uPqJsEdOvHj+S6zFobN0fxA/vksmCKJHhN6hFQrFIa3C6oK6EH7/BnJEsUMmIRsXMra32lzE/Tq9nqjYIdy996qc6eJWsxshqquj9Tb78pN152ndCNgvujMYsUHT4v7QxUW4=",
    "orderNo": "E2341234",
    "systemId": 94848494
}复制代码

Request Parameter Description

Field Description Field Name Field Type Remark
order number orderNo string Order Number
user account systemId number Will pass
signature sign String Signature string, please provide us with the tools to generate

Return parameters

{
    "code": 0,
    "message": "success",
    "data": {
        "memberId": 123123,
        "systemId": 86123123
    }
}复制代码

code success is equal to 0

Test program

Similar programs reference how to do performance testing on the message queue .

difficulty

  • Because of the lock, a user can simultaneously have an order in the processing, the pressure must be measured each parameter will differ.
  • The user must be present in the user, the user to measure the amount of pressure required is proposed.

solution

  • The user id and order number is parameterized, use AtomicIntegerthe thread-safe class load and a good array of arguments in advance to ensure that every parameter is unique and different from each other. (Random method is not applicable because the probability of repeat performance and consume more)
  • Reserve more users, since the user is acquiring increasing order of acquisition array index, each request does not need to bind a user. After attempts to get 2000 users will be able to meet the demand cycle.

About Java thread safety issues Reference: operation of atomic and thread-safe , quick look, i ++ is really unsafe , atomic operations combined with the thread-safe .

Test Script

Reservations about debugging methods and functions, performance testing framework the third edition there are code references the class.

package com.okayqa.others.payyst

import com.fun.base.constaint.ThreadLimitTimesCount
import com.fun.frame.excute.Concurrent
import com.fun.frame.httpclient.FanLibrary
import com.fun.utils.ArgsUtil
import com.fun.utils.RString
import com.okayqa.common.RSAUtilLJT
import com.okayqa.common.Users
import com.alibaba.fastjson.JSONObject
import org.apache.http.client.methods.HttpPost
import org.slf4j.Logger

import java.util.concurrent.atomic.AtomicInteger

class T extends FanLibrary {

    static Logger logger = getLogger(T.class)


    static AtomicInteger i = new AtomicInteger(111000);

    public static void main(String[] args) {
        def argsUtil = new ArgsUtil(args)
        def thread = argsUtil.getIntOrdefault(0, 1)
        def times = argsUtil.getIntOrdefault(1, 100)
        def reqs = []

        thread.times {
//            def mark = new HeaderMark("requestid")
            reqs << new Thr(times)
        }

        new Concurrent(reqs, "会员支付和续费接口").start()
        testOver()
    }

    static class Thr extends ThreadLimitTimesCount {

        static Logger logger = getLogger(Thr.class)

        public Thr(int times) {
            super(null, times, null);
        }

        @Override
        protected void doing() throws Exception {
            String url = com.okayqa.studentapd.base.OkayBase.HOST+"/api/member/createOrRenewMember"
            Map<String, String> p = new HashMap<>();
            p.put("days", "1");
            p.put("memberId", "208");
            p.put("orderNo", "F" + RString.getString(4) + i.getAndAdd(1));
            p.put("orderPaySystemId", "85123213");
            p.put("orderPayTime", "2020-02-09 10:00:00");
            p.put("payMoney", "30");
            p.put("recordSources", "3");
            p.put("renewal", "false");
            def user = Users.getStuUser(i.getAndAdd(1) % 2000)
//            output(user)
            p.put("systemId", user);
            String sign = RSAUtilLJT.sign(p, RSAUtilLJT.getPrivateKey(RSAUtilLJT.RSA_PRIVATE_KEY));
            p.put("sign", sign);
            HttpPost post = getHttpPost(url, JSONObject.fromObject(p).toString());
            def s = "F" + getNanoMark()
            post.addHeader(getHeader("requestid", s));

            def simlple = FanLibrary.excuteSimlple(post)
            if (!simlple.contains("success")) {
                logger.warn(s + OR + user + simlple.toString())
                fail()
            }
        }

    }
}
复制代码

There is a pit, AtomicIntegerclass, although a thread-safe class, but not all methods are safe, for instance get(), I have used two getAndAdd()methods, although the increase in the amount of time through the loop speed of the user, but the accuracy or most important, after experimental verification 2000 user enough to use.

  • Solemnly declare : The article first appeared in public No. "FunTester", prohibit third parties (except Tencent cloud) reproduce, publish.

Technology Featured articles

Non-technical Selected Articles

Guess you like

Origin juejin.im/post/5e438e9c518825496e784222