1. 시행 개요
MSA (Micro Service Architecture)
현재 담당하는 업무는 각각 독립된 역할을 하는 여러 서비스 (약 40여개의 서비스 존재)들로 구성되어 있다. Interface, Core 처리, Gateway 등 각 역할에 맞는 서비스들이 존재하며 유기적으로 연결되어 있다.
각 서비스는 작고 독립적이며 느슨하게 결합되어 있다. 때문에 서비스 각 독립적으로 배포할 수 있다는 장점이 있다.
단점으로는 서비스 간 통신이 필요하다는 점이다. 이로 인해 복잡해질 수 있으며, 상호작용 테스트가 어렵다. 또한 통합 유지관리가 어렵다는 단점이 존재한다.
위의 관점에서 보았을 때 현 업무는 통합 관리가 정상적으로 이뤄지지 않고 있다. 각 Transaction 이 유기적으로 어떻게 연결되는 지 업무를 오래 담당하던 사람이 아니면 파악하기 힘들다.
또한, 로깅룰 마저 각 프로세스 별로 상이하게 작성되어 있어 Transaction 추적이 용이하지 않다.
이중화
담당 업무는 각기의 서버 롤에 맞게 IDC 내에 이중화가 되어 있다.
서버 롤은 인터넷망, 전용선망, 내부망, 배치존 등이 존재하며 모두 Round Robin을 통해 L4이중화 되어 있다.
이는 위 MSA 아키텍쳐와 맞물려 운영 복잡도를 기하급수적으로 증가 시킨다.
일례로 기본이 되는 트랜잭션은 아래와 같은 프로세스를 통해 트랜잭션이 처리된다.
some_interface -> some_core -> some_gw
위 트랜잭션 사이클을 모두 확인하기 위해서는 interface 프로세스가 존재하는 대외망 서버를 01, 02 번 모두 확인하고, 내부망 어디에서 처리되었는 지 내부망 서버 01, 02를 확인해야한다. 마지막으로 타 기관 연동 확인을 위해 대외망 서버 01, 02 다시 확인해야 한다.
위 프로세스에서 병렬처리가 추가되거나 또 다른 기관과의 통신이 추가되면 복잡도는 더 올라가고, 추적은 쉽지 않게 된다.
서비스가 많은만큼 경우의 수 또한 증가하는 것이다.
2. 개선
Trace Id 와 Span Id
- Trace Id : 전체 작업에 할당된 ID이다. 한 Transaction을 추적하는 데 사용. 작업에 작은 단위들이 존재한다면, 각각의 작은 단위들은 공통의 TraceId 를 부여받는다.
- Span Id : 각각의 작은 단위들이 가지고 있는 ID. 모두 서로 다른 ID를 가지고 있기 때문에 서로 다른 작업단위들을 구분해주는 역할을 한다.
- 위 TraceId와 SpanID를 로깅하고, 각각의 통신에서 Header를 통해 주고 받으며 Transaction을 추적할 수 있게 수정.
c.f. 위의 TraceId와 SpanId 는 Spring Cloud Sleuth를 사용하면 손쉽게 구성할 수 있다. 단, 현재 회사가 ISMS 인증으로 인해 온라인 라이브러리 다운로드가 쉽지 않은 점, 존재하는 각 모듈들의 스프링 부트 버전이 제 각각 상이한 점으로 인해 직접 구축하는 것이 낫다고 판단해 직접 개발.
2. 기존 로그
2023-07-03 17:47:42.605 [71898] INFO Logger.log(29) - 10.222.241.5 |REQ|TCP 전문 내용 ...|
구성 : YYYY-MM-DD HH:MI:SS.SSS [thread name] 로그레벨 로깅 클래스 - .. 로깅 내용
3. TO-BE log
2023-07-03 17:47:42.605 [71898, f62969423d8a42cc, 6t123789d8a42cc] INFO Logger.log(29) - 10.222.241.5 |REQ|전문내용|
구성 : YYYY-MM-DD HH:MI:SS.SSS [thread name, trace id, span id] 로그레벨 로깅 클래스 - .. 로깅 내용
4. 구성 방법
a. 알아야 될 기술
- MDC(Mapped Diagnostic Context) : JAVA Map 형식으로 클라이언트의 특징적인 데이터를 저장하기 위한 메커니즘으로 slf4j, logback, log4j2 등 현재 담당 업무에서 사용 중인 log 라이브러리에 모두 적용 가능.
MDC.put("traceId", UUID.randomUUID().toString().replace("-", "").substring(0, 16));
MDC.clear();
- logback.xml, log4j2.xml 등.. : 로깅 형식을 적용 하기 위해 pattern 등을 지정하는 로깅 관련 config xml.
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %yellow(%X{traceId}, %X{spanId}) %highlight(%-5level) %cyan(%logger{36}.%M%magenta(\(%line\))) - %msg%n</pattern>
</encoder>
</appender>
Http Header 투입 : TRS 내부 통신은 모두 HTTP로 통신됨으로 Http Header 이용 가능.
httpHeaders.put("X-B3-TraceId", traceId); httpHeaders.put("X-B3-SpanId", spanId); httpHeaders.put("X-B3-ParentSpanId", parentSpanId);
참고 : Spring Framwork에서 사용하는 HTTP 관련 라이브러리로 RestTemplate, Jersey, WebClient 등이 존재. 현 업무에선 RestTemplate, Jersey 두 가지 모두 사용되고 있으므로 각 프로젝트의 사용 라이브러리에 맞는 Header 값 세팅 방법 필요.
Request Filter : RestTemplate, Jersey 두 가지 모두 가능한 방식으로 Controller 단에 도착하기 전 먼저 시행되는 RequestFilter 를 구현 가능. -> RequestFilter에서 MDC 세팅 등 필요.
병렬처리로 인해 신규 스레드 생성하여 실행되는 경우 각 신규 스레드에 모두 span id 부여 필요.
'로직과의 사투 > Operational Issues' 카테고리의 다른 글
로깅 룰 구축기 (2) - Jersey에 적용하기 (0) | 2023.09.26 |
---|---|
네이티브 메모리 누수 추적기 (0) | 2023.07.25 |