출처 :
마이크로서비스 패턴 (책)
독후감
궁금한점
4가지 보안 요소 구현해야함.
기존 모놀리스 FTGO 에서의 방식
인메모리 세션의 단점은 sticky 걸어줘야한다.
아니면 세션을 아예 없애기.
msa 에서는 보안 구현이 왜 어려울까?
가령 주문 서비스는 소비자 본인의 주문 정보만 조회할수 있어야 한다.
그러려면 인증/인가 를 조합해야 한다.
인증/인가를 누가 담당해야하나?
모놀리식에서 썼던 다음 2가지 방법은 msa 에서 쓸수 없다.
인메모리 보안 컨텍스트
메모리를 공유할수가 없기 때문에 인메모리 보안컨텍스트를 쓸수 없다.
중앙화 세션
인메모리 보안 세션도 마찬가지다.
셰어드 DB 를 쓰면 DB기반 세션을 이용하면 가능은 하지만..
여러가지 방법 존재
서비스마다 알아서 사용자를 인증하는 방식
단점 많다.
게이트웨이에서 하는게 좋다.
API 클라이언트와(A)
, 로그인 기반 클라이언트(B)
의 흐름도.
도메인로직. 즉 개별 애그리게잇에 ACL 을 gw 에 구현하는건 무리.
서비스에서 한다.
역할 기반으로 URL 과 메서드를 인가 하고, ACL로 애그리거트 접근을 따로 관리.
jwt 는 transparent token 의 표준 규격.
두 당사자 간의 사용자 신원/역할 등의 정보를 안전하게 표현하는 표준 수단.
json payload.
jwt 생성자와 수신자만 알수있는 시크릿으로 서명.
제3자가 위변조 하기는 거의 불가능.
하지만 jwt는 토큰 자체가 포함되어 있기 때문에 취소할수 없다.
그래서 만료일자를 짧게해서 탈취되도 뭔가 못하게.
잦은 갱신의 부담은 OAuth 2.0 표준으로 해결 가능.
깃헙, 구글 같은 퍼블릭클라우드 서비스가, 자기 정보에 접근하는 서드파티에게 패스워드 노출 없이 허가할수 있는 방안을 찾다 정착된 프로토콜.
OAuth 2.0 주제는 깊다. 코딩공작소 7장도 괜찮은 참고자료.
로그인 기반 클라이언트 인증
과API 클라이언트 인증
가 있다고 했다.
먼저 API 클라이언트 인증
의 흐름.
다음은 로그인 기반 클라이언트 인증
의 흐름.
1~4 부분이 클라이언트가 로그인 하는 과정이다. (access_token 과 refresh_token 을 쿠키 형태로 내려준다)
이후 부터는 두 토큰을 요청마다 담아서 보낸다.
그림에는 없지만, 만료된 경우 gw는 인증서버에 리프레시 승인을 요청한다.
외부구성 설정 방식 2가지.
스프링 부트는 외부화 구현 메커니즘을 제공함.
우선순위
1. CLI 인수
2. OS 환경변수
3. jvm 시스템 프로퍼티
4. OS 환경 변수
5. 현재 디렉터리의 구성파일
구성서버는 여러가지 방법으로 구현 가능
인스턴스 시동할때, 구성 전용 서버에 접속해서 pull.
구성서버 접속 url 정도는 배포 인프라에 등록되어있어야 한다.
spring cloud config
server/client?
서버 : 버전관리시스템, DB, 해시코프볼트 등 구성 프로퍼티를 저장하는 다양한 백엔드기술 지원.
클라 : 서버에서 구성 프로퍼티를 가져와 application context에 주입하는 역할
구성서버 장점?
서버 운영자 입장에서, 초당 요청수, 리소스 이용률, 앱의 상태(disk, mem, cpu..) 등등 이 궁금함.
하드웨어 가용성 자체에대한 모니터링은 aws 알람 등을 활용해도 되지만, 서비스 동작에 대한건 개발자가 해주는것이 좋겠다.
가령 헬스체크 API 제공은 개발자가, 운영자는 API 를 주기적으로 호출하여 시스템 모니터링 이라고 구분하긴 하지만 그냥 다 개발자가 하는경우도 있지.
rdbms 에는 테스트 쿼리를 날리는 식으로 구체적으로 상태체크를 해야한다.
spring boot acuator
도 구성보다 관습(convention over configuration)
이 적용되어 있다.
rdmbs 가 다운되어있거나 rabbitmq 가 가동중인지 헬스체크하는 로직이 자동 구성 되어있다.
즉 health 가 DOWN 상태로, 503을 반환한다.
eb 를 쓰고 있다면 5변 연속 실패시 서비스에서 제외시킨다.
여기서 궁금!
db나 브로커가 문젠건데, 인스턴스가 out of service 되는게 맞는걸까?
새 인스턴스를 띄워봤자 문제는 여전히 발생할것.
근데 로컬에서 테스트해보니, db 를 죽이면 down 으로 바뀌긴 하는데, 다시 살려봤자 up 으로 바뀌진 않더라. 그런의미에서는 새 인스턴스를 띄우는게 도움이 되려나?
자바는 로그 3총사(logback, log4j, jul) 가 있고, 퍼사드인 SLF4 를 쓰고 있을것.
기존에는 파일 시스템 경로에 로그 파일이 생성되도록 설정했었다.
그러나 컨테이너, 서버리스 등 요즘 배포에서는 stdout 에 로깅한다.
(서버리스는 파일시스템 자체가 없다)
서비스의 stdout 을 갖고 뭘 할지는 배포 인프라가 결정함.
보통 elk 를 쓴다.
외부 요청마다 유일한 ID (traceId) 를 부여한다.
trace는 하나 이상의 Spen 으로 구성된다. (최상위는 gw 일거고, 계속 자식 스팬이 생성된다)
작업명, 시작/종료 타임스탬프 등 으로 구성되어있다. (mdc context 를 볼수있게 되어있지 않을까 싶다)
instrumentation library 와 추적서버로 구성되어있다
각 서비스는 외부 요청이 들어올때마다 traceId 를 할당. 서비스 간 상태 추적을 전파하면서 분산 추적 서버에 스팬을 보고 한다.
AOP 프레임 워크인 스프링 클라우드 슬루스
를 쓰면 알아서 분산 추적 API 를 호출한다.
instrumentation 라이브러리가 보고한 스팬을, 짜깁기 해서 완전한 트레이스 형태로 만들어 DB 에 저장한다.
집킨 은 잘 알려진 분산 추적 서버이다.
sql/no sql db 같은 저장소에 보관한다.
화면 ui 도 있다.
aws 엑스레이도 분산 추적 서버의 일종이다.
x-ray 는 비용과 효율이 좋지 않다고 하더라.
집키이든 x-ray든 번거로우면 그냥 슬루스만 쓰라고 하더라. 연동도 쉽고
서비스에서 서비스로 흘러가는 과정을 기록
traceId 로는 해당 요청의 모든로그를 찾을수 있다.
다음은 마이크로미터 메트릭스
라는 라이브러리를 사용한 예시코드이다.
public class OrderService {
@Autowired
private MeterRegistry meterRegistry;
public Order createOrder(...) {
...
meterRegistry.counter("placed_orders").increment();
return order;
}
public void approveOrder(long orderId) {
...
meterRegistry.counter("approved_orders").increment();
}
public void rejectOrder(long orderId) {
...
meterRegistry.counter("rejected_orders").increment();
}
push
방식 : aws cloudwatch
pull
방식 : 프로메테우스.
Ftgo 는 micrometer-registry-prometheus 라이브러리로 연계한다.
라이브러리 추가후, GET /actuator/prometheus
하면 프로메테우스가 기대한 포맷으로 지표를 가져올수 있다.
아래는 지표 포맷.
$ curl -v http://localhost:8080/actuator/prometheus | grep _orders
# HELP placed_orders_total
# TYPE placed_orders_total counter
placed_orders_total{service="ftgo-order-service",} 1.0
# HELP approved_orders_total
# TYPE approved_orders_total counter
approved_orders_total{service="ftgo-order-service",} 1.0
중복된 예외를 제거하고, 알림을 생성하고, 예외 해결 과정을 관리하는 중앙 서비스에 예외를 보고한다.
sentry나 허니배저가 있다.
고객지원, 컴플라이언스 준수, 수상한 동작 감지를 위해 사용자 액션을 DB에 저장한다.
마이크로서비스 섀시 프레임워크를 써서 횡단관심사를 해결하자.
외부화 구성
헬스 체크
지표
서비스 디스커버리
회로 차단기
분산 추적
외부화 구성 스프링부트
회로차단기 - 스프링클라우드
마이크로서비스 섀씨는 다양한 횡단 관심사를 구현하기 좋은수단.
하지만 다른 언어에는 소용이 없다.
서비스메시 패턴이란?