😀
fistkim TECH BLOG
  • Intro
  • 강의
    • Reactive Programming in Modern Java using Project Reactor
      • Reactor execution model 1
      • Reactor execution model 2
      • Reactor execution model 3 - parallelism
      • Reactor execution model 4 - overview
      • Transform
      • Combine
      • Side Effect Methods
      • Exception/Error handling
      • retry, retryWhen, repeat
      • BackPressure
      • Cold & Hot Streams
    • NEXTSTEP 클린코드 with java 9기
      • 정리노트
    • NEXTSTEP DDD 세레나데 2기
      • CH01 도메인 주도 설계 이해
      • CH02 크게 소리 내어 모델링 하기
      • CH03 도메인 주도 설계 기본 요소
      • CH04 도메인 주도 설계 아키텍처
      • CH05 도메인 이벤트
    • NEXTSTEP 인프라 공방 1기
      • 망 분리하기
      • 통신 확인하기
      • 도커 컨테이너 이해하기
      • [미션 1] 서비스 구성하기 실습
      • [미션 2] 서비스 배포하기 실습
      • 서버 진단하기
      • 어플리케이션 진단하기
      • [미션 3] 서비스 운영하기
      • 웹 성능 진단하기
      • 부하 테스트
      • k6
      • [미션 4] 성능 테스트
      • 리버스 프록시 개선하기
      • 캐싱 활용하기
      • [미션 5] 화면 응답 개선하기
      • Redis Annotation 및 설정
      • 인덱스 이해하기 & DB 튜닝
      • [미션 6-1] 조회 성능 개선하기
      • [미션 6-2] DB 이중화 적용
    • NEXTSTEP 만들면서 배우는 Spring 3기
      • CH01 올바른 방향 바라보기
      • CH02 HTTP 이해 - 웹 서버 구현
        • HTTP 파싱
        • HTTP 웹 서버 구현
      • CH03 MVC - @MVC 프레임워크 구현
        • Servlet 다시 짚기
        • Cookie, Session 다시 짚기
        • MVC 프레임워크 구현
      • CH04 나만의 라이브러리 구현
      • CH05 DI - DI 프레임워크 구현
      • CH06 Aspect OP
    • 스프링 시큐리티
      • 스프링 시큐리티 아키텍처
      • WebAsyncManagerIntegrationFilter
      • SecurityContextPersistenceFilter
      • HeaderWriterFilter
      • CsrfFilter
      • (+) 스프링 시큐리티 + JWT
      • (+) 마치며
    • 더 자바, 코드를 조작하는 다양한 방법
      • CH01 JVM 이해하기
      • (+) 클래스 로더 이해하기
      • CH02 바이트 코드 분석 및 조작
      • (+) jacoco
      • CH03 리플렉션
      • CH04 다이나믹 프록시
      • CH05 애노테이션 프로세서
    • 더 자바, 애플리케이션을 테스트하는 다양한 방법
      • CH01 JUnit 5
      • CH02 Mockito
      • (+) Spy vs Mock
      • CH03 도커와 테스트
      • CH04 성능 테스트
      • (+) VisualVM
      • (+) 테스트 자동화
      • CH05 운영 이슈 테스트
      • CH06 아키텍처 테스트
    • 모든 개발자를 위한 HTTP 웹 기본 지식
      • CH01 인터넷 네트워크
      • CH02 HTTP 기본
      • CH03 HTTP 메서드 속성
      • CH04 HTTP 메서드 활용
      • CH05 HTTP 상태코드
      • CH06 HTTP 헤더1 - 일반 헤더
      • CH07 HTTP 헤더2 - 캐시와 조건부 요청
      • (+) HTTPS 원리
    • 스프링 프레임워크 핵심 기술
      • CH01 IOC 컨테이너
      • CH02 AOP
      • (+) 스프링 의존성 관리
      • (+) 생성자 주입 장점
    • 코딩으로 학습하는 GoF의 디자인 패턴
      • 객체 생성
        • 싱글톤 패턴
        • 팩토리 메소드 패턴
        • 추상 팩토리 패턴
        • 빌더 패턴
        • 프로토타입 패턴
      • 구조
        • 어댑터 패턴
        • 브릿지 패턴
        • 컴포짓 패턴
      • 행동
        • (작성중)
    • 실전 Querydsl
      • CH01 프로젝트 환경구성
      • CH02 예제 도메인 모델
      • CH03 기본문법
      • CH04 중급 문법
      • CH05 실무활용 (스프링 데이터 JPA와 Querydsl)
      • CH06 스프링데이터JPA 가 제공하는 Querydsl 기능
      • (+) 별칭(alias)
      • (+) Slice 쿼리
    • 스프링 데이터 JPA
      • CH01 핵심개념이해 1
      • CH02 핵심개념이해 2
      • CH03 핵심개념이해 3
      • CH04 Spring Data Common
      • CH05 Spring Data JPA
    • 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
      • CH01 지연 로딩과 조회 성능 최적화
      • CH02 컬렉션 조회 최적화
      • CH03 전체 정리
    • 초보를 위한 쿠버네티스 안내서
      • CH01 쿠버네티스 시작하기
      • CH02 쿠버네티스 알아보기
      • CH03 쿠버네티스 실습 준비
      • CH04 쿠버네티스 기본 실습
    • Flutter Provider Essential
      • CH01 Introduction
      • CH02 Provider Overview
      • CH03 TODO App
      • CH04 Weather App
      • CH05 Firebase Authentication App
    • Flutter Bloc Essential
      • CH01 Introduction
      • CH02 Bloc Overview
      • CH03 TODO App
      • CH04 Weather App
      • CH05 Firebase Authentication App
    • Flutter Advanced Course - Clean Architecture With MVVM
      • CH01 Introduction
      • CH02 Clean Architecture 4 Layer
      • CH03 MVVM
      • CH04 Data Layer
      • (+) Data Layer - response to model
      • (+) Data Layer - Network
      • CH05 Domain Layer
      • CH06 Presentation Layer
      • CH07 Application Layer
      • (+) Application Layer - l10n
      • (+) Application Layer - DI
      • (+) Application Layer - environment
    • 자바 알고리즘 입문
      • CH01 문자열
      • CH02 Array(1, 2 차원 배열)
      • CH03 Two pointers, Sliding window[효율성: O(n^2)-->O(n)]
      • CH04 HashMap, TreeSet (해쉬, 정렬지원 Set)
      • CH05 Stack, Queue(자료구조)
      • CH06 Sorting and Searching(정렬, 이분검색과 결정알고리즘)
      • CH07 Recursive, Tree, Graph(DFS, BFS 기초)
      • CH08 DFS, BFS 활용
      • CH09 Greedy Algorithm
      • CH10 dynamic programming(동적계획법)
  • 도서
    • 만들면서 배우는 클린 아키텍처
      • 학습목표
      • CH01 계층형 아키텍처의 문제는 무엇일까?
      • CH02 의존성 역전하기
      • CH03 코드 구성하기
      • CH04 유스케이스 구현하기
      • CH05 웹 어댑터 구현하기
      • CH06 영속성 어댑터 구현하기
      • CH07 아키텍처 요소 테스트하기
      • CH08 경계 간 매핑하기
      • CH09 어플리케이션 조립하기
      • CH10 아키텍처 경계 강제하기
      • CH11 의식적으로 지름길 사용하기
      • CH12 아키텍처 스타일 결정하기
    • 클린 아키텍처
      • 들어가며
      • 1부 소개
        • 1장 설계와 아키텍처란?
        • 2장 두 가지 가치에 대한 이야기
      • 2부 벽돌부터 시작하기: 프로그래밍 패러다임
        • 3장 패러다임 개요
        • 4장 구조적 프로그래밍
        • 5장 객체 지향 프로그래밍
        • 6장 함수형 프로그래밍
      • 3부 설계 원칙
        • 7장 SRP: 단일 책임 원칙
        • 8장 OCP: 개방-폐쇄 원칙
        • 9장 LSP: 리스코프 치환 원칙
        • 10장 ISP: 인터페이스 분리 원칙
        • 11장 DIP: 의존성 역전 원칙
      • 4부 컴포넌트 원칙
        • 12장 컴포넌트
        • 13장 컴포넌트 응집도
        • 14장 컴포넌트 결합
      • 5부
        • 15장 아키텍처란?
    • 스프링 입문을 위한 자바 객체 지향의 원리와 이해
      • CH01 사람을 사랑한 기술
      • CH02 자바와 절차적/구조적 프로그래밍
      • CH03 자바와 객체 지향
      • (+) 자바 코드 실행에 따른 메모리 적재과정
      • CH04 자바가 확장한 객체 지향
      • CH05 객체 지향 설계 5 원칙 - SOLID
      • CH06 스프링이 사랑한 디자인 패턴
      • CH07 스프링 삼각형과 설정 정보
      • (부록) 람다(lambda)
    • 객체지향의 사실과 오해
      • CH01 협력하는 객체들의 공동체
      • CH02 이상한 나라의 객체
      • CH03 타입과 추상화
      • CH04 역할, 책임, 협력
      • CH05 책임과 메시지
      • CH06 객체 지도
      • CH07 함께 모으기
      • (+) 인터페이스 개념 바로잡기
    • 도메인 주도 개발 시작하기
      • CH01 도메인 모델 시작하기
      • CH02 아키텍처 개요
      • CH03 애그리거트
      • CH04 리포지터리와 모델 구현
      • CH05 스프링 데이터 JPA를 이용한 조회 기능
      • CH06 응용 서비스와 표현 영역
      • CH07 도메인 서비스
      • CH08 애그리거트 트랜잭션 관리
      • CH09 도메인 모델과 바운디드 컨텍스트
      • CH10 이벤트
      • CH11 CQRS
    • 자바 ORM 표준 JPA 프로그래밍
      • CH01 JPA 소개
      • CH02 JPA 시작
      • CH03 영속성 관리
      • CH04 엔티티 매핑
      • CH05 연관관계 매핑 기초
      • CH06 다양한 연관관계 매핑
      • CH07 고급 매핑
      • CH08 프록시와 연관관계 관리
      • CH09 값 타입
      • CH10 객체지향 쿼리 언어
      • CH11 웹 애플리케이션 제작
      • CH12 스프링 데이터 JPA
      • CH13 웹 애플리케이션과 영속성 관리
      • CH14 컬렉션과 부가 기능
      • CH15 고급 주제와 성능 최적화
      • CH16 트랜잭션과 락, 2차 캐시
    • 소프트웨어 세상을 여는 컴퓨터과학
      • CH01 컴퓨터 과학 소개
      • CH02 데이터 표현과 디지털 논리
    • 이펙티브 자바
      • 1 장 들어가기
      • 2장 객체 생성과 파괴
        • [01] 생성자 대신 정적 팩터리 메서드를 고려하라
        • [02] 생성자에 매개변수가 많다면 빌더를 고려하라
        • [03] private 생성자나 열거 타입으로 싱글턴임을 보증하라
        • [04] 인스턴스화를 막으려거든 private 생성자를 사용하라
        • [05] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
        • [06] 불필요한 객체 생성을 피하라
        • [07] 다 쓴 객체 참조를 해제하라
        • [08] finalizer 와 cleaner 사용을 피하라
        • [09] try-finally 보다는 try-with-resources 를 사용하라
      • 3장 모든 객체의 공통 메서드
        • [10] equals는 일반 규약을 지켜 재정의하라
        • [11] equals 를 재정의하려거든 hashCode도 재정의하라
        • [12] toString 을 항상 재정의하라
        • [13] clone 재정의는 주의해서 진행하라
        • [14] Comparable 을 구현할지 고려하라
      • 4장 클래스와 인터페이스
        • [15] 클래스와 멤버의 접근 권한을 최소화하라
  • 토픽
    • 서버 모니터링
      • CPU 사용량
      • 메모리 사용량
      • 스레드 풀
    • Spring Boot Monitoring
      • Spring actuator
      • Spring eureka
      • Prometheus
      • grafana
      • Spring actuator + Prometheus + grafana
    • JAVA 데일리 토픽
      • 메모리 누수(memory leak)
      • 객체 참조의 유형
      • 커스텀 스레드 풀
      • Mark And Compact
      • serialVersionUID 이해하기
      • 함수형 인터페이스
      • 메소드 참조
      • equals()와 hashCode()가 무엇이고 역할이 무엇인지
      • StringBuffer vs StringBuilder
      • String vs StringBuilder, StringBuffer
      • String interning
    • JAVA GC
    • 프로그래머스 문제 풀기
      • 해시
      • 스택/큐
      • 힙(Heap)
      • 정렬
      • 완전탐색
      • DFS/BFS
    • 데이터베이스 구성 및 작동 흐름
    • 데이터베이스 JOIN 원리
    • 객체지향생활체조 원칙
    • 상태(state), 상속(inheritance), 합성(composition) 의 상관관계
    • java enum은 메모리에 언제, 어떻게 할당되는가
    • Checked Exception vs UnChecked Exception
    • Reactive Streams 원리탐구 - 간단한 예제 직접 작성해보기
    • Flutter Basic
    • Flutter StatefulWidget 생명주기
    • Flutter 가 위젯을 그리는 원리
    • Flutter 클린 아키텍처
      • application layer
        • 패키지 구조 및 레이어 설명
        • environment
        • dependency injection
        • go_router
        • foreground & background
        • 다국어처리 (l10n, i18n)
        • Global 처리(시스템 점검, fore->back 등)
        • connection_manager
        • permission_manager
        • push_notification_manager
        • firebase 연동
      • data layer
        • 패키지 구조 및 레이어 설명
        • network
        • repository
      • domain layer
        • 패키지 구조 및 레이어 설명
      • presentation layer
        • 패키지 구조 및 레이어 설명
        • resources
    • 기술 관련 포스팅 읽기
  • 기타
    • 작업일지
      • 2023. 10
      • 2023. 09
      • 2023. 08
      • 2023. 07
      • 2023. 06
      • 2023. 05
      • 2023. 04
      • 2023. 03
      • 2023. 02
      • 2023. 01
      • 2022. 12
    • Business Model
      • 아이디어 불패의 법칙
      • 린 모바일 앱 개발
      • 린 스타트업
      • 제로투원
      • MIT 스타트업 바이블
      • 린치핀
    • 백로그 종합
