크라슐라

다모앙 하면서 겪은 대용량 트래픽 튜닝이야기

지금은 유지보수 등으로 그누 5 에서 고랭으로 바꾼 모사이트 이야기입니다.
그누보드 가져가서 쓰기만하고 튜닝이야기가 딱히 공유되지않는다는 어느분의 말씀도 생각나서 적어봐요.
그런의미에서 그누7을 기다리며 써봅니다.

그누보드 5 + 나리야 빌더였습니다.
동접 몇천되는데 튜닝해서 버텼어요.

파트1. DB 측면
1. 새 글 보기는 테이블부터 문제더군요
그 사이트에는 게시판이 100 여개가 넘어요. 그래서 유니온 쿼리로 가져오는 부분이 큰 문제가 되었고 레디스 캐시가 추가되었습니다.

2. 메인도 latest 함수가 여러개 있으면 n+1 쿼리 문제가 생깁니다. 마찬가지로 레디스 캐시적용.
3. 방문자, 현재접속자 이거 사용자가 많으니까 DB부하가 너무커서 삭제하고 구글 애널리틱스로만 봅니다.
4. 각종 n+1 쿼리들... 죄다 없애는데 집중했습니다 조인으로 통합하거나 클래스로 메모리 캐시뒀죠. orm 같으면 lazy 로딩에서 eagar 로 바꾸는 부분이죠.

수정한 예시로는 게시글 목록을 보면 사이드바에서 멤버정보를 가져오니까 get_member 함수가 게시물만큼 호출되니.. n+1 이죠
다들 모여서 수정했어요.

n+1 쿼리문제는 코드로 찾기는 힘들어서 그누보드 디버그바에 중복쿼리 표시기능을 추가하고 수시로 보일때마다 없앴네요.
나중에는 phpstan 플러그인 만들어서 찾고 수정했어요.

5. 포인트, unique 데드락.
4년전인가 5년전? 모던 php  오프라인 모임이 살아있을 때였습니다.
참석자중 한 분이 영카드에 상품이 많아지면 느려지고 데드락이 발생한다는 거예요?.. 

그때는 잘몰랐죠. 이거 참여하면서 보니까 정말 데드락이 발생하더라구요.
아시다시피 그누5 까지는 myIsam 을 지원하느라 트랜젝션이 없습니다.
get_unique 함수는 테이블 단위 락을 거는데 이게 게시글 적을때,  주문번호마다 호출되는데요

저희 사이트는 이용자가 되게많으니까 글쓰는 사람도 많고 테이블이 수시로 락걸려가지고... row 단위로 락을 걸수있는
DB 트렌젝션으로 코드를 변경했습니다.
여기서 일단락 되는듯 했으나...

포인트에 데드락발생.
포인트는 댓글 작성/삭제, 게시글 작성/삭제, 열람 등 더 많이 관여하죠
php 로그쪽에 마구 발생하고 난리..

그누보드 포인트 계산을 잘보면 get_sum 함수를 호출하는데요 포인트를 그때마다 다 합쳐서 계산합니다.
일단은 포인트 함수들 전면 조정했습니다. insert_point 함수에 트랜젝션을 추가하고
업데이트 쿼리 순서를 조정해서 데드락을 피했습니다. ㅠ

근데 이건 근본적으로는 부하문제고... 이거 개선하려면 복식부기 방식의 테이블로 변경해야합니다.
쉽게 말하면 모든게 기록된 장부 테이블 , 유효기간이 남아 사용할 수있는 포인트 테이블, 현재 포인트 이렇게 나뉘어야합니다.
그러면 나중에 대조하기도 쉽고 포인트 로직이 간단해져요.

6. 각종 인덱스 재설계
그누보드 기본은 인덱스가 잘없어요. 이건 팁게시판에도 적혀있고 골수(?) 유저들은 알고있죠
DBA 분들이 많이 도와주셨고요. 그외에도 DB 부하보면서 쿼리 인덱스 재설정... 되었어요.

7. 검색 부하.
게시판 like 검색인데다가 통합검색하려니 유니온 쿼리... 검색부하가 너무 커서 스핑크스 검색엔진 붙여놨어요.
근데 스핑크스는 기본방식도 cpu 부하가 너무커서 델타인덱싱으로 교체했어요.

8. 게시글 수정일이 컬럼이 없음.
문제: 게시판 테이블 wr_last 는 댓글이 달리면 바뀝니다.
그래서 스핑크스 등 검색엔진의 델타인덱싱을 할수가 없어요 그래서 수정일 컬럼부터 추가 했어요.

9. 진짜 댓글이랑 게시판 테이블 분리... 이건 아직하지 않았지만요 중요해요. 부하가 ㅠ
그누 7관련 댓글에도 요청사항이던데요.
그외 성능과 관련없지만 . 0000 날짜. 이거 좀 없애야해요.

파트2. 코드 측면

램과 cpu ... 클라우드에서는 곧 비용입니다. 한푼이 아쉽고... xdebug 프로파일러를 눈빠지게 보면서 아끼려고 애썼죠.

1. htmlpurifier 호출될때마다 새로운 객체가 호출되서 10MB 가까운 램을 사용합니다.
php fpm 에 pm.maxchildern 갯수만큼 사용하니까 100여개를 띄우면 10 x 100 MB =  1GiB 죠

함수내부에 static 을 둬서 객체 생성을 한번만 하게 변경.
3mb 로 줄였습니다 700 mb 세이브.

2. 캐시 인터페이스

그누보드 훅에서 상당수는 캐시에 관한것입니다.
기본은 파일 캐시만 있고 파일 i/o 는 메모리보다 느리죠.

