Spring Batch에서의 Chunk란 데이터 덩어리로 작업 할 때각 커밋 사이에 처리되는 row 수를 얘기합니다. 즉, Chunk 지향 처리란 한 번에 하나씩 데이터를 읽어 Chunk라는 덩어리를 만든 뒤, Chunk 단위로 트랜잭션을 다루는 것을 의미합니다. 여기서 트랜잭션이라는게 중요한데요. Chunk 단위로 트랜잭션을 수행하기 때문에실패할 경우엔 해당 Chunk 만큼만 롤백이 되고, 이전에 커밋된 트랜잭션 범위까지는 반영이 된다는 것입니다. Chunk 지향 처리가 결국 Chunk 단위로 데이터를 처리한다는 의미이기 때문에 그림으로 표현하면 아래와 같습니다.
Chunk 지향 프로세싱은 1000개의 데이터에 대해 배치 로직을 실행한다고 가정하면, Chunk 단위로 나누지 않았을 경우에는 한개만 실패해도 성공한 999개의 데이터가 롤백된다. Chunk 단위를 10으로 한다면, 작업 중에 다른 Chunk는 영향을 받지 않는다.
Reader에서 데이터 하나를 읽어 온다.(item 단위)
읽어온 데이터를 Processor에서 가공한다.(item 단위)\
가공된 데이터들을 별도의 공간에 모은 뒤 Chunk 단위만큼 쌓이게 되면 Writer에 전달하고 Writer는 일괄 저장한다. (Chunk = items)
여기선 Reader, Processor에서는 1건씩 다뤄지고, Writer에서는 Chunk 단위로 처리된다는 것을 기억하면 된다.
Chunk-oriented processing의 장점
위에서 알아본청크지향 프로세싱을 사용하지 않는다 하더라도 개발자가 충분히 비슷한 로직으로 구현을 할 수도 있습니다. 하지만청크지향 프로세싱은 단순히 청크단위의트랜잭션만 제공해주는것은 아닙니다.
Spring batch 청크지향 프로세싱의 가장 큰 장점이라고 하면, 내결함성 (Falut tolernat)를 위한 다양한 기능들을 제공하고 있다는 것 입니다.
멀티 스레드 환경에서 chunk 지향 불가
각 Reader와 Writer의 Javadoc에 항상 저thread-safe문구가 있는지 확인해보셔야 합니다. 만약 없는 경우엔 thread-safe가 지원되는 Reader 와 Writer를 선택해주셔야하며, 꼭 그 Reader를 써야한다면SynchronizedItemStreamReader등을 이용해thread-safe로 변환해서 사용해볼 수 있습니다.
그리고 또 하나 주의할 것은 멀티 쓰레드로 각 Chunk들이 개별로 진행되다보니 Spring Batch의 큰 장점중 하나인 실패 지점에서 재시작하는 것은 불가능 합니다. 이유는 간단합니다. 단일 쓰레드로 순차적으로 실행할때는 10번째 Chunk가 실패한다면9번째까지의 Chunk가 성공했음이 보장되지만, 멀티쓰레드의 경우 1~10개의 Chunk가 동시에 실행되다보니 10번째 Chunk가 실패했다고 해서1~9개까지의Chunk가 다 성공된 상태임이 보장되지 않습니다. 그래서 일반적으로는 ItemReader의saveState옵션을false로 설정하고 사용합니다.
- 과연 dto를 테스트하는게 의미가 있는지 위와 같은 코드를 작성하는 게 의미가 있는지 등을 생각하게 되면서 jacoco 설정을 찾아보게 되었습니다.
- 저의 경우 dto와 querydsl에 의해 생기는 Q클래스를 제외하도록 특정 디렉토리의 특정 클래스를 제외시키는 방법을 사용하였습니다.( 제가 사용한 방법과 다른 방법 등은 아래 주소에서 확인하실 수 있습니다.)
// build.gradle 에 추가
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
"com/myintroduce/web/dto/*",
"**/Q*.class"
])
}))
}
}
예를 들어 고객이 원하는 상품을 어떻게 잘 제공할 것인가? 의 대한 문제는 커머스라는 도메인이 있습니다.
커머스 도메인의 하위 도메인으로 판매자가 무엇을 판매할 것인가? 의 대한 문제는 상품이라는 도메인이 있고,
공통된 상품에 대해서 어떻게 공통 정보를 제공할 것인가? 의 대한 문제는 카탈로그 도메인이 있습니다.
그 밖에 판매자, 사용자, 카테고리, 주문, 배송 등 많은 도메인이 존재합니다.
소프트웨어의 존재에 대한 가치
소프트웨어의 본질은 해당 소프트웨어의 사용자를 위해도메인에 관련된 문제를 해결하는 능력에 있습니다.
아무리 기술적으로 정교하고 뛰어난 성능을 갖추더라도 당면한 문제를 해결하지 못하는 소프트웨어는 실패한 소프트웨어라고 할 수 있습니다. 얼마나 빠른가, 얼마나 많이 처리할수 있나, 얼마나 많은 사람이 붙어서 사용할 수 있나 등은 나중 이야기입니다.
기존 개발의 문제점(비즈니스 로직의 위치)
데이터베이스 위주의 개발 (데이터베이스 모델링을 중요시) - 서비스에는 흐름제어 로직밖에 없고 비즈니스 규칙과 개념들은 SQL에 존재한다. 이렇게 비즈니스 로직과 저장 기술이 강하게 결합되어 있는 구조인 경우, 저장소를 변경하기 쉽지 않다. 또한 성능 측면에서 성능을 데이터베이스에 의존하게 된다. 이러면 데이터가 많아졌을 때 데이터베이스의 성능은 지속적으로 떨어지고 이를 최적화 하기 위해 데이터베이스 서버의 사양과 용량을 계속 증가시키고 쿼리 튜닝에 몰두할 수 밖에 없다. 클라우드 인프라를 사용한자동 스케일 아웃은 의미가 없어진다.정작 바쁜 것은 데이터베이스이기 때문에 어플리케이션을 아무리 스케일 아웃해봐야 효과는 미미하다.
트랜잭션 스크립트 패턴 - 서비스(Spring에서 사용되는 Service를 말함)에 모든 비즈니스 로직이 있고 비즈니스 절차에 따라 도메인 객체를 이용해 처리한다. 도메인 객체는 단지 속성값만 이용되는 정보 묶음의 역할만 하게 된다. 서비스는 유스케이스 처리의 단위이고 대부분의 비즈니스 로직 처리가 서비스에서 이뤄지므로 비슷한 유스케이스의 경우 서비스에중복되는 코드가 계속 생겨날 수 있고 이런한 점이 유지보수를 어렵게 한다.비즈니스 로직을 테스트하기 위해 Mocking을 해야하고 이는 테스트의 복잡성을 높이고 관리하기 어려운 테스트 코드를 발생시킨다.
그럼 비즈니스 로직은 어디에 있는 것이 좋을까요?
도메인 모델 패턴
도메인 객체가 속성뿐만 아니라 비즈니스 행위를 가지고 있어 책임을 수행하게 된다.
서비스의 책임들이 도메인으로 분산되기 때문에 서비스의 메서드는 단순해진다.
거대한 서비스 클래스 대신 각기 적절한 책임을 가진 여러 클래스로 구성되므로 이해하기 쉽고 관리 및 테스트하기 쉽다.
잘 정의된 도메인 모델은 코드양을 줄이고 재사용성도 높다.
도메인 모델 패턴은 도메인 주도 설계의 애그리거트 패턴을 적용할 수 있는 구조이다.
도메인 주도 설계
도메인 주도 설계는 크게 전략적 설계와 전술적 설계로 나뉩니다.
전략적 설계 - 도메인 전문가 및 기술팀이 함께 모여 유비쿼터스 언어를 통해 도메인 지식을 공유 및 이해하고 이를 기준으로 개념과 경계를 식별해 바운디드 컨텍스트(bounded context)로 정의하고 경계의 관계를 컨텍스트 맵(context map)으로 정의하는 활동
전술적 설계 - 전략적 설계에서 도출된 바운디드 컨텍스트와 도메인을 이용하여 애그리거트 패턴, 엔티티와 값 객체, 레포지토리, 등을 구성하고 구현하는 활동
전략적 설계
도메인과 서브도메인
도메인은 한 조직이 행하는 일과 그 조직 안의 세계를 의미합니다.
서브 도메인은 어떤 도메인 영역의 상위 도메인이 있는 것을 강조하기 위해 사용하는 용어입니다.
서브 도메인은중요도에 따라핵심 서브도메인, 지원 서브도메인, 일반 서브도메인으로 나눕니다.
핵심 서브도메인 - 다른 경쟁자와 차별화를 만들 비즈니스 영역이기 때문에 기업의 프로젝트 목록에서 높은 우선순위를 갖는 영역이자 소프트웨어 개발에서 전략적으로 가장 큰 투자가 필요한 영역. 예) 커머스 도메인에서 핵심 서브도메인은 주문, 결졔, 상품, 카테고리 등
지원 서브도메인 - 비즈니스에 필수적이지만 핵심은 아닌 부분으로 볼 수 있다. 그러나 핵심 도메인을 성공시키기 위해서는 반드시 필요한 영역. 핵심 서브도메인 다음으로 중요한 영역. 예) 커머스 도메인에서 지원 서브도메인은 카탈로그, 쿠폰 등
일반 서브도메인 - 비즈니스적으로 특화된 부분은 아니지만 전체 비즈니스 솔루션에는 필요한 부분으로 기존 제품을 구매해서 대체할 수 있다. 예) 커머스 도메인에서 일반 서브도메인은 파일관리, 인증관리 등
예시로 든 서브 도메인들은 커머스 도메인이라고 할지라도 회사마다 중요하게 보는 것이 다르기 때문에 달라질 수 있음
유비쿼터스 언어
같은 것을 보고 다른 용어를 사용하고 있다.
특정 도메인에서 특정 용어가 해당 도메인에서의 의도를 명확히 반영하고, 도메인의 핵심 개념을 잘 전달할 수 있는 언어
모든 팀원이 특정 용어를 들었을 때 같은 것을 생각할 수 있는 명확하게 정의된 언어. 같은 용어에 각자 다른 생각을 하거나 같은 것을 말하지만 용어가 다른 경우가 있으면 안된다.
도메인에서 사용하는 언어는 코드에 그대로 똑같이 반영되야 한다. 똑같이 반영되지 않으면 개발자는 해당 용어를 해석하고 이해해야하는 부담이 생긴다.
유비쿼터스 언어를 사용함으로써 코드의 가독성을 높여 코드를 분석하고 이해하는데 시간을 절약할 수 있다.
용어가 정의 될 때마다 용어 사전에 이를 기록하고 명확하게 정의 함으로써 추후 또는 다른 사람들도 공통된 언어를 사용할 수 있도록 한다.
용어사전 예시)
한글명
영문명
설명
상품
product
메뉴를 관리하는 기준이 되는 데이터
메뉴 그룹
menu group
메뉴 묶음, 분류
메뉴
menu
메뉴 그룹에 속하는 실제 주문 가능 단위
메뉴 상품
menu product
메뉴에 속하는 수량이 있는 상품
금액
amount
가격 * 수량
주문 테이블
order table
매장에서 주문이 발생하는 영역
빈 테이블
empty table
주문을 등록할 수 없는 주문 테이블
주문
order
매장에서 발생하는 주문
주문 상태
order status
주문은 조리 ➜ 식사 ➜ 계산 완료 순서로 진행된다.
방문한 손님 수
number of guests
필수 사항은 아니며 주문은 0명으로 등록할 수 있다.
단체 지정
table group
통합 계산을 위해 개별 주문 테이블을 그룹화하는 기능
주문 항목
order line item
주문에 속하는 수량이 있는 메뉴
매장 식사
eat in
포장하지 않고 매장에서 식사하는 것
바운디드 컨텍스트
도메인 영역의 경계
바운디드 컨텍스트안에서는 유비쿼터스 언어를 사용해야한다.
도메인 영역의 경계의 기준은 유비쿼터스 언어를 사용했을 때, 해당 용어의 개념이 달리지는 그 곳을 기준으로 경계를 나눈다.
바운디드 컨텍스트 경계
고객이라는 도메인은 결제 도메인 입장에서는 신용카드 정보나 계좌 정보를 가진 결제자로서 사용되고 배송 도메인 입장에서는 상품을 받을 주소와 우편번호, 전화번호를 소유한 수취자를 의미한다.
도메인 모델은 특정한 컨텍스트 안에서 완전한 의미를 갖는다.
바운디드 컨텍스트는 여러개의 서브 도메인으로 구성되고 하나의 서브 도메인은 한 바운디드 컨텍스트에 포함된다.
좋은 바운디드 컨텍스트
하나의 BOUNDED CONTEXT는 하나의 팀에만 할당되어야 한다.
하나의 팀은 여러 개의 BOUNDED CONTEXT를 다룰 수 있다.
각각의 BOUNDED CONTEXT는 각각의 개발 환경을 가질 수 있다.
컨텍스트 맵
컨텍스트 맵 예시
컨텍스트 경계를 식별해 내고 이들간의 관계를 표현한 그림을 컨텍스트 맵(Context Map)이라 한다
컨텍스트간의 관계는 선으로 표현되고 U는 Upstream으로서 공급자, D는 Downstream으로서 수요자를 나타낸다. 즉 데이터가 흐르는 방향
최근 서비스는 마이크로서비스 아키텍처 형태로 독립적인 기능을 수행하는 작은 단위의 서비스로 나누어 개발하고 있습니다. 작은 단위의 서비스로 분리함에 따라 서비스의 복잡도를 줄일 수 있으며, 변경에 따른 영향도를 최소화하면서 개발과 배포를 할 수 있다는 장점이 있습니다. 하지만, 여러 서비스의 엔드포인트를 관리해야 하는 어려움이 있으며 각 서비스의 API에서 공통적으로 필요한 기능을 중복으로 개발해야 하는 문제가 있습니다.
API Gateway는 사용자가 설정한 라우팅 설정에 따라 각 엔드포인트로 클라이언트를 대리하여 요청하고 응답을 받으면 다시 클라이언트에게 전달하는 프록시 역할을 합니다.
그뿐만 아니라 API Gateway는 엔드포인트 서버에서 공통으로 필요한 인증/인가, 사용량 제어, 요청/응답 변조등의 기능을 플러그인 형태로 제공하고 있습니다. 플러그인을 사용하면 각 엔드포인트 API 서버가 구현하지 않아도 되기 때문에 개발자 입장에서는 개발 비용을 줄일 수 있습니다.
TOAST API Gateway 살펴보기
TOAST API Gateway는 크게 2가지 개념으로 엔드포인트를 관리하고 있습니다.
도메인(Domain): 도메인은 하나의 엔드포인트 서비스를 관리하기 위한 개념입니다. 도메인은 도메인 키와 엔드포인트 정보를 설정할 수 있습니다. 도메인 키는 각 엔드포인트를 구분하여 라우팅하기 위한 키 값으로 이용됩니다.
엔드포인트(Endpoint): 엔드포인트에서 제공하는 REST API를 관리하는 역할을 합니다.
API Gateway 생성하기
예시: 블로그 서비스
다음과 같이 블로그 서비스는 3개의 엔드포인트로 서비스 구성되고 있다고 가정합니다.
account : 블로그 사용자들의 계정 정보를 관리하는 서비스
post : 블로그 글을 관리하는 서비스
storage: 포스트의 첨부파일(이미지, 도큐먼트 파일 등)을 관리하는 서비스
blog-account 도메인 생성
API Gateway를 생성하기 위해서는 가장 먼저 도메인을 생성해야 합니다. 3개의 서비스 중 account 서비스의 도메인 생성 예제입니다.
API Gateway가 클라이언트로 부터 요청을 전달받으면 설정된 플러그인의 속성 그룹 순서대로 플러그인이 동작합니다.
Access Control 에서 제한된 사용자의 요청, 사용 제한 초과 시 요청을 거부합니다.
Authentification 에서 인증되지 않은 요청, 변조된 요청에 대해 요청을 거부합니다.
Custom 에서 요청/응답에 대한 메시지 변조를 하거나 사용자 정의 응답을 정의할 수 있습니다.
Proxy 에서 사용자의 API 서버로 요청을 포워딩하고 응답 값을 전달받아 요청자에게 전달합니다.
Access Control
IP ACL
특정 클라이언트만 요청을 허용할 수 있도록 블랙/화이트리스트 방식의 IP 접근 제어 기능을 제공합니다.
사용량 제한(Usage Limit)
단위 시간(초 단위) 동안 호출 가능한 횟수만큼만 클라이언트가 API를 호출할 수 있도록 설정할 수 있습니다.
QoS(Quality of Service) 또는 엔드포인트 서버의 보호 목적으로 API 사용량을 제어할 수 있습니다.
CORS(Cross-Origin Resource Sharing)
동일 출처 정책(Same Origin Policy)에 의해 브라우저에서는 다른 도메인의 리소스를 요청할 경우 보안 문제를 발생시킵니다. 이를 우회하기 위해서는 CORS 규약에 의해 웹 브라우저와 서버 간 정의된 헤더와 함께 요청과 응답 주고 받아야 합니다. CORS 플러그인을 사용하면 엔드포인트에서 구현하지 않아도 되며, 변경이 발생하는 경우에도 쉽게 설정을 변경할 수 있습니다.
Authentication
사전 호출 API (Pre-call API)
API Gateway가 클라이언트의 요청을 엔드포인트로 포워딩하기 전, 설정한 사전 호출 API를 호출합니다. 사전 호출 API의 응답 HTTP Status Code가 200 OK가 아닌 경우 요청을 거부합니다.
사전 호출 API를 통해 사용자 정의 형식의 인증을 처리할 수 있습니다. (예: 세션 토큰의 유효성 검사)
HMAC, JWT
클라이언트의 요청이 중간에 변조되진 않았는지 무결성을 검증합니다.
HMAC 또는 JWT 플러그인에서 비밀키를 설정합니다.
클라이언트는 비밀키를 이용하여 요청정보의 해시 값을 생성하여 요청 헤더에 추가하여 API Gateway로 요청을 전달합니다.
API Gateway는 클라이언트의 요청 정보와 사용자가 설정한 비밀키를 이용하여 해시 값을 생성합니다.
클라이언트가 전송한 해시 값과 API Gateway가 생성한 해키 값이 일치하지 않은경우, 무결성이 보장되지 않은 것으로 보아 요청을 거부합니다.
Custom Plugin
Modify Header
엔드포인트 서버로 전달되는 요청의 헤더값을 변조하여 엔드포인트로 요청할 수 있습니다.
클라이언트로 전달되는 응답의 헤더값을 변조하여 클라이언트에 응답을 전달 할 수 있습니다.
URL Rewrite
클라이언트의 요청 URL을 변조하여 사용자의 엔드포인트 서버 URL로 요청을 포워딩할 수 있습니다.
사용자 정의 응답 (User-defined Response)
사용자가 정의한 응답 헤더와 본문(Body)을 응답하도록 설정합니다.
통계
API Gateway 콘솔> Dashboard 에서 각 도메인별 API 통계를 확인할 수 있습니다.
API 호출 성공 수(HTTP 400미만), 실패 수(HTTP 4XX, 5XX) 그리고 평균 응답시간(ms)과 아웃바운드 네트워크 트래픽를 확인할 수 있습니다. 통계를 통해 특정 엔드포인트의 REST API의 이상 동작이나 품질을 쉽게 확인할 수 있습니다.
API는 서버와 데이터베이스에 대한 출입구 역할을 한다. : 데이터베이스에는 소중한 정보들이 저장되는데요. 모든 사람들이 이 데이터베이스에 접근할 수 있으면 안 되겠지요. API는 이를 방지하기 위해 여러분이 가진 서버와 데이터베이스에 대한 출입구 역할을 하며, 허용된 사람들에게만 접근성을 부여해줍니다.
API는 애플리케이션과 기기가 원활하게 통신할 수 있도록 한다. : 여기서 애플리케이션이란 우리가 흔히 알고 있는 스마트폰 어플이나 프로그램을 말합니다. API는 애플리케이션과 기기가 데이터를 원활히 주고받을 수 있도록 돕는 역할을 합니다.
API는 모든 접속을 표준화한다. API는 모든 접속을 표준화하기 때문에 기계/ 운영체제 등과 상관없이 누구나 동일한 액세스를 얻을 수 있습니다. 쉽게 말해, API는 범용 플러그처럼 작동한다고 볼 수 있습니다.
API 사용하면 뭐가 좋을까?
API를 사용하면 많은 이점들이 있는데요. Private API를 이용할 경우,
개발자들이 애플리케이션 코드를 작성하는 방법을 표준화함으로써, 간소화되고 빠른 프로세스 처리를 가능하게 합니다.
EndPoint
A web service endpoint is the URL where your service can be accessed by a client application.
Difference
API vs Endpoint An API refers to a set of protocols and tools that allow interaction between two different applications. In simple terms, it is a technique that enables third-party vendors to write programs that can easily interface with each other. On the other hand, an endpoint is the place of interaction between applications. API refers to the whole set of protocols that allows communication between two systems while an endpoint is a URL that enables the API to gain access to resources on a server.
결국 API란 두 시스템, 어플리케이션이 상호작용(소통) 할 수 있게 하는 프로토콜의 총 집합이라면 ENDPOINT란 API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL이다
MSA는 MicroService Architecture의 줄임말로, 소프트웨어 개발 기법 중 하나입니다. MSA는 작고, 독립적으로 배포 가능한 각각의 기능을 수행하는 서비스들로 구성된 프레임워크입니다. 경량화되고 독립적인 여러 개의 서비스를 조합하여 애플리케이션을 구현하는 방식으로 서비스마다 자체 데이터베이스를 가지고 동작하기 때문에 개발부터 빌드, 배포까지 효율적으로 수행할 수 있습니다.
MSA 등장 배경
애플리케이션 개발 초기에는 전체 소스 코드를 하나의 배포 유닛 (war 또는 ear)으로 내장시키는 'Monolithic' 방식을 사용하였습니다. 하지만 기존 애플리케이션의 사소한 변경사항이 있더라도 자체적인 QA(Quality Assurance) 주기에 따라 업데이트를 하거나 일부 서비스 업데이트로 오류가 발생한 경우 전체 시스템을 중단하고 오류를 해결하는 등의 다운타임이 발생하는 일이 빈번하였습니다. 이러한 문제점을 해결하기 위해 애플리케이션의 핵심 서비스를 분할하는 MicroService Architecture라는 방식이 생겨났으며 각 서비스들을 독립적으로 구축하고 배포할 수 있게 되었습니다.
Monolithic이란?
Monolithic은 소프트웨어의 모든 구성요소가 한 프로젝트에 통합되어 있는 형태이며, 모듈별로 개발을 하고 개발이 완료된 하나의 결과물로 패키징 하여 배포되는 형태를 의미합니다.
장점
개발 초기에는 단순한 아키텍처 구조와 개발 용이함
단점
서비스 규모가 커짐에 따라 전체 시스템 구조 파악 및 유지보수가 어려워짐
부분 장애가 전체 서비스의 장애로 확대될 수 있음
배포 시간이 오래 걸림
한 Framework와 언어에 종속적
부분적인 Scale-out(여러 서버로 나누어서 일을 처리 방식)이 어려움
MSA 장점
분산형 개발을 통해 개발 주기가 단축되기 때문에 빠르고 유연한 배포가 가능 (출시 기간 단축)
서비스가 독립적이기 때문에 다른 서비스에게 영향을 주지 않음 (뛰어난 복구 능력)
서비스별 기술 도입 및 확장이 자유로움 (높은 확장성)
모놀리식 방식에 비해 애플리케이션이 모듈화 되고 규모가 작기 때문에 우려사항이 줄어듦 (손쉬운 배포)
다중 언어 지원(Polyglot) API를 사용 (향상된 개방성)
하나의 애플리케이션을 여러 부분으로 분할했기 때문에 각 서비스 업데이트 및 개선 용이 (편리한 액세스)
MSA 단점
각 서비스들은 API를 통해 통신하므로 네트워크 통신에 의한 오버헤드 발생
서비스별로 로그가 생성되므로 중앙 로그 모니터링이 존재 X
하나의 프로젝트에 수많은 서비스들이 존재하므로 모든 서비스 모니터링 오버헤드 증가
하나의 서비스에서 다른 서비스를 호출하므로 장애 발생 시 경로 및 장애 추적이 힘듦
서비스가 분산되어 있기 때문에 모놀리식에 비해 상대적으로 많이 복잡
MSA 사례 (bingle)
기존 인프라 구조
Elastic Load Balancer : 둘 이상의 가용 영역에서 EC2 인스턴스, 컨테이너, IP 주소 등 여러 대상에 걸쳐 수신되는 트래픽을 자동으로 분산합니다.
EC2로 트래픽 분산
AWS Opsworks로 배포, 관리
기존 인프라 구조의 문제점 레파지토리 하나에 기능이 전체 포함되어 있었다. 그의 문제는, commit이 복잡하고 테스트에 시간이 너무 걸린다는 것.
언제나 모든 서비스를 함께 디플로이, 스케일 하는것
새로운 기술 도입이 어려움(기능 추가)
바로 시도해 볼 수 있는 상황이 아니기때문에, 기술적 자유로운 사고가 어렵다.
Bingle의 혁신목표
독립적 스케일링
독립적 배포
독립적인 기술 스택
독립적인 개발 언어
독립적인 테스트, 모니터링
마이크로서비스를 위한 AWS 템플릿 준비
API게이트웨이 - Lambda - DB (예전에 했던 프로젝트도 이런느낌)
인프라를 코드로 관리
이상의 기능들은 무한, 자동 스케일링이 가능하기때문에 서버 안정성이 확보
Lambda 업로드, 끊기지않고 바로 업로드, 배포 가능
스팸 필터 마이크로 서비스 구조 만들기 DynamoDB의 스팸 URL, 단어등을 추가 시켜서 필터 Lambda에서 해당 필터조건을 가지고 필터링 기능을 구현시킨 것 (이것의 장점은 다양한 기능에 적용시킬 수 있다는 것이고, DynamoDB에 스팸 URL추가하기도 쉽고, 배포, 테스트하는 것이 모두 코드로 자동화 할 수 있다는 것이다. 그리고 얼마나 많은 스팸체크를 했는지 확인 할 수 도 있다.)
마이크로서비스로의 마이그레이션
새로 추가되거나 변경이 필요한 기능부터 하나씩 분리
BusinessDomain 단위로 서비스 구성(search, feed, tracking등)
다른 개발자가 쓰기 쉽도록 인터페이스화, Swagger 문서화
AWS에서 제공하는 managed서비스 활용 CloudSearch, KinesisStream등
Java Application은 JVM(Java Viirtual Machine) 위에서 구동됩니다. JVM에서는 Java Application이 사용하는 메모리를 관리하고 있는데 이 JVM의 기능중 더 이상 사용하지 않는 객체를 청소하여 공간을 확보하는 GC라는 작업이 있습니다.
GC란 Garbage Collection(쓰레기 객체 정리, 이하 GC)의 약자입니다. Java Runtime시 Heap 영역에 저장되는 객체들은 따로 정리하지 않으면 계속헤서 쌓이게되어 OutOfMemmory Exception이 발생할 수 있습니다. 이를 방지하기 위하여 JVM에서는 주기적으로 사용하지 않는 객체를 수집하여 정리하는 GC를 진행합니다.
JAVA에서GC의 도입의 전제 가설(weak generational hypothesis)
대부분의 객체는 금방 접근 불가능 상태 (unreachable)가 된다.
오래된 객체에서 젋은 객체로의 참조는 아주 적게 존재한다.
아래와 같이 객체를 생성하고 해당 객체의 어떤 동작을 10,000번 수행하는 반복문에서 마지막 한번을 제외 한 9,999번의 객체들은 생성 후 바로 접근 불가능 상태가 된다. 이를 unreachable 상태라고 하며, GC가 발생하지 않으면 10,000개의 객체 현재 참조 되지 않지만 메모리를 점유 하고 있다고 볼 수 있다.
for (int i = 0; i < 10000; i++) {
SampleObj obj = new SampleObj();
obj.doTest(i);
}
또 아래와 같이 객체를 생성하고 다른 메소드나 클래스에 해당 객체를 전달 후 에는 다시 참조 하지 않는 경우가 대 부분이다. 이를 오래된 객체에서 젊은 객체로의 참조는 아주 적게 발생 한다라고 말 할 수 있다.
SampleObj obj = new SampleObj();
obj.setValue(1);
doTest2(obj);
JVM의 메모리 영역
GC의 수행영역별 구분
Eden영역부터 Servior영역까지를 Young 영역이라고 부릅니다. 크게 Young, Old, Perm 영역으로 나누어 지는데 JDK 8버전 부터는 이 영역이 사라졌습니다.
GC는 수행되는 영역에 따라 두가지로 구분 할 수 있다.
GC가 수행되는 영역에 따라Minor GC 와 Major GC(Full GC) 로 구분한다.
Minor GC는Eden과Survivor1,2의Young Generation영역의 객체를 메모리에서 삭제한다.
Major GC는Minor GC과정에서 삭제 되지 않고,Old Generation영역으로 옮겨진 객체 중 미사용 된다고 판단되는 객체를 메모리에서 삭제한다.
SWT(Stop-The-World)
GC를 이해하고자 할 때 중요한 요소가 있다.
GC가 발생하고 이를 수행하는 과정에서 진행중인 쓰레드는 멈추고GC를 수행하는 쓰레드만 동작하게 되는 데 이를Stop-The-World라 부른다. 이 Stop-the-world가 경우에 따라서는 시스템 장애로 이어 질 수 있기 때문에 GC와는 떼어 놓을 수 없다.
메모리 영역이 크게 설정 되어 있으면, GC가 발생하는 횟수를 줄일 수 있지만, GC 수행 시간은 증가 하기 때문에 최적화가 필요 할 수 밖에 없는 이유이다.
STW(Stop-The-World)
GC가 발생하면JVM은 어플리케이션을 멈추고,GC를 실행하는쓰레드만동작하게 되고 이를Stop-The-World라고 한다.
STW가 발생하는 동안은 어플리케이션이 중지 되기 때문에 장애로 이어 질 수 있다.
GC 발생 시나리오
GC는 기본적으로 다음과 같은 시나리오로 동작한다.
객체가 생성되면 Eden 영역에 위치 하게 된다.
Eden영역이 가득차게 되면 Minor GC가 발생하여 참조가 없는 객체는 삭제되고, 참조 중인 객체는 Suvvivor 영역으로 이동한다.
Survivor영역이 가득차게 되면 Minor GC가 발생하고 참조가 없는 객체는 삭제되고, 참조 중인 객체는 다른 Survivor2영역으로 이동한다.
Survivor 영역에서의 GC과정을 반복 하며, 계속 참조 중인 객체는 OLD 영역으로 이동한다.
예외) Eden 영역에서 Survivor 영역으로 이동 할 때 객체가 남아있는 영역보다 큰 경우 OLD 영역으로 이동한다.
GC 수행 방식에 따른 종류와 변화
JVM 버전의 변화에 따라 여러가지 GC방식이 추가 되고 발전되어 왔다.
버전별로 지원하는 GC는 차이가 존재하며, 서비스 상황에 따라 필요한 GC방삭을 JVM옵션을 통한 설정으로 사용이 가능하다.
GC의 종류는 다음과 같다.
Serial Garbage Collector
-주로32비트JVM에서 돌아가는싱글쓰레드어플리케이션에서 사용(별도로 지정하지 않는 경우 기본GC) -Minor GC 뿐 아니라 Major GC인 경우도 올스탑(stop-the-world)하는 싱글쓰레드 방식.
Parallel Collector(=Throughput Collector)
-64비트JVM이나멀티CPU유닉스머신에서기본GC로 설정되어 있음. - MinorGC와 MajorGC 모두 멀티쓰레드를 사용. -MinorGC뿐 아니라MajorGC인 경우도올스탑(stop-the-world)
CMSCollector (ConcurrentMark-Sweep)
-Initial Mark단계에서참조 상태인 객체를짧은 시간에Marking후,올스탑없이Concurrent Mark단계에서참조상태 객체를 확인.Remark단계에서변경되거나 추가된 객체를 확인.ConcurrentSweep단계애서참조 되지 않는 객체를 정리. -CPU리소스를 많이 사용,메모리 파편화가 단점.
G1 Collector (Garbage First)
- 기존 Young, Old 영역의 개념과 다른 Heap에Resion개념을 도입함. - 하나이상의Resion에서 객체를 복사해 다른Resion으로 이동 시키는 방식. -CMS와 비슷한 방식으로동작 시작.Heap에전역적으로Marking하고,가장많은 공간이 있는 곳부터 메모리 회수 진행. 이 부분 때문에Garbage First라는 이름이 붙었다. - CMS Collector의CPU리소스 및 메모리파편화의 단점 해결.