Powered by GitBook
On this page
  • 카오스 엔지니어링이란
  • 카오스 엔지니어링의 목적
  • 카오스 몽키
  • 공격 대상(watcher)과 공격 유형(Assaults)
  • 카오스 몽키 설정
  • 카오스 몽키 실습
  • 카오스 몽키 활성화
  • watcher 활성화
  • 공격 지시
  • 생각정리
  1. 강의
  2. 더 자바, 애플리케이션을 테스트하는 다양한 방법

CH05 운영 이슈 테스트

Previous(+) 테스트 자동화NextCH06 아키텍처 테스트

Last updated 1 year ago

카오스 엔지니어링이란

용어 자체에 대한 설명이 레퍼런스마다 조금씩 다른데 이 제일 직관적인 것 같아서 첨부한다.

카오스 엔지니어링 은 프로덕션 오류에 대한 서비스를 강화하여 개발자가 일관된 안정성을 얻을 수 있도록 하는 방법론입니다.

카오스를 유발하는 일반적인 방법은 시스템 구성 요소가 실패하게 만드는 오류를 의도적으로 삽입하는 것입니다. 불리한 상황에서 시스템의 안정성을 관찰, 모니터링, 대응 및 개선하는 것이 목표입니다.

일부러 시스템에 운영 상황에서 발생할 수 있는 오류 상황을 유발 시켜서 시스템의 저항성을 테스트하고 이걸 키워 나가는 엔지니어링 방법론을 의미한다.