캐시로 레디스 훅을 붙였는데 프로파일링 하니까 이부분도 5% 의 cpu 를 차지하길래 인터페이스로 바꿨습니다.
모든 캐시훅을 일반 함수로 바꿨네요.

4. 관련해서 세션도 php.ini 을 통해 레디스에 저장하도록 교체
5. s3 
데이터 트레픽 비용을 줄여야 살아남습니다.
처음에는 게시판의 s3 플러그인을 붙였습니다

문제발생:
 1 나리야쪽이 커버가 안되고 커스텀한쪽에 새 훅을 추가했죠
 2. 회원목록에서 없는 멤버프로필은 파일 i/o 가 발생하니까 그냥 404 응답되게 했어요.
 문제는 404 페이지가 따로있었고 이게 다 새로운 데이터 트래픽이라는거죠.
 

 다른 개발자가 왜 그렇게 이상하게 만드냐

라고 하더라구요.

그래서 바꿨어요.
이건 회원테이블에 멤버 프로필이 존재여부를 저장하는 컬럼, 멤버프로필 변경일 컬럼 2개를 추가해서 출력할때 바로 구분하게했죠

파트3. 보안 측면

1. 그누보드5는 sql 인젝션 위험성이 있는데요 mysqli_real_escape 는 우회로가 있습니다 주로 큰따옴표, 작은따옴표 관련 조합으로 가능하다고하죠.
그래서 sql_ 접두사의 그누보드 함수들을 PDO 로 모두 교체하고 PDO quote 를 사용하게 했어요. 이 함수는 우회할 수 가 없다고 그러더군요.

그래도 혹시나해서 몇몇 중요한곳들은 pstmt 로 바인딩 쿼리로 변경했고 시간이 많이 걸렸습니다.
아무래도 실명인증 서비스를 이용하다보니 해킹이 너무 겁났죠.

나중에는 sql_query 내부에 문자열들어온거 null 바이트 문자열 필터링도 추가했습니다.


xss 는 나리야쪽 주로 수정해서 그누5 쪽은 별 상관없었어요.
---

근데 결국 고랭으로 교체 되었습니다.
왜냐면 mvc 가 아닌탓에 유지보수가 힘들었어요. (이거 대다수의 그누보드 썼던 스타트업이 레거시라면서 php 버리는 이유)
php 에서 왜 다른거로 바꾸냐? 기술블로그나 그 쪽 사람들 질문하면 거의 저거 던데요. 
그 중에는 리엑트 써야된다는 이유도 있었구요

나리야빌더가 그누보드 우회해서 새롭게 만들어낸 파일들도 엉망이였구요
뭐 좀 추가하려면 영향받는게 되게 많았고요 테스트도 e2e 만되서 힘들고...
ai 도 토큰이 너무 커져서... 잘 안돌았구요. 여튼 그누 7을 기대합니다.

라라벨 같은 멀쩡한 프레임워크 쓴다고 하니까 코드쪽은 문제가 상당수 해결되겠죠.
DB 는 포인트 테이블 좀... 다시 생각해주셨음해요.


블로그에 축약해서 적은거 풀어서 적었어요.
관련 코드

https://varietn.tistory.com/entry/%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C%EC%9D%98-%EC%84%B1%EB%8A%A5-%EC%9D%B4%EC%8A%88-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0
6명이 반응했습니다
|

댓글 4개

대단히 어려운 작업일텐데 대단하시네요.

고랭 선택하신 이유가 있으신가요.
전 자사 사이트가 그누4로 된 아주 오래된 사이트라서 고랭으로 바꾸던 중 3만 loc 정도 코딩 했을 때 패턴부터 msa로 해서 관리포인트 너관리포인트 늘어나고 런타임 에러 잡는데 시간도 많이 걸려서 컴파일 되면 대부분 잘돌아간다는 러스트로 바꿔서 지금도 작업중이거든요.   아예 디비 구조까지 바꿨습니다.  두달정도 안에 완료할 예정인데 작업하시는데 얼마나 걸리셨나요?

저도 대량의 자료 검색시 느려지는 문제와 슬로우 쿼리 때문에 골머리를 앓다가. 요즘 디비테이블 파티셔닝에 대해 알아보고 있습니다.

테이블을 쪼개자니...전체검색시 일이 번거로워 지고...하여간 고생하신 흔적이 보이네요. 고생하셨습니다.

궁금한점이,
db 는 여전히 mariadb 쓰나요?
postgres 를 쓰면 검색부터 벡터(자연어 쿼리) 까지 되는데, golang 으로 작업하다면 이게 더 좋은 선택 같네요.

저는 요즘에 db 를 의도적으로 postgres 를 쓸려고 합니다. 인공지능 시대에는 dbms 도 인공지능에 친화적인걸 쓰는게 여러모로 잇점이 많겠더라구요.

 
아직은 mysql 씁니다
댓글을 작성하시려면 로그인이 필요합니다.

자유게시판

+
제목 글쓴이 날짜 조회
22시간 전 조회 113
어제 조회 102
어제 조회 172
어제 조회 104
어제 조회 218
어제 조회 161
어제 조회 207
2일 전 조회 112
2일 전 조회 145
2일 전 조회 127
2일 전 조회 129
2일 전 조회 120
2일 전 조회 92
2일 전 조회 83
2일 전 조회 228
2일 전 조회 206
2일 전 조회 137
2일 전 조회 78
2일 전 조회 88
2일 전 조회 68
2일 전 조회 95
2일 전 조회 81
2일 전 조회 67
3일 전 조회 90
3일 전 조회 141
3일 전 조회 80
3일 전 조회 90
3일 전 조회 85
3일 전 조회 101
3일 전 조회 90