[Spring] CM4SB와 Jmeter로 API 응답 지연 테스트하기 (카오스 엔지니어링)
카오스 엔지니어링
넷플릭스(Netflix)의 카오스 엔지니어링을 설명하기 위한 기본 원칙을 담고 있는 PRINCIPLES OF CHAOS ENGINEERING의 내용을 참고하였습니다.
카오스 엔지니어링(Chaos Engineering)이란 프로덕션 서비스의 각종 장애 조건을 견딜 수 있는 시스템의 신뢰성을 확보하기 위해 분산 시스템을 실험하고 배우는 분야이다. 대규모 분산 소프트웨어 시스템 발전으로 인해 IT 업계는 발빠른 변화가 일어나고 있다. 개발 유연성과 배포 속도를 높이는 방식을 발빠르게 채택하고 있다. 이러한 방식에 대해 마주한 질문은 "우리가 배포 환경의 복잡한 시스템자체를 우리가 신뢰할 수 있는가?"이다.
분산 시스템 내부의 각 개별 서비스가 올바르게 작동하는 경우에도 해당 서비스 간의 상호 작용으로 인해 예측할 수 없는 결과가 발생할 수 있다. 즉, 프로덕션 환경에 직접 영향을 미치는 아주 드물지만 파괴적인 실제 장애로 인해 예기치 않은 결과가 발생하면, 분산 시스템이 혼란(Chaos)를 가져오게 된다.
예측 불가능한 비정상적인 행동이 시스템에 나타나기 전에 이러한 약점들을 식별할 수 있어야 한다.
- 부적절한 fallback 설정 (어떤 기능이 약해지거나 제대로 동작하지 않을 때, 이에 대처하는 기능 또는 동작)
- 부적절한 타임 아웃 설정으로 폭풍 재시도 로직 발생
- 너무 많은 트래픽을 받는 다운 스트림 종속성
- 단일 실패 지점이 충돌할 때 연쇄 장애
이 때, 고객에게 영향을 미치기 전에 중요한 문제를 사전에 해결해야 한다. 즉, 시스템에 내재된 혼란을 관리함으로서 유연상과 속도를 증가시키고, 복잡성이 존재하고 있더라도 프로덕션 배포에 대해 신뢰를 가져야 한다.
경험 및 시스템 기반 접근 방식(empirical, systems-based approach)은 대규모 분산 시스템의 혼란을 해결하고 이러한 시스템이 현실적인 조건을 견딜 수 있다는 확신을 심어준다. 통제된 실험을 하는 동안 관찰함으로써 분산 시스템의 동작에 대해 배운다. 우리는 이것을 카오스 엔지니어링(Chaos Engineering) 이라고 부르기로 했다.
CM4SB(Chaos Monkey For Spring Boot)
스프링에서도 위 Netflix의 Chaos Engineering에 영감을 받고 제작된 오픈소스 라이브러리 CM4SB가 존재한다. 이 오픈소스에서 제공하는 Chaos Monkey를 통해 실행 중인 Spring Boot 앱을 명령어로 공격할 수 있다.
동작방식
Spring Boot Chaos Monkey가 클래스 경로에 있고 profile 이름으로 활성화된 경우 chaos-monkey애플리케이션에 자동으로 연결된다. (spring.profile = chaos-monkey)
이제 공격(Assaults)할 클래스를 찾는 감시자(Wathcer)를 활성화할 수 있다. 전체 애플리케이션을 공격하는 런타임 공격(Runtime Assaults)도 있다.
스프링 CM4SB와 Jmeter로 API 응답 지연 테스트하기
1. Profile 설정
CM4SB로 시작하려면 스프링 앱 profile은 chaos-monkey로 실행해야 한다.
2. gradle 의존성 추가하기
chaos-monkey의 상태를 확인하기 위해서는 spring-actuator가 필요하다. 그러므로 actuator와 chaos-monkey 의존성을 추가해준다.
- actuator는 spring boot가 실행 중일 때 헬스 체크, 로그레벨 변경, 매트릭스 데이터 조회 등 다양한 작업들을 할 수 있게 해주는 라이브러리이다.
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'de.codecentric:chaos-monkey-spring-boot:2.5.4'
카오스가 정상적으로 실행된다면 스프링 앱 실행 화면에 다음과 같이 Chaso Monkey 로고가 나오는 것을 확인할 수 있다.
3. yml 파일에 설정 추가하기
application-chaos-monkey.yml에 다음과 같은 설정을 추가한다.
- Spring Boot Actuator Endpoints 설정하기 (health, info, chaosmonkey)
- repository watcher 활성화하기
# https://codecentric.github.io/chaos-monkey-spring-boot/latest/#endpoints
management:
endpoint:
chaosmonkey:
enabled: true
chaosmonkeyjmx:
enabled: true
endpoints:
web:
exposure:
# include specific endpoints
include:
- health
- info
- chaosmonkey
chaos:
monkey:
watcher:
repository: true
Actuator로 상태 확인하기
GET: http://localhost:8080/actuator/ 로 정상적으로 yml 설정이 적용되었는지 확인할 수 있다. 다음과 같이 health, info, chaosmonkey가 있어야 한다.
Httpie로 Console에서 확인하기
curl 명령어보다 Httpie를 사용하면 다음과 같이 보기 좋게 결과가 출력된다. 다음 명령어를 입력하면 chaos monkey의 상태를 확인해 볼 수 있다. "you switched me off"는 아직 chaos monkey가 비활성 상태라는 뜻이다.
$ http localhost:8080/actuator/chaosmonkey/status
응답 지연 이슈 재현하기
1. Chaos Monkey Watcher 확인
감시자(Watcher)는 Repository에만 위 yml 파일에서 직접 설정해주었다. 설정이 제대로 되었는지 확인해보자.
$ http localhost:8080/actuator/chaosmonkey/watchers
2. Chaos Monkey 활성화
다음 post 요청으로 Chaos Monkey를 활성화시킨다.
http post localhost:8080/actuator/chaosmonkey/enable
3. Chaos Monkey 활성화 확인
그리고 다시 status를 확인해보면 "Ready to be evil!"로 바뀌었음을 확인할 수 있다.
http localhost:8080/actuator/chaosmonkey/status
5. Chaos Monkey 지연 공격 설정
이제 응답 지연 공격을 설정해준다. 이는 위에서 설장한 Repository에만 공격이 설정된다.
$ http post localhost:8080/actuator/chaosmonkey/assaults level=3 latencyRangeStart=2000 latencyRangeEnd=5000 latencyActive=true
- level 3: 3번 요청에 1번 공격
- latencyRangeStart=2000 latencyRangeEnd=5000: 2초부터 5초내로 응답 지연시키기
- latencyActive=true: latency 어택 활성화
assault로 get 요청을 하면 지연 공격 설정이 제대로 되었는지 확인해볼 수 있다.
$ http localhost:8080/actuator/chaosmonkey/assaults
Jmeter로 CM4SB 응답 지연 테스트하기
Jmeter로 간단한 API를 테스트해봤다. Thread Group을 생성하고 나서 다음과 같이 설정하였다
- Thread: 20 (쓰레드 갯수)
- Ramp-up Period: 1 (모든 쓰레드를 동작하는 데 걸리는 시간)
- Loop Count: infinite (반복 횟수)
그런 다음 http request를 추가하여 GET post/1를 요청하도록 설정하였다. 그리고 이에 대한 처리 결과를 받아 볼 수 있는 Aggregate Report를 추가해준다. 모든 설정이 끝났으면 해당 파일을 findOne.jmx로 저장한다.
콘솔에서 해당 파일을 실행하려면 위에서 저장한 findOne.jmx 경로로 들어가서 다음 명령어를 입력해주면 된다.
$ ~/apache-jmeter-5.4.3/bin/jmeter -n -t ./findOne.jmx
응답 지연 공격 설정 전
응답지연 공격 설정 전에는 30초 동안 처리한 요청 횟수가 9만 5천개에 달하고 초당 3152개씩 처리해주었다.
summary + 94584 in 00:00:30 = 3152.8/s Avg: 6 Min: 1 Max: 34 Err: 0 (0.00%) Active: 20 Started: 20 Finished: 0
응답 지연 공격 설정 후
2~5초내로 응답 지연 공격 설정을 한 후에는 확실히 느려진 것을 확인할 수 있다. 30초 동안 처리한 요청 횟수는 543개이고 초당 18개씩 처리해주었다. 약 174배 느려진 것을 확인할 수 있다. 그래도 단순한 GET 요청이라서 응답 지연 공격에도 Error 카운트는 0으로 발생하지 않았다.
summary + 543 in 00:00:30 = 18.2/s Avg: 1110 Min: 1 Max: 4990 Err: 0 (0.00%) Active: 20 Started: 20 Finished: 0
실습한 내용은 github에서 확인할 수 있습니다.
참고
https://github.com/codecentric/chaos-monkey-spring-boot
https://principlesofchaos.org/
http://channy.creation.net/blog/1173
https://blog.codecentric.de/en/2018/07/chaos-engineering/
https://codecentric.github.io/chaos-monkey-spring-boot/latest/#getting-started