저번 프로젝트에서 ngrinder를 도커로 설정했었는데 이번에 로컬에 설치하려다가 오류에 오류에 오류를 마주치다가 결국 도커로 설정한 썰 푼다
java -Djava.io.tmpdir=/Users/{Myhome}/ngrinder/ngrinder-controller/lib -jar ngrinder-controller-3.5.9.war --port 8080
localhost:8080 으로 접속하여 초기 ID/Password(admin/admin)를 입력
admin>Download Agent 에서 Agent를 다운받아 압축을 출어주고 cmd 창으로 접근하여 agent를 실행
# Agent쉘스크립트 파일 실행
./run_agent.sh
# Agent 백그라운드 실행
./run_agent_bg.sh
Agent Management 로 들어가서 Agent 확인
Script 탭으로 가서 script 작성
하려고 했는데 Script탭으로 안넘어가짐 [1차 오류]
.nGrinder 폴더 삭제 후 다시 기동이 필요하다는 글을 보고 다시 삭제 후 agent 재기동
sudo rm -r .ngrinder
참고 : https://github.com/naver/ngrinder/discussions/968
@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, "192.168.100.104")
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://192.168.100.104:8081/products", 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))
}
}
}
[2차 오류] TPS 그래프가 안그려짐
다시 테스트 만들어서 테스트 실행하니 [3차 오류]테스트 무반응 현상..
Agent 를 확인해보니 Agent 가 busy 상태였고 stop시킨 다음에 다시 테스트 실행.
[4차 오류] test stopped by error 를 마주침
ㅋㅋ
다시 .ngrinder 파일을 지우고,, 재부팅,, 다시 스크립트 작성,, 테스트 실행,,
똑같은 현상이 반복됨..
내 무지함의 한계이긴하겠지만 구글링을 아무리 해도 해결방법이 보이지 않아서 아예 도커로 설정하는 방법으로 방향을 틀었다.
FROM openjdk:11-slim
ARG WAR_FILE=./*war
COPY ${WAR_FILE} app.war
ENTRYPOINT ["java", "-jar", "/app.war"]
2) docker-compose.yml 파일도 작성해준다.
version: "3.8"
services:
ngrinder:
container_name: arm_ngrinder
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
docker-compose up -d
로 도커에 빌드!
ngrinder-controller 디렉토리 구조
./ngrinder
├─docker-compose.yml
├─/ngrinder-controller
│├─ngrinder-controller-3.5.9.war
│├─lib
│├─Dockerfile
│└─docker-compose.yml
│
└─/ngrinder-agent
3) ngrinder-agent 디렉토리 안의 Docker file은 다음과 같이 작성
FROM openjdk:11-slim
COPY / /home/
CMD /home/run_agent.sh -ch ngrinder-controller-arm
ngrinder-agent 디렉토리 구조
├/ngrinder-agent
│├─ Dockerfile
│├─ lib
│├─ run-agent.sh
│├─ run-agent-bg.sh
│ .
│ .
│ .
4) ngrinder-agent, ngrinder-controller가 들어있는 경로에 docker-compose.yml 파일을 작성 후에 docker-compose up -d
로 도커에 올려줌
version: "3.8"
services:
ngrinder-controller:
container_name: ngrinder-controller-arm
build:
context: ./ngrinder-controller
dockerfile: Dockerfile
restart: always
ports:
- "8080:8080"
- "12000-12009:12000-12009"
- "16001:16001"
networks:
- ngrinder
ngrinder-agent:
container_name: ngrinder-agent-arm
depends_on:
- ngrinder-controller
build:
context: ./ngrinder-agent
dockerfile: Dockerfile
restart: always
networks:
- ngrinder
networks:
ngrinder:
driver: bridge
된다ㅜㅜ 하
초기에 작성한 스크립트
@RunWith(GrinderRunner)
class TestRunner {
public static GTest login
public static GTest add
public static HTTPRequest request
public static Map<String, String> headers = [:]
public static Map<String, Object> params = [:]
public static List<Cookie> cookies = []
public static String body = '[{ "optionId" : 1,"quantity" : 1},{ "optionId" : 2,"quantity" : 5}]'
public static String token
@BeforeProcess
public static void beforeProcess() {
HTTPRequestControl.setConnectionTimeout(300000)
login = new GTest(1, "POST /api/v1/login")
add = new GTest(2, "POST /carts/add")
request = new HTTPRequest()
grinder.logger.info("before process.")
}
@BeforeThread
public void beforeThread() {
login.record(this, "login")
add.record(this, "add")
grinder.statistics.delayReports = true
grinder.logger.info("before thread.")
}
//로그인
@Test
public void login() {
// 로그인 API에 요청을 보내서 JWT 토큰을 받아옴
HTTPResponse response = request.POST("http://192.168.100.91:8081/api/v1/login", [email: "ssar@nate.com", password: "ssar"])
grinder.logger.info("처음에 추가되는 토큰: {}", response.getHeader("Authorization").toString().substring(15))
//토큰 앞에 붙는 쓸데없는 String 제거
token = response.getHeader("Authorization").toString().substring(15);
//헤더에 넣어줌
headers.put("Authorization", token)
//헤더 가져옴
def result = response.getHeader("Authorization");
grinder.logger.info("header: {}", result)
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))
}
}
@Test
public void add() {
grinder.logger.info("봐야되는거: {}", headers)
request.setHeaders(headers)
HTTPResponse response = request.POST("http://192.168.100.91:8081/carts/add", body.getBytes())
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))
}
}
}
결국 오랫동안 구글링을 하다가 테스트를 알파벳 순으로 한다는 것을 알게됨..ㅋ
login() 보다 add()를 먼저 실행하니 당연히 오류가 나지.. 그래서 test1, test2로 이름을 바꿈
최종 스크립트
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test1
public static GTest test2
public static HTTPRequest request
public static Map<String, String> headers = [:]
public static Map<String, Object> params = [:]
public static List<Cookie> cookies = []
public static String body = '[{ "optionId" : 1,"quantity" : 1},{ "optionId" : 2,"quantity" : 5}]'
public static String token
@BeforeProcess
public static void beforeProcess() {
HTTPRequestControl.setConnectionTimeout(300000)
test1 = new GTest(1, "POST /api/v1/login")
test2 = new GTest(2, "POST /carts/add")
request = new HTTPRequest()
grinder.logger.info("before process.")
}
@BeforeThread
public void beforeThread() {
test1.record(this, "test1")
test2.record(this, "test2")
grinder.statistics.delayReports = true
grinder.logger.info("before thread.")
}
//로그인
@Test
public void test1() {
// 로그인 API에 요청을 보내서 JWT 토큰을 받아옴
HTTPResponse response = request.POST("http://192.168.100.91:8081/api/v1/login", [email: "ssar@nate.com", password: "ssar"])
grinder.logger.info("처음에 추가되는 토큰: {}", response.getHeader("Authorization").toString().substring(15))
//토큰 앞에 붙는 쓸데없는 String 제거
token = response.getHeader("Authorization").toString().substring(15);
//헤더에 넣어줌
headers.put("Authorization", token)
//헤더 가져옴
def result = response.getHeader("Authorization");
grinder.logger.info("header: {}", result)
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))
}
}
@Test
public void test2() {
grinder.logger.info("봐야되는거: {}", headers)
request.setHeaders(headers)
HTTPResponse response = request.POST("http://192.168.100.91:8081/carts/add", body.getBytes())
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))
}
}
}
과정을 겪으면서 여러가지 에러(test가 안만들어지는 error while fetching files from svn for admin 에러, 스크립트 500에러 등)를 만났지만 굵직한 에러들만 몇개 정리해봄..
모든 개발자들이 그렇듯 새로운 툴의 설치 과정과 설정과정에서 다양한 에러들을 마주치게 되는데 과정은 괴로워도 해결하고 나면 미화됨.. 변태같은 직종
다음 포스트는 tps 그래프에 대한 내용을 다룰예정..!!
안녕하세요. 저도 스크립트 탭으로 넘어가지지 않는 오류 때문에 막혔는데 .nGrinder 폴더 삭제를 하려고 하는데 어디 위치에 있는지 알 수 있을까요?