분류 전체보기
-
좌충우돌 Coroutine 적용기실무에서 알게된 내용 2022. 7. 1. 01:41
최근 담당하고 있는 서비스에 Coroutine을 적용할 기회가 있었다. 이에 Coroutine를 적용하면서 알게 된 내용을 정리해보고자 한다. 참고로 코루틴 개념을 처음 접한 건 3년 전 어드민 서비스를 만들 때 Generator함수를 사용해 보면서 였다. Coroutine이란 무엇일까? 사람들마다 정의가 조금씩 다를 순 있겠지만 나는 코루틴을 비동기 프로그래밍을 하기 위한 일시 정지 가능한 경량화된 스레드(light-weight thread)라고 정의를 내린다. 그럼 경량화된 스레드란 무엇일까? 이것에 앞서 프로세스와 스레드의 개념부터 우선 정리해 보고자 한다. 흔히 프로세스는 실행되고 있는 프로그램(disk에 있는 program이 memory에 올라간 상태) 또는 OS로부터 시스템 자원을 할당받는 작..
-
모듈간 의존성 개선 및 정리 작업실무에서 알게된 내용 2022. 6. 30. 10:08
Edge API 전환 작업을 진행하며, 추가로 모듈 간 의존성을 개선 및 정리하는 작업을 조금 진행했었다. 아직, 완벽하다고 말할 수 있는 상태는 아니지만 해당 작업을 진행하며 개인적으로 고민했던 사항들을 아래와 같이 정리해 봤다. 참고로, 내가 담당하고 있는 서비스의 모듈은 아래와 같이 총 7개로 구성돼 있다. internal api external api service domain common common-web client 1. api 모듈(internal/external)이 의존하고 있는 모듈 (as-is: 5개, to-be: 4개) common common-web api 모듈(internal/external)에서 각각 선언해서 사용하고 있던 request/response 객체를 common-w..
-
로그가 간헐적으로 중복 노출되는 이슈실무에서 알게된 내용 2022. 6. 29. 08:56
작업했었던 프로젝트를 배포하고 모니터링을 하는데, 로그가 간헐적으로 중복 노출되는 이슈가 있었다. 사실 처음에는 다른 로그들은 한 번씩만 남고 있는 상태였기 때문에 로그가 중복 노출될 거라는 생각은 전혀 하지 못했다. 따라서, 당연히 휴먼에러로 인해 애플리케이션 레벨에서 의도치 않게 작업이 여러 번 수행되고 있을 거라는 생각을 가장 먼저 했다. 하지만, 아무리 생각해봐도 애플리케이션 레벨의 이슈는 아닌 것 같았다. 왜냐하면, 간헐적으로 중복 노출됐던 로그 중 하나가 아래 코드 부분이었는데 DB로부터 데이터를 읽어와서 publish 메소드를 호출하는데, 여기서 간헐적으로 해당 메소드가 여러 번 호출되는 건 로직상 불가능하다고 생각했기 때문이다. 또한, 이 시점에 중복 노출됐던 로그 정보를 자세히 확인해 봤..
-
ClientAbortException은 언제 발생하는가?실무에서 알게된 내용 2022. 6. 23. 08:05
서비스 모니터링을 하다가 아래처럼 ClientAbortException(java.io.IOExceiption: Broken pipe)이 발생하고 있는 것을 확인했다. 이에 해당 Exception이 언제 발생하는지를 분석해 봤다. 일단 해당 로그를 보면서 가장 눈에 띄었던 포인트는 특정 API를 호출하는데 4초가 걸리는 점과 예외 메시지에 org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe이 있다는 점이었다. 이를 근거로 클라이언트 쪽에서 API 응답 시간이 오래 걸리니까 서버에서 응답을 내려주기 전에 커넥션을 끊어 버려서 그런가?라는 의심을 했었다. 코드를 분석해보니 아래 빨간 네모 부분에서 Excepti..
-
운영 배포 전에 챙겼던 Kafka Producer Client 포인트들실무에서 알게된 내용 2022. 6. 22. 11:36
1. 주요 옵션 정리 buffer.memory producer가 kafka 서버로 데이터를 보내기 전에 잠시 기다리는 버퍼 메모리 공간 기본값은 33,554,432 byte (32MB), compression.type producer가 데이터를 보낼 때 압축을 해서 보낼 수 있는데, 이때 압축하는 방식 기본값은 none retries 일시적인 오류로 producer가 데이터 전송에 실패할 경우, 재전송할 횟수 acks producer가 kafka로 데이터를 전송한 뒤 요청 완료를 결정하기 위한 옵션 0(빠른 전송), 1(리더만 메시지를 받았는지 확인), all(모두 메시지를 받았는지 확인) batch.size producer가 여러 데이터를 같은 파티션을 전송할 때 batch방식으로 보내는데 이때의 크기..
-
컬럼 값을 Collection으로 받을 때 Querydsl 이슈실무에서 알게된 내용 2022. 6. 21. 21:09
최근 팀 내에서 GW 방식으로 통신하던 것들을 Edge API로 전환하는 작업을 하고 있다. 이 때문에 Querydsl를 사용해서 쿼리를 작성해야 하는 일이 있었다. 그런데, 특정 검색조건에 대해 Querydsl을 작성하고 DB 통합 Test를 돌렸더니 갑자기 NPE(NullPointerException)가 발생했다. (참고로 현재 내가 맡고 있는 서비스에서는 DB 통합 Test를 위해 Database Rider을 사용하고 있다.) 처음 들었던 생각은 애초에 말도 안 되는 생각이지만 '데이터가 없어서 그런가?'였다. 역시나 이건 아니었다. 이에 코드를 분석해 봤더니 아래 빨간 네모에서 null 값을 리턴하고 있어서 NPE가 발생하고 있었다. [MethodNode 클래스] 여기서 궁금증이 하나 생겼다. ..
-
Grafana loki에서 에러 로그 하나가 검색이 안 됐던 이슈실무에서 알게된 내용 2022. 6. 14. 18:49
1. 문제 상황 : Grafan loki에서 다른 에러 로그는 검색이 잘 되는데, 특정 에러 로그 하나가 검색이 안 됐던 이슈가 있었다. 현상 이유 : loki query에서 정규표현식 오퍼레이터 '=~' 는 줄 바꿈(\n)을 포함하여 전체 문자열과 일치해야 검색이 되는데, 정규 표현식 ' . ' 문자는 기본적으로 줄 바꿈과(\n)이 있으면 일치하지 않는다고 판단한다. 이로 인해, 로그 메시지에 줄 바꿈이 포함된 경우 일치하지 않는다고 판단해서 검색이 안 됐던 이슈였다. 해결 as-is $field=~".*$value.*" to-be $field=~"(?s).*$value.*" 이에 대한 내용은 Grafana Loki 공식 문서에 LogQL의 Log queries 부분을 참고하면 된다. 참고 자료 htt..
-
시스템 별로 Feign Client readTimeout 설정 때문에 내부 동작 코드 분석실무에서 알게된 내용 2022. 6. 14. 17:06
현재 내가 담당하고 있는 서비스는 Feign Client로 OkHttpClient를 사용하고 있었다. feign.okhttp.enabled: true 위 yml 설정 때문에, 아래 코드를 보면 Feign Client로 OkHttpClient를 사용하게 된다. [OkHttpFeignLoadBalancedConfiguration 클래스] 다만, 아래 이미지를 보면 OkHttpClient 가 바로 호출되는 건 아니고 현재 내가 담당하고 있는 서비스에서 사용 중인 sleuth 의존성 때문에 TraceLoadBalancerFeignClient(LoadBalancerFeignClient의 하위 클래스)가 호출돼서 내부에서 LazyTracingFeignClient로 위임, 마지막으로 OkHttpClient로 위임하는..