Home Apache jmeter
Post
Cancel

Apache jmeter

Apache Jmeter

image

Download Release 클릭 후 나는 apache-jmeter-5.6.3.zip 다운받았다.

파일 압축을 해제 한 후 bin 파일에 들어가서

ApacheJMeter.jar 파일을 실행하면 jmeter가 실행된다.

window인 나는 jmeter.bat을 실행했다.






JMeter plugin

link

image

이렇게 검색해도 된다.




image

해당 이미지처럼 클릭해서 플러그인 매니저를 다운받는다.

jmeter 압축해제 한 뒤 해당 파일을 jmeter 폴더의 lib/ext 안에 넣어준다.




JMeter를 재시작 하면 아래와 같이 플러그인을 설치할 수 있게 메뉴가 생겼다.

image






Http Test

Thread 설정

JMeter에서 Test Plan 우클릭 → add → Thread(Users) → Thread Group을 하여 Thread Group을 생성한다.

image

1) Number of Threads (users) : 쓰레드 개수 → 사용자 수



2) Ramp-Up Period (in seconds) : 쓰레드 당 생성시간

1
2
3
4
5
Number of Threads = 1000이고 Ramp-up = 10 일 때, 1000명의 유저를 생성하는데 10초가 걸린다.

→ 1초 동안 100명의 유저가 요청을 한다

Ramp-up = 0 으로 설정하면, 동시 접속 자 수는 1000명이 된다.



3) Loop Count : Thread당 수행할 테스트 횟수

1
2
3
Number of Threads = 1000 이고 Loop Count = 10 일 때, 1000명의 유저는 동일한 작업을 10번 수행하게 된다.

따라서 총 1000 * 10 = 10000 번 수행되고, 총 요청 횟수로 생각할 수 있다.






WebSocket Test

WebSockeet Sampler 플러그인을 설치한다.

options 탭 → Plugins Manager → Available Plugins 탭 클릭 → WebSocket Sampler by Peter Doornbosch를 체크

우측 하단의 Apply Changes and Restart JMeter버튼 클릭

image



image

WebSocket Close: WebSocket 연결을 닫는 작업을 테스트한다.
→ WebSocket 연결의 안정성과 정상적인 종료 상황을 확인

WebSocket Open Connection: WebSocket 서버에 연결을 연다.
→ WebSocket 연결 설정이 올바른지 확인하고, 연결이 성공적으로 이루어지는지 확인

WebSocket Ping/Pong: WebSocket 통신 중에 Heartbeat 메시지를 보내고 받아서 연결의 활성 상태를 유지하는지 테스트한다.
→ 서버와의 연결 유지 여부를 확인

WebSocket Single Read Sampler: WebSocket에서 메시지를 읽어오는 작업을 테스트한다.
→ 서버로부터의 응답을 확인하거나 특정 이벤트를 감지

WebSocket Single Write Sampler: WebSocket으로 메시지를 전송하는 작업을 테스트한다.
ex) 채팅 메시지를 보내는 등의 작업 테스트

WebSocket Request-Response Sampler: WebSocket을 통해 요청을 보내고, 서버로부터의 응답을 받는 작업을 테스트한다.
→ 요청과 응답 간의 시간을 측정하고, 성능을 평가



MessageMapping으로 채팅 메시지를 보내는 경우에는 WebSocket Single Write Sampler를 사용하면 될 것 같고

EventListener를 통해 연결 및 종료 이벤트를 감지하는 경우에는

각각 WebSocket Open Connection 및 WebSocket Close Sampler를 사용하면 될 것 같다.

image







test

login

채팅을 하기 전 header에 token을 담기 위해서 login 먼저 진행했다.



Thread Group

Thread Group 안에 HTTP Request, Debug Sampler, View Results Tree 추가

Thread Group > Add > Sampler > HTTP Request
Thread Group > Add > Listener > View Results Tree
Thread Group > Sampler > Debug Sampler

image





HTTP Request

Body Data에 json형식으로 nickname과 password를 작성한다.

1
2
3
4
{
    "nickname" : "nick.123",
    "password" : "nick.123"
}

image





HTTP Header Manager

HTTP request > Add > Config Element > HTTP Header Manager

HTTP Header Manager에 Name = Content-type, Value = application/json를 추가한다.

image





View Results Tree

Response data > Response Body로 보면 아래와 같은 형식으로 응답이 온다.

{"success":true, "role_check":"사용자","token":"token1234","username":"nick.123"}





Regular Expression Extractor

HTTP request > Add > Post Processor > Regular Expression Extractor

응답이 온 값들 중 token만 값을 저장하려고 한다.

  • Name of created variable : token
  • Regular Excpression : "token":"([^"]+)"
  • Template : $1$
  • Match No. : 1

image




token이 추출 된 것을 볼 수 있다.

image





BeanShell PostProcessor

HTTP request > Add > Post Processor > BeanShell PostProcessor

Debug Sampler에서 추출한 token 값을 넣었다.

1
2
3
import org.apache.jmeter.protocol.http.control.Header;

sampler.getHeaderManager().add(new Header("Authorization",vars.get("token")));

image





로그인 후의 http request

게시글 조회로 test를 해봤다.

HTTP Request를 만들고 HTTP Header Manager에 token을 넣어준다.

image

image






Chat

전체 보기

image



참고로 모든 요청에 HTTP Header Manager를 생성하여 아래와 같이 작성했다.

image

*simpSessionId는 아래에서 설명 예정




WebSocket Open Connection

Thread Group > Add > Sampler > WebSocket Open Connection

Stomp 프로토콜을 사용하여 통신하는 엔드포인트는 /ws 다.

