[Testing] nGrinder로 Spring Boot WAS의 성능을 테스트해보자

Posted by qwlake on May 20, 2021

nGrinder

naver/ngrinder

설치 및 실행

1
2
3
4
5
docker pull ngrinder/controller
docker run -it -v ~/ngrinder-controller:/opt/ngrinder-controller --name controller -p 80:80 -p 16001:16001 -p 12000-12009:12000-12009 ngrinder/controller

docker pull ngrinder/agent
docker run -d --name agent --link controller:controller ngrinder/agent

windows의 경우 80포트가 system에 의해 사용되고 있을 수도 있음. 그럴 경우 아래 명령어를 cmd에 입력하여 포트 확보.

1
net stop W3SVC

Option

Monitor 실행

Installation-Guide#install-monitor

테스트 스크립트 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
// import static net.grinder.util.GrinderUtils.* // You can use this if you're using nGrinder after 3.2.3
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith

import org.ngrinder.http.HTTPRequest
import org.ngrinder.http.HTTPRequestControl
import org.ngrinder.http.HTTPResponse
import org.ngrinder.http.cookie.Cookie
import org.ngrinder.http.cookie.CookieManager

/**
* A simple example using the HTTP plugin that shows the retrieval of a single page via HTTP.
*
* This script is automatically generated by ngrinder.
*
* @author admin
*/
@RunWith(GrinderRunner)
class TestRunner {

    public static GTest test
    public static HTTPRequest request
    public static Map<String, String> headers = [
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
        "Origin":"https://dev-www.carrotins.com"
    ]
    public static Map<String, Object> params = [:]
    public static List<Cookie> cookies = []
    // public static List<String> osTypes = ["PC_WEB", "MOBILE_WEB", "IOS", "ANDROID"]
    // public static List<String> platformTypes = ["PC_WEB", "MOBILE_WEB", "MOBILE_APP"]
    public static List<String> args = [
        ["PC_WEB", "PC_WEB"],
        ["MOBILE_WEB", "MOBILE_WEB"],
        ["MOBILE_WEB", "IOS"],
        ["MOBILE_WEB", "ANDROID"]
    ]
    public static Random r = new Random()

    @BeforeProcess
    public static void beforeProcess() {
        HTTPRequestControl.setConnectionTimeout(300000)
        test = new GTest(1, "127.0.0.1")
        request = new HTTPRequest()
        grinder.logger.info("before process.")
    }

    @BeforeThread
    public void beforeThread() {
        test.record(this, "test")
        grinder.statistics.delayReports = true
        grinder.logger.info("before thread.")
    }

    @Before
    public void before() {
        request.setHeaders(headers)
        CookieManager.addCookies(cookies)
        grinder.logger.info("before. init headers and cookies")
    }

    @Test
    public void test() {
        // String url = "http://172.29.11.157:8080/cms/area/${r.nextInt(2)+1}?platformType=${platformTypes.get(r.nextInt(3))}&osType=${osTypes.get(r.nextInt(4))}"
        List list = args.get(r.nextInt(4))
        String url = "http://172.29.11.157:8080/cms/area/${r.nextInt(2)+1}?platformType=${list.get(0)}&osType=${list.get(1)}"
        HTTPResponse response = request.GET(url, headers=headers)
        assert 200 <= response.statusCode && response.statusCode < 300
    }
}

프로세스를 도커로 실행시킬 경우 localhost는 프로세스가 속한 컨테이너를 의미한다는걸 기억하자

테스트 실행

nGrinder 테스트 실행 중 TPS가 잘 올라가다가 Connection refused 에러가 발생할 경우 Connection reset on each test run 옵션을 체크 해제해 보자

테스트 결과

output.csv

image

Issue

  • locust 로 테스트 할 때는 TPS 700 / respomse time 200ms 수준이였는데 nGrinder로 할 때는 왜 성능이 더 좋게 나오는지?
  • 레디스 사용 안 하고 DB에 select를 날리는 api를 부하 테스트하니 TPS와 Response Time이 미쳐 날뜀. 편차도 심하고 TPS가 갑자기 하락하는 경우도 부지기수

    → dev-www db(maria)를 사용하면 다른 양상을 보이는 것으로 보아 db i/o 문제인듯

    → db global variables 중에서 connection 관련 변수를 dev-www와 똑같이 조정해 보아도 여전함

    → spring boot의 db connection 관련 변수를 다른 프로젝트의 변수와 동일하게 조정해도 마찬가지

    → spring web + jdbc 조합에서만 이 문제가 발생하는 것으로 보아, 이 조합에서 was가 스레드를 많이 먹어서 db가 제대로 성능을 발휘하지 못했나?

    image