목록 전체 글 (295)
배경WAS 전면에 Nginx 를 두고 TLS, HTTP2.0, RateLimit, 정적 자원 호스팅 등 요청을 전처리하고 있다. 이 Nginx 의 메트릭을 모니터링하려고 한다. WAS 의 응답 시간, 요청 수뿐만 아니라, Nginx가 전면에서 처리하는 응답 시간, 요청 수, 리다이렉트 수가 궁금했다. nginxlog-exporter처음에는 Nginx가 기본적으로 제공하는 exporter 를 사용했었다. nginxinc/prometheus-exporter 에서 알 수 있듯, 해당 exporter 에서 제공하는 메트릭은 충분하지 않았고, 응답 시간을 포함한 원했던 메트릭은 대부분 Nginx plus 에서만 제공했다. nginx 의 액세스 로그에 응답 시간을 남기는 설정이 있음을 미리 알고 있었다. 그래서 ..
소개 DB에 데이터가 쌓였을 때 조회 성능과 개선 포인트를 확인했다. DB 쿼리 빈도를 줄여 조회 성능을 개선하는 캐싱이나 DB 부하 분산은 다루지 않는다. 대신 데이터를 만드는 방법부터 DB 엔진에 넣는 데 걸리는 시간, 인덱스나 쿼리 수정 고민 과정을 적어볼 생각이다. 튜닝 키워드는 아래와 같다. 1. 더미 데이터를 추가하고 쿼리 조회 성능을 확인한다.2. 인덱스/커버링 인덱스를 적용한다.3. 실행 계획으로 인덱스 튜닝 결과를 확인한다.4. OFFSET 기반 페이지네이션의 문제를 확인하고 개선한다. 천만 개 더미데이터 삽입테스트 환경으로 1000명 유저, 각 유저는 20개의 앨범을 소유, 각 앨범에는 500개의 사진 정보를 가정한다. 총 천개의 Member 데이터, 2만 개의 Album 데이터, 천만..
배경사용자로부터 이미지를 수신, 이를 3D 변환 애플리케이션에서 읽을 수 있도록 이미지를 전달하는 API 서비스를 운영하고 있다.처음 이 서비스는 특정 고객사 내부망에 납품된 형태로 시작했다. 폐쇄된 환경이다 보니 디스크 저장 밖에 선택지가 없었고, 외부 접근을 걱정할 일도 없었으니 별도 보안도 신경 쓰지 않았던 것 같다.팀의 목표는 이 서비스를 살려 SaaS로 전환, 클라우드에 배포하고 외부 사용자가 접근할 수 있도록 하는 것이었다. 파일 저장소가 S3로 바뀌었고, 보안을 신경 써야 했다.사용자의 사용 패턴을 명확하게 알고 있던 기존보다, 더 다양한 사용 케이스와 이에 따른 사용성을 고민해야 했다. 여러 개선 포인트가 있었고, 나는 그중에서도 이미지 업로드, 파일 관리 서비스를 메인으로 담당했다.이 글..
두 번의 갱신 분실 문제 발생유저가 파일을 업로드하면 사용 가능 공간을 확인하고 현재 사용 중인 공간을 업데이트한다. 업로드 동시 요청이 발생하는 경우, 마지막에 수행되는 커밋의 결과만 반영되어 의도하지 않은 값이 저장된다. 이렇게 여러 트랜잭션에서 동일한 데이터를 동시에 수정하려할 때, 마지막으로 수행한 수정만 반영되는 경우를 두 번의 갱신 분실 문제라고 한다.# 두개의 스레드에서, 동시에 5MB 파일을 업로드할 때Thread 1 - 현재 스토리지 사용량 조회 0MBThread 2 - 현재 스토리지 사용량 조회 0MBThread 1 - 스토리지 사용량 기록 5MBThread 2 - 스토리지 사용량 기록 5MB 낙관적 락낙관적 락은 조회와 수정에 버전을 함께 확인하여 충돌 여부를 파악한다. 엔티티 버전을..
Mysql InnoDB 의 RepeatableRead Mysql 의 기본 Transaction isolate 수준은 RepeatableRead 이다. RepeatableRead 는 트랜잭션이 시작된 시점 이후로 여러 번 Select Row 를 확인해도 동일한 값을 갖는다는 것이다. Mysql 은 SnapShot을 사용해서 이를 보장한다. 트랜잭션마다 별도의 스냅샷을 기록하여 다른 트랜잭션이 값을 변경하고 Commit 해도 이 스냅샷을 이용해서 동일한 값을 읽게 되는 것이다. Phantom read 문제Repeatable Read 는 데이터의 추가, 삭제의 변경은 막지 못해 Phantom read 문제가 발생한다. 한 트랜잭션 내에서 전과 다른 조회 결과 row 수를 조회하게 된다는 것이다. InnoDB..
GC와 Stop the world JVM의 가비지컬렉터는 힙 영역의 메모리에서 더 이상 사용되지 않는 자원을 정리하는 역할을 한다. 이때 사용되지 않는다란 다른 지역 변수, static 변수, 파라미터, JNI의 객체, 다른 힙 영역의 객체 등에서 더 이상 참조되지 않는 것을 말한다. 아래 그림에서 빨간색으로 표시된 Unreachable objects는 GC의 대상이 된다. 이때 자원을 정리하는 과정에서 새로운 객체가 할당되거나 객체 간 연결이 생길 경우를 방지하기 위해, GC를 위한 스레드를 제외한 모든 스레드의 작업이 중단된다. 이런 GC를 위한 애플리케이션 전체 중단 시간을 Stop the world라고 한다. ( 보다 자세한 STW가 필요한 이유 ) 두가지 GC와 처리 영역들 Stop the wo..
0. AS IS 기존에는 이 메인 / 백업 스토리지 업로드를 동기로 처리했다. 400KB의 이미지를 업로드할 때 main 33ms, backup 1680ms 정도가 필요했고, 사용자 응답은 이 둘을 더한 값 + ⍺ 가 될 것이다. 이미지 업로드 시에 각 스토리지 업로드를 비동기로 처리하되 모든 업로드가 정상일 경우에만 사용자에게 정상으로 응답하고자 한다. 그리고 동시에 비동기식 업로드 과정에서 생길 수 있는 더미 파일을 사용자 흐름에 포함하지 않고 처리하고자 한다. 이 글에선 위 요구 사항을 만족하기 위한 작업 과정을 소개한다. 목차는 다음과 같다. 1. 단순 비동기 처리 2. Future로 비동기 / 블록킹 방식으로 처리하는 경우, 그 문제점 3. CompletableFuture으로 쉽게 구현하는 다양..
Mysql db replication DB를 백업하기 위해서 replication 을 사용한다. 백업을 위함도 클 것이고, 쿼리 부하 분산, 지역화의 이점도 얻을 수 있을 것이다. 이 글에선 아래 네가지 키워드를 다룬다. - Mysql이 제공하는 Replication 방식과 각 장단점- 비동기 복제의 정합성 문제- Spring boot에서 읽기와 쓰기 Datasource 분기하기 복제 종류 Mysql 의 복제 방식은 '동기', '비동기', '반동기'가 대표적이다. 동기 방식은 한 노드에 요청된 쿼리를 트랜잭션 내에서 다른 노드들에 전달하고 모든 노드들이 동기화되면 트랜잭션의 결과를 반환한다. 마스터(또는 첫 요청을 받은 노드)가 다른 노드들에 쿼리를 전달하는 식으로 진행된다. 모든 노드에서 동일한 요청..