-
nGrinder란? (설치 및 부하 테스트)성능테스트 2023. 1. 8. 00:01728x90
개요
이전 포스팅에서는 nGrinder와 Jmeter에 대해 비교해보고 nGrinder를 사용하고자 했습니다.
nGrinder가 무엇인지 조금 더 상세하게 알아보고 실제로 설치 및 부하 테스트를 진행해보겠습니다.
nGrinder란?
네이버에서 진행한 오픈 소스 프로젝트로 서버의 부하 테스트를 위한 도구입니다.
nGrinder는 어떻게 동작하는가?
nGriner는 2가지의 중요한 컴포넌트인 Controller와 agent로 구성되어 있습니다.
nGrinder Controller
- 성능 테스터가 테스트 스크립트를 생성하고 테스트 실행을 구성할 수 있도록 하는 웹 애플리케이션
Agent
- 대상 시스템에 부하를 주는 가상 사용자 생성기
Target
- 부하 테스트의 대상이 될 서버
nGrinder 설치
우선 자바 설치가 먼저 되어있어야 합니다.
https://github.com/naver/ngrinder/releases
[그림 2 ]참고 - 링크로 접속한 후 가장 최신 버전인 war 파일을 다운로드합니다
nGrinder 실행
다운받은 경로로 이동하여 아래 명령어를 실행시킵니다.
8080 포트는 Spring Boot Application을 띄우기 위해 다른 포트를 사용하도록 하겠습니다. (여기서는 80 포트 활용)
*만약 여러 자바 버전을 가지고 계시다면 유의하시길 바랍니다. (하단에 디버깅 과정 나옴)
java -XX:MaxPermSize=200m -jar ngrinder-controller-3.5.7.war --port 80
nGrinder는 SVNKit, mave, Jetty 서버, groovy, python 등의 라이브러리를 포함하고 있기 때문에 큰 PermGen 메모리를 필요로 합니다.
(문서에서는 옵션을 주지 않으면 에러가 난다고 하는데 사실 저는 에러가 나진 않았습니다)
따라서 해당 옵션을 줍니다.
-XX:MaxPermSize=200m
nGrinder 실행시 java.io.tmpdir 에러 처리
ERROR Please set `java.io.tmpdir` property like following. tmpdir should be different from the OS default tmpdir. `java -Djava.io.tmpdir=${NGRINDER_HOME}/lib -jar ngrinder-controller.war`
http://ngrinder.373.s1.nabble.com/controller-td3268.html
java -Djava.io.tmpdir=/Users/junuu/.ngrinder/lib -jar ngrinder-controller-3.5.8.war --port 7777
-Djava.io.tmpdir=/Users/{사용자마다 다른 user}/.ngrinder/lib 를 주어 해결하였습니다.
nGrinder 접속과 Agent 다운로드
localhost:80 포트에 접속합니다. (위에서 옵션으로 80포트를 주었기 때문 그렇지 않다면 기본값은 8080)
접속하면 [그림 3] 처럼 페이지가 보이며 초기 아이디와 비밀번호는 admin/admin입니다.
로그인 후 [그림 4]처럼 페이지가 보이며 우측 상단의 에이전트 다운로드를 선택합니다.
agent jar 파일을 다운로드 후, 압축을 풀고 다운된 경로로 이동하여 실행시켜 줍니다.
./run_agent.sh
window에서는 이렇게 하면 됩니다.
run_agent.bat
실행 후 결과
스크립트 만들기
상단 내비게이션에서 스크립트로 이동한 후 만들기 -> 스크립트 만들기
이후 [그림 7]에 스크립트명과 http 메서드, url을 입력해줍니다.
스크립트명 : Grinder-test
테스트할 URL(GET) : http://127.0.0.1:8080/stress-test
@RestController @RequestMapping("/stress-test") class NGrinderTestController { @GetMapping fun helloNGrinder(): String{ return "hello" } }
저는 위의 코드처럼 저는 간단하게 "hello"를 반환하는 메서드를 만들어서 테스트해보겠습니다.
이후 만들기를 누르면 다음과 같은 코드가 보입니다.
@RunWith(GrinderRunner) class TestRunner { public static GTest test public static HTTPRequest request public static Map<String, String> headers = [:] public static Map<String, Object> params = [:] public static List<Cookie> cookies = [] @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() { HTTPResponse response = request.GET("http://127.0.0.1:8080/stress-test", params) if (response.statusCode == 301 || response.statusCode == 302) { grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode) } else { assertThat(response.statusCode, is(200)) } } }
만약 POST 요청을 보내고 싶다면 request.POST로 변경하고 이에 적절한 params을 넣어주면 됩니다.
수정한 부분적 예시
public static Map<String, Object> params = ["memberId": "string", "eventName": "eventName1"] headers.put("Content-Type", "application/json") HTTPResponse response = request.POST("http://127.0.0.1:8080/coupons/event", params)
웹 화면에서는 검증을 눌러서 Groovy로 작성한 테스트 코드를 실행시키며, 테스트 결과 요청이 정상적으로 날아갔는지 확인해줍니다.
저는 [그림 8]처럼 무한 검증중이 떠서 그냥 저장하기 눌렀습니다.
* 이때 nGrinder Controller에서 Enter를 치니까 바로 진행되었습니다.
다음과 같은 에러들이 나타납니다.
net.grinder.engine.common.EngineException: Error while initialize test runner
General error during conversion: Unsupported class file major version 60
java.lang.IllegalArgumentException: Unsupported class file major version 60
PC에 설치된 JDK는 11 버전인데 빌드 패스의 기본 JRE설정 및 Java Compiler설정이 JavaSE-16 버전으로 되어있는 게 원인이라고 합니다.
로그 메시지를 보면 16 버전으로 실행되었습니다..
2022-10-26 23:23:59,605 INFO OpenJDK Runtime Environment 16.0.2+7-67: OpenJDK 64-Bit Server VM (16.0.2+7-67, mixed mode, sharing) on Windows 10 amd64 10.0
자바버전은 11로 찍히는데 왜 이럴까요?
실제로 실행시키는 경로에서 다시 java -verison을 찍어보니 다음과 같이 나옵니다.
"C:\Program Files\Java\jdk-9.0.4\bin\java.exe" -jar A.jar
위와 같이하면 특정 버전의 자바로 실행시킬 수 있습니다.
"C:\Program Files\java\jdk-11.0.15.1\bin\java.exe" -XX:MaxPermSize=200m -jar ngrinder-controller-3.5.7.war --port 80
저는 이렇게 실행했습니다.
다시 검증을 해보니 이제 잘 됩니다. ㅎㅎ
실제 성능 측정 시작
상단의 메뉴에서 성능 테스트 -> 테스트 생성으로 이동합니다.
[그림 9]과 같은 화면이 나오게 되며 에이전트는 아까 다운로드하였던 최대 1개를 지정합니다. (여러 agent 지정하면 여러 개도 가능합니다)
일단 가상 사용자를 10명으로 설정해보고 스크립트는 아까 지정한 nGrinder-hello.groovy를 불러옵니다.
이제 저장 후 시작 -> 지금 시작을 눌러줍니다.
이제 [그림 10]처럼 테스트가 하나 생성되고 "1명의 사용자가 테스트를 실행 중에 있습니다."라는 메시지가 보입니다.
[그림 11]은 결과로 1분 동안의 요청에서 TPS는 4,841, MTT는 1.9가 나왔음을 알려줍니다.
TPS(Transaction Per Second) : 초당 처리량 높을수록 좋음
Mean Test Time : 평균 response time(ms 단위)
이후 100명 Ramp-Up, 3000명 10초 No Ramp-Up 등 다양하게 시도해보았습니다.
단순한 "hello"를 반환하는 GET 요청이어서 많은 트래픽을 300ms이내에 처리할 수 있는 모습입니다.
마무리
실제로 성능 테스트를 해보기 전까지는 많이 어려울 것 같다고 예상하였지만, 생각보다 가이드가 좋고 툴이 친절하여 편하게 진행하였습니다.
참고자료
https://naver.github.io/ngrinder/
https://github.com/naver/ngrinder/wiki/Installation-Guide
'성능테스트' 카테고리의 다른 글
[Mac] homebrew jmeter 설치 및 테스트 (0) 2023.11.19 Tomcat Thread의 수는 얼마나 늘리는게 좋을까? (1) 2023.08.09 JVM Memory Leak 만들고 탐지, 개선하기 (2) 2023.07.14 의미있는 성능테스트 (0) 2023.07.09 nGrinder vs Jmeter (1) 2023.01.07