을 쓴 것이 있는데 이걸 이 있다. 책도 있는데 내용이 재미있을 것 같다.

카오스 엔지니어링의 목적

위에 링크를 첨부한 마이크로소프트의 글에 정리가 잘 되어있는데, 아래와 같다.

카오스 몽키

이번 강의에서 다룬 툴이다. AOP를 이용해서 래핑한 객체를 활용해서 의도적으로 장애 상황을 만들 수 있다. 몽키가 분탕질(?) 치는 컨셉으로 '카오스 몽키' 라고 네이밍을 한 것 같다.

다음은 강의 자료 일부이다.

공격 대상(watcher)과 공격 유형(Assaults)

공격 대상은 말 그대로 카오스 몽키를 이용해서 공격할 수 있는 대상들을 의미한다. 위 어노테이션들이 붙은 bean 들은 모두 공격 대상으로 삼을 수 있다. 공격 유형은 어떤 장애를 의도적으로 일으킬지(=카오스 몽키를 이용해서 어떤 장애를 일으킬 수 있는지) 그 종류를 말한다.

카오스 몽키 설정

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'de.codecentric:chaos-monkey-spring-boot:3.0.1'

    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
spring.profiles.active=chaos-monkey
management.endpoint.chaosmonkey.enabled=true
management.endpoints.web.exposure.include=health,info,chaosmonkey