채팅을 할 때 network로 해당 url을 살펴보면 아래와 같이 보여진다.

ws://localhost:8080/ws/${유저 번호}/${세션 식별자}/websocket



이를 Server URL에 작성하면 ws, localhost, 8080으로 작성할 수 있다.

image



여기서 Path는 ws/${유저 번호}/${세션 식별자}/websocket인데

유저번호를 3자릿수로, 세션 식별자를 8자릿수로 설정했다.




변수 추가

image



user number

Thread Group > HTTP Request > Add > Config Element > Random Variable

100~999 랜덤 숫자

image




session

Thread Group > HTTP Request > Add > Config Element > User Defined Variables

a~z 중 랜덤 8자리

Name = sessionId, Value = ${__RandomString(8,abcdefghijklmnopqrstuvwxyz)}

image



따라서 path는 /ws/${num}/${sessionId}/websocket로 설정할 수 있다.

image



작성 후에 실행하면 성공적으로 띄워지는 것을 볼 수 있다.

image


이제 채팅을 연결 시켜봤으니 사용자가 해당 채팅을 연결 시켜보는 작업을 진행한다.





Send Connect : WebSocket Single Write Sampler

Thread Group > Add > Sampler > WebSocket Single Write Sampler

image

WebSocket Open Connection”으로 연결을 열어둔 상태에서

“WebSocket Single Write Sampler”로 메시지를 보내기 때문에 use existing connection 적용

Request data :["CONNECTED\nversion:1.2\n\n\u0000"]


만약 config에서 heart-beat를 설정했다면 ["CONNECTED\nversion:1.2\nheart-beat:0,0\n\n\u0000"]와 같이 작성





SEND SUBSCRIBE : WebSocket Single Write Sampler

Thread Group > Add > Sampler > WebSocket Single Write Sampler

image

구독하는 url : /topic/public/${roomId}

Request data : ["SUBSCRIBE\ndestination:/topic/public/room/'${roomId}'\nid:sub-0\n\n\u0000"]

  • \n\n: STOMP 프로토콜에서는 헤더와 본문을 구분하기 위해 빈 줄 (두 개의 연속된 개행 문자)을 사용

  • \u0000: 이는 STOMP 프레임의 끝을 나타내는 NULL 문자



만약 id 값을 넣지 않고 ["SUBSCRIBE\ndestination:/topic/public/room/'${roomId}'\n\n\u0000"] 와 같이 작성했다면

No subscriptionId in GenericMessage 라는 에러가 뜬다.

image



STOMP 프로토콜에서는 클라이언트가 구독(subscribe) 요청을 할 때 필수정인 정보를 전달한다.

  • destination : 구독할 대상의 목적지를 지정한다. (topic이나 queue의 이름)

  • id : 클라이언트가 메시지를 수신할 때 사용할 subscriptionId를 지정한다.

    서버가 클라이언트에게 할당하는 고유한 식별자로써

    클라이언트는 이 subscriptionId를 통해 메시지를 구독하고, 서버는 해당 subscriptionId를 통해 메시지를 전송한다.


1
2
3
>>> SUBSCRIBE
id:sub-0
destination:/topic/public/3d41c3ed-8ddb-458d

Websocket 정리 글을 참고한다.





채팅방 입장(code)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ChatController
@MessageMapping("/chat/addUser")
public void addUser(@Payload ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) {
    // 일부 코드 생략 
    String sessionId = (String) headerAccessor.getHeader("simpSessionId");
    String token = headerAccessor.getFirstNativeHeader("Authorization");
    redisService.addSession(sessionId, token);
    log.info("[chat] addUser token 검사: " + user.getNickname());
    template.convertAndSend("/topic/public/" + roomId, chatMessage);
}

// WebSocketConfig  
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic");
    config.setApplicationDestinationPrefixes("/app");
}

작성해야 할 정보 : token, sessionId, roomId, MessageType, day, time

위 정보들을 request data에 담기 위해서 JSR223 Sampler를 사용했다.



Thread Group > Add > Sampler > JSR223 Sampler

*만약 JSR223 Sampler가 존재하지 않을 경우 Options의 Plugins Manager에서 설치하면 된다.

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
import java.util.UUID;
import java.util.Calendar;
import java.text.SimpleDateFormat;

// 현재 시간을 가져오기 위해 Calendar 객체 생성
Calendar cal = Calendar.getInstance();

// 월과 일을 가져옴 (월은 0부터 시작하므로 1을 더해줌)
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);

// SimpleDateFormat을 사용하여 원하는 형식으로 날짜를 포맷
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd");
String formattedDate = dateFormat.format(cal.getTime());

// 시간과 분을 가져옴
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);

// roomId 생성
String roomId = UUID.randomUUID().toString();

// 생성된 roomId를 JMeter 변수에 할당
vars.put("roomId", roomId);

// 가져온 월과 일을 JMeter 변수에 할당
vars.put("date", formattedDate); 

// 가져온 시간과 분을 JMeter 변수에 할당
vars.put("time", String.valueOf(hour) + ":" + String.valueOf(minute));



Request data :

1
["SEND\ndestination:/app/chat/addUser\nAuthorization:${token}\ncontent-type:application/json\n\n{\"roomId\":\"${roomId}\",\"type\":\"JOIN\",\"day\":\"${date}\",\"time\":\"${time}\"}\n\u0000"]




1
2
3
4
5
6
@MessageMapping("/chat/addUser")
public void addUser(@Payload ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) {
    // 코드 생략 
    log.info("[chat] addUser token 검사: " + user.getNickname());
}

사용자가 채팅방에 접속했을 때 띄워지는 log가 출력되었다.

image





REFERENCE

This post is licensed under CC BY 4.0 by the author.