목록분류 전체보기 (316)
ecsimsw
문제 사항 PICUP은 사용자 사진, 동영상을 저장하고 읽는 스토리지다. 기존 PICUP의 파일 읽기 구조는 아래와 같다. 사용자가 WAS에 자원을 요청하면 WAS 에선 토큰을 확인해 사용자의 자원 액세스 권한을 확인하고 파일 시스템으로 실제 파일을 읽어와 반환한다. 중간 WAS 는 오롯이 권한 확인의 용도일 뿐이었다. 사용자가 파일을 요청할 때마다 WAS 는 같은 파일이라도 매번 Disk I/O 를 사용해 파일을 로드할 것이다. 메모리 캐시를 사용하자니 크기가 큰 동영상이나 이미지 파일을 올리는 데는 적합하지 않아, 근본적인 해결 방법은 안된다고 생각했다. html, js, css 나 FE의 에셋들과 같은 다른 정적 자원처럼, CDN이나 웹 서버의 캐싱을 사용해 파일 요청에 대한 WAS의 부하를 분산하..
0. 배경 PICUP 에서는 WAS 전면에 Nginx 를 두고 TLS, HTTP2.0, RateLimit, 정적 자원 호스팅 등 요청을 전처리하고 있다. 이 Nginx 의 메트릭을 모니터링하려고 한다. WAS 의 응답 시간, 요청 수뿐만 아니라, Nginx가 전면에서 처리하는 응답 시간, 요청 수, 리다이렉트 수가 궁금했다. 1. nginxlog-exporter 처음에는 Nginx가 기본적으로 제공하는 exporter 를 사용했었다. nginxinc/prometheus-exporter 에서 알 수 있듯, 해당 exporter 에서 제공하는 메트릭은 충분하지 않았고, 응답 시간을 포함한 원했던 메트릭은 대부분 Nginx plus 에서만 제공했다. nginx 의 액세스 로그에 응답 시간을 남기는 설정이 있음..
소개 이 글은 PIC-UP 프로젝트에 데이터가 쌓였을 때 조회 성능이 어떻게 되고, 어떤 개선 포인트가 있을지 확인했던 과정을 적어보았다. DB 쿼리 빈도를 줄여 조회 성능을 개선하는 캐싱이나 DB 부하 분산은 다루지 않는다. 대신 데이터를 만드는 방법부터 DB 엔진에 넣는 데 걸리는 시간, 인덱스나 쿼리 수정 고민 과정을 적어볼 생각이다. 다루는 내용은 아래와 같다.<p data-ke-size="size16"..
미리 보기 핸들러의 요청 처리 속도를 제한한다. 아래 핸들러는 0.1초에 한 번으로 처리 속도가 제한되고, 5개까지 보관해 두었다가 속도에 맞춰 처리한다. 10 개의 요청을 동시에 전송했을 때 5개만 처리되고 나머지는 429 (Too Many Requests) 를 응답받는 것을 확인할 수 있다. 그리고 처리되는 5개의 요청은 속도 제한에 따라 0.1초에 하나씩 처리된다. Leaky bucket algorithm 처리 속도를 일정하게 정하여 네트워크 트래픽 체증을 제어한다. bucket 크기를 미리 지정하여 순차적으로 처리하고, 버킷 크기를 넘어선 요청은 버려진다. 즉시 처리 rate는 0.1초, 사이즈는 3 인 버킷에, 5개의 패킷이 동시에 도착하고 0.2초 후에 3개의 패킷이 이어 도착했다고 가정해 보..
대기에 DB Connection 을 점유하는 비관적 락이전 글 에서 프로젝트에서 생긴 동시성 문제가 왜 발생했는지 소개하고 이를 해결할 수 있는 락 종류를 소개했다. 추가적인 인프라와 적은 코드 수정, 그리고 확실한 동시성 문제 처리를 원했기에 비관적 락을 선택했다. 인덱스 조건을 수정하여 사용자별 로우락을 유도해 불필요한 대기를 없앴다. 그리고 얼마 후 DB 락 대기 시간 동안 커넥션을 점유하고 있음을 로그로 확인했다. 사용자 간 독립적으로 락 처리를 했지만, 한 사용자가 락으로 모든 커넥션을 물고 있으면 결국 락이 걸린 로우와 독립적인 다른 사용자는 그 사용자를 대기해야 했다. 이 글에서는 동시성 문제를 해결하기 위해 여러 락 방식을 적용하면서 발생했던 에러 사항들과 해결 과정을 소개한다. 목..
미리 보기 컨트롤러에 @ShutDown 어노테이션을 추가하고 임시 응답을 어떻게 전달할지를 지정해주는 것으로 ShutDown 조건에서 해당 컨트롤러 아래 모든 핸들러의 임시 응답을 자동으로 생성해 준다. 위 예시에서 DailyCountRepository 타입의 빈이 존재하지 않으면 /api/counts 를 GET 요청하는 경우 아래와 같이 응답한다. HTTP status : 503, SERVICE_UNAVAILABLE Content type : application/json Message : This API is currently unavailable. 아래 사용 방법이나 버전, 기능은 현재 글을 쓰는 첫 배포 시점을 기준으로 한다. 최신 변경 사항은 https://github.com/ecsimsw/ap..
Mysql InnoDB 의 RepeatableRead Mysql 의 기본 Transaction isolate 수준은 RepeatableRead 이다. RepeatableRead 는 트랜잭션이 시작된 시점 이후로 여러 번 Select Row 를 확인해도 동일한 값을 갖는다는 것이다. Mysql 은 SnapShot을 사용해서 이를 보장한다. 트랜잭션마다 별도의 스냅샷을 기록하여 다른 트랜잭션이 값을 변경하고 Commit 해도 이 스냅샷을 이용해서 동일한 값을 읽게 되는 것이다. Phantom read 문제 Repeatable Read 는 데이터의 추가, 삭제의 변경은 막지 못해 Phantom read 문제가 발생한다. 한 트랜잭션 내에서 전과 다른 조회 결과 row 수를 조회하게 된다는 것이다. InnoDB..
기존의 문제점PicUp 프로젝트에선 서비스 간 통신 방법으로 메시징을 이용한다. 서비스 간 처리가 필요할 때 이벤트를 발행, 메시지 큐에 담아두고 처리를 맡는 다른 서비스에서 이를 리스닝하여 처리한다. 픽업 프로젝트에선 앨범 삭제 기능이 좋은 예시이다. 사용자가 앨범을 삭제할 때 관련 사진 파일들을 전부 삭제하는 처리 시간까지 사용자 요청 주기에 포함해선 안되므로 요청 주기 내에선 DB 데이터만 삭제하고 이 이벤트를 메시지 큐에 담았다가 비동기로 파일을 삭제하게 된다. 문제는 메시징과 DB 트랜잭션이 다른 원자성을 갖는다는 것이다. 원자성은 한 작업의 단위 내에서 세부 작업들은 모두 성공하거나 모두 실패해야 함을 말한다. 메시징과 DB 트랜잭션은 원자성이 보장되지 않기 때문에 ..