위와 같이 설정하고 어플리케이션을 띄우면 로그에 아래와 같이 뜬다.

이렇게 뜨면 실행할 준비가 되었다. 아래와 같이 카오스몽키에 요청을 보내면 현재 상태에 대해서 알 수 있다.

http://localhost:8080/actuator/chaosmonkey
{
    "chaosMonkeyProperties": {
        "enabled": false,
        "lastEnabledToggleTimestamp": null,
        "togglePrefix": "chaos.monkey"
    },
    "assaultProperties": {
        "level": 1,
        "deterministic": false,
        "latencyRangeStart": 1000,
        "latencyRangeEnd": 3000,
        "latencyActive": false,
        "exceptionsActive": false,
        "exception": {
            "type": "java.lang.RuntimeException",
            "method": "<init>",
            "arguments": [
                {
                    "type": "java.lang.String",
                    "value": "Chaos Monkey - RuntimeException"
                }
            ]
        },
        "killApplicationActive": false,
        "killApplicationCronExpression": "OFF",
        "memoryActive": false,
        "memoryMillisecondsHoldFilledMemory": 90000,
        "memoryMillisecondsWaitNextIncrease": 1000,
        "memoryFillIncrementFraction": 0.15,
        "memoryFillTargetFraction": 0.25,
        "memoryCronExpression": "OFF",
        "cpuActive": false,
        "cpuMillisecondsHoldLoad": 90000,
        "cpuLoadTargetFraction": 0.9,
        "cpuCronExpression": "OFF"
    },
    "watcherProperties": {
        "controller": false,
        "restController": false,
        "service": false,
        "repository": false,
        "component": false,
        "restTemplate": false,
        "webClient": false,
        "actuatorHealth": false,
        "beans": [],
        "excludeClasses": []
    }
}

