본문 바로가기

전체 글

(156)
JVM 메모리 누수 트러블슈팅 (Native memory leak) 현재 팀에서는 예전부터 꾸준히 서버의 메모리 사용량이 우상향하는 현상이 있었다.우리는 java application의 서버를 운용중이고, 거대한 모놀리스 시스템으로 많은 트래픽과 동시에 많은 데이터를 처리하고 있다. 서버를 물리장비에서 컨테이너로 전환한 뒤에, 모니터링하면서 메모리 사용량이 지속적으로 증가하는 것을 알 수 있었다.JVM의 Max Heap은 컨테이너의 50% 수준으로 설정해놓았고, 그 외 Metaspace, native memory, cache 등의 용량을 생각해봐도 이해할 수 없는 수치로 계속해서 올라갔고, 어디선가 메모리 누수가 발생하고 있음이 분명했다. # Heap & Metaspace 영역 체크사실 Java 개발자는 직접적으로 작업해서 관여할 수 있는 메모리 영역이 주로 JVM he..
도메인(Domain) 관점 모듈 분리 (With. DDD, MSA) 시스템이 점점 거대해지면서, 우리 팀 또한 공통 모듈의 저주에 빠지고 말았다. (공통 모듈의 저주? https://techblog.woowahan.com/2637/) 거대한 하나의 모듈을 분리할 필요성을 느꼈고, 그 과정에서 논의하며 정리했던 내용들을 기록해둔다. (도메인과 관련된 글이나 자료는 많았지만, 대부분 추상적이고 실효성이 있는 자료를 찾지 못했다..) 도메인은 무엇일까? 도메인이란 단어 뜻 자체는 영토, 분야, 영역, 범위 등의 의미를 가진다. 인터넷 주소의 의미로도 사용된다. 다만, MSA와 DDD에서 흔히 사용하는 도메인의 단어는 [영역]의 의미를 가진다고 볼 수 있다. Domain이라고 하면, DDD에 대한 얘기를 하려고 하는걸까? 라는 인식이 있어서 꺼려진다. 하지만, DDD 개발방법론..
Distributed transaction (분산트랙잭션) (with. Saga pattern) 예전부터 MSA는 많이 듣고 이론으로 많이 접해봤지만, MSA가 완벽히 적용되서 운용되는 서비스를 직접 경험해보지 못했다. 실 운용 서비스에서 연관관계가 높은 서비스들을 어떻게 도메인을 분리하고 통신하고 연동하고 있을지 궁금하다. 대부분 내가 경험해봤던건 모놀리틱 서비스에서 MSA로 넘어가는 과정들이였다. 그 과정 속에서 직접적으로 와닿았던 문제는 크게 다음과 같은 2가지 문제였다. 1. 네트워크 통신 비용 - MSA가 되면 기존과 다르게, 수많이 흩어진 서비스로부터 데이터를 가져와야한다. 어떻게 풀어낼 수 있을까? CQRS? 2. 분산트랜잭션 해당 포스트에선 두번째 문제 분산트랜잭션에 대해서만 다루고, 이를 해결하기 위한 방법을 정리해본다. # 분산 트랜잭션 모든 아키텍쳐가 그렇듯 MSA에도 단점은 존..
[Kubernetes] JVM Heap 메모리 모니터링 (With. Visual VM, jstat) JVM 힙 메모리를 모니터링 해야할 일이 생겼다. 로컬이나 물리장비에 떠있는 서버를 Visual VM 연동을 통해 모니터링 해본 경험은 있지만, Kubernets 환경에서의 Visual VM 연동은 낯설었다. # Visual VM ? - https://visualvm.github.io/ VisualVM: Home News: July 19, 2022: VisualVM 2.1.4 Released This release introduces several heapviewer improvements. From now, VisualVM is available as an optional GraalVM component. See the Release Notes for all changes. The tool can be..
[Spring] Guava RateLimiter 사용법 (spring throttling) Spring에서 throttling을 하기 위해 Guava의 RateLimiter가 주로 사용된다. 사용법과 예제를 정리해본다. Guava Rate Limiter Rate Limiter는 초당 실행횟수를 제어해서 throttling을 도와주는 클래스이다. 라이브러리 추가 dependencies { implementation("com.google.guava:guava:31.1-jre") } 1초에 한번 실행 describe("1초에 1번 실행") { val rateLimiter = RateLimiter.create(1.0) // RateLimiter 생성 repeat(10) { val startTime = ZonedDateTime.now().second rateLimiter.acquire() // = ra..
[Spring] 외부 API 호출 서비스 테스트코드 작성하기 (WebClient & MockWebServer) Spring에서는 API를 호출할 수 있는 많은 REST Client를 제공한다. 그 중에서도 WebClient가 가장 많이 추천되는 편이다. Spring 팀에서도 RestTemplate의 대안으로 WebClient를 추천하고 있고, Reactive 환경과 MSA를 생각하고 있다면, WebClient는 좋은 대안이 될 것이다. 그럼 이러한 WebClient로 작성한 서비스는 어떻게 테스트 코드를 작성할 수 있을까? 두가지 방법이 존재한다. Mockito를 사용하는 방법 실제 WebClient를 사용하고, MockWebServer를 호출하는 방법 Mockito를 이용해 일일히 stubbing하는 방법도 있지만, 이 방법은 너무 번거롭고 복잡하다. 또한, 테스트하려는 서비스가 WebClient 동작방식에 대..
Spring boot Dockerfile 최적화하기 (spring boot dockerfile best practice) Spring Boot Dockerfile 간단하게 스프링 어플리케이션을 도커파일로 작성하면 아래와 같다. FROM openjdk:11 ARG JAR_FILE=build/libs/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080/tcp ENTRYPOINT ["java","-jar","/app.jar"] Spring Boot의 빌드 결과는 바로 실행 가능한 하나의 jar 파일로 나오기 때문에, 단순히 jar 파일을 옮겨주고 실행 시켜주는 것만으로 Dockerfile 작성이 끝난다. 하지만, 여기서 Dockerfile을 하나씩 최적화 시켜보자. .dockerignore 작성 Docker 이미지 생성 시 필요없는 파일은 최대한 제거해준다. 특히 Dockerfile의 경우 은근히 사이즈..
Docker란? (Docker의 기본개념) Docker 도커는 컨테이너를 이미지 파일로 빌드하고 배포하여 어디서나 실행할 수 있도록 해주는 오픈소스이다. 사실 상 컨테이너는 리눅스의 기술이고 도커가 없어도 컨테이너를 구현할 수 있다. 하지만 도커를 이용하면 여러 장점이나 옵션들을 사용할 수 있다. 컨테이너를 git에 저장된 소스처럼 build/push/pull 할 수 있는 방법을 먼저 제공하면서 주목받았다. Docker 설치 (https://www.docker.com/get-started) 그렇다면 위에서 말한 컨테이너(container)는 무엇일까? Container 컨테이너 단위로 OS, 라이브러리, 어플리케이션을 하나로 패키징 할 수 있다. 하나의 OS 위에 여러 어플리케이션을 독립적으로 실행할 수 있도록 한다. 여러 어플리케이션의 격리된 ..