카오스 몽키 실습

카오스 몽키 활성화

{
    "chaosMonkeyProperties": {
        "enabled": false,
        "lastEnabledToggleTimestamp": null,
        "togglePrefix": "chaos.monkey"
    },
    "assaultProperties": {
        "level": 1,
        "deterministic": false,
        "latencyRangeStart": 1000,
        "latencyRangeEnd": 3000,
        "latencyActive": false,
        "exceptionsActive": false,
        "exception": {
            "type": "java.lang.RuntimeException",
            "method": "<init>",
            "arguments": [
                {
                    "type": "java.lang.String",
                    "value": "Chaos Monkey - RuntimeException"
                }
            ]
        },
        "killApplicationActive": false,
        "killApplicationCronExpression": "OFF",
        "memoryActive": false,
        "memoryMillisecondsHoldFilledMemory": 90000,
        "memoryMillisecondsWaitNextIncrease": 1000,
        "memoryFillIncrementFraction": 0.15,
        "memoryFillTargetFraction": 0.25,
        "memoryCronExpression": "OFF",
        "cpuActive": false,
        "cpuMillisecondsHoldLoad": 90000,
        "cpuLoadTargetFraction": 0.9,
        "cpuCronExpression": "OFF"
    },
    "watcherProperties": {
        "controller": false,
        "restController": false,
        "service": false,
        "repository": false,
        "component": false,
        "restTemplate": false,
        "webClient": false,
        "actuatorHealth": false,
        "beans": [],
        "excludeClasses": []
    }
}

일단 "enabled": false 인 것이 보인다. POST 로 /actuator/chaosmonkey/enable 를 통해 카오스 몽키를 활성화 시켜주고 enabled 가 true 가 되었는지 확인한다.

watcher 활성화

curl --location 'http://localhost:8080/actuator/chaosmonkey/watchers' \
--header 'Content-Type: application/json' \
--data '{
  "controller": true,
  "restController": true,
  "service": true,
  "repository": true,
  "component": false,
  "restTemplate": false,
  "webClient": false,
  "actuatorHealth": false
}'

POST 를 통해 위와 같이 통신하면 data 에 세팅한 것과 같이 watcher 가 활성화 된다. 공격 대상에 따라 커스텀해서 세팅하자.

공격 지시

일단 실습은 간단하게 레이턴시를 의도적으로 발생시키는 것을 했다.

curl --location 'http://localhost:8080/actuator/chaosmonkey/assaults' \
--header 'Content-Type: application/json' \
--data '{
  "level": 5,
  "latencyRangeStart": 2000,
  "latencyRangeEnd": 3000,
  "latencyActive": true
}'

아래와 같이 매우 단순한 핸들러에 카오스 몽키를 이용해서 레이턴시를 걸고 Jmeter 로 부하테스트를 해보자.

@RestController
public class SampleController {

    @GetMapping("/index")
    public String stressTest() {
        return "index";
    }

}

먼저 비교를 위해서 카오스 몽키로 레이턴시를 걸기 전의 데이터를 보자.

TPS 가 10.1 이 나왔다.

이제 카오스 몽키로 레이턴시를 의도적으로 발생시키도록 하고 다시 테스트해보자. 레이턴시는 아래와 같이 걸었다.

curl --location 'http://localhost:8080/actuator/chaosmonkey/assaults' \
--header 'Content-Type: application/json' \
--data '{
  "level": 5,
  "latencyRangeStart": 5000,
  "latencyRangeEnd": 6000,
  "latencyActive": true
}'

TPS가 6.9가 나왔다. Maximum 을 보아도 카오스 몽키 적용 전에 10이었는데 5951로 올랐다. 왜냐면 내가 레이턴시를 6000 으로 설정해줬기 때문이다.(그런데 적어도 6000을 초과해야하는 것 아닌가 싶다.)

아래와 같이 레이턴시 길이를 더 늘려서 다시 테스트 했다.

curl --location 'http://localhost:8080/actuator/chaosmonkey/assaults' \
--header 'Content-Type: application/json' \
--data '{
  "level": 5,
  "latencyRangeStart": 10000,
  "latencyRangeEnd": 15000,
  "latencyActive": true
}'

성능이 확실히 더 떨어졌음을 확인할 수 있다.

강의에서는 아래와 같이 런타임에러도 실습했다.

http POST localhost:8080/actuator/chaosmonkey/assaults level=3 latencyActive=false exceptionsActive=true exception.type=java.lang.RuntimeException

생각정리

잘 활용 하면 정말 좋은 툴이라고 생각이 든다. 예전에 강의를 볼때는 이런게 있구나 싶었었는데, 회사에서 운영 이슈를 실제로 마주하고서 다시 이 강의를 보니까 예전에 강의를 볼 때보다 활용성이 아주 좋아 보인다.

팀원끼리 모여서 실제로 일어날 수 있는 여러 장애 시나리오를 수립한 뒤 그 시나리오에 맞게 카오스 몽키를 이용해서 의도적으로 장애를 일으켜서 서버의 장애 내성을 파악하고 필요한 조치를 해두면 좋을 것 같다.

에 여러 엔드포인트들에 대한 정보들이 나와있다.

먼저 카오스 몽키를 활성화 해야하는데 일단 를 통해서 전체적인 카오스 몽키의 세팅 상태를 확인한다.

절반의 확률로 2초 ~ 3초의 레이턴시를 발생시킨다. 각 프로퍼티에 대한 설명은 에 자세히 나와있다.

마이크로소프트의 글에 정리된 내용
넷플릭스에서 카오스 엔지니어링 관련한 글
잘 번역해둔 포스팅
복원력 테스트
백업 전략 설계
재해 복구 전략 설계
장애 조치(failover) 및 장애 복구(fallback) 단계 명문화
지역적 장애에 대한 계획
다시 시도 논리 구현
상태 프로브 구성 및 테스트
읽기 및 쓰기 인터페이스 분리
공식문서
http://localhost:8080/actuator/chaosmonkey
https://codecentric.github.io/chaos-monkey-spring-boot/latest/#_properties