드루팔, nginx, fastcgi

드루팔을 운영하시는 분의 요청으로 서버를 들여다보았다. 트래픽이 조금만 들어오면 다운되는 상황이라고 하셨슴.

나쁜 모듈 찾기

우선 플러그인 모듈중에 유명하지 않거나 검증되지 않은 녀석들이 있는지 확인했다. 복잡한 모듈들 때문에 사이트가 다운되는 것이 아닐까 예상했는데, 의외로 로그인 박스에 문제가 있었다.

메인페이지에 로그인 박스가 있었고, 거기에 captcha기능을 달아두셨는데, 이 녀석 내부에 문제가 있는지 CPU를 엄청나게 쓰고 있었다.

로그인 페이지를 따로 만들고 그쪽에 넣도록 했다. 메인페이지가 5초가량 걸리던 것을 1초이내 응답하도록 하는데 성공했다.

서버 구성

한대의 서버에서 아파치와 MySQL이 동작 중이었다. 확장을 위해 데이터베이스 서버와 웹 서버를 분리했다.

테이블들은 myisam으로 되어있던 것을 innodb로 모두 바꿨다. 드루팔을 기본으로 설치하면 모두 myisam으로 해버리는 듯하다. (innodb를 위해 튜닝을 해서 그렇겠지만… 훨씬 빨라짐)

Cloudflare 의 CDN을 연결했다. CDN에서 굉장히 많은 트래픽을 처리했다고 그래프를 그려주시는데, 정말인지는 모르겠지만, 월 2만원에 이런 저런 서비스를 해주니 고마울 따름.

아파치는 nginx 와 php5-fpm 으로 바꿨고, memcached 를 설치하고 드루팔 캐시에 연결하니 속도가 엄청나게 빨라짐. (memcache 에는 4기가 까지 줘봤지만, 사실 2기가 정도면 넘치겠지..)

  • php5-apc : opcache.enable=1 도 해주었다.

  • mysql 설정 - 이렇게 무식한 설정을 써보게 되다니.. (gist 참고)

  • varnish와 함께 쓰는 것까지 시도했지만, 그렇게는 잘 안되었다.

  • fast-cgi 를 캐시하는 방법이 있는데, 이건 그야말로 최고있다. 하지만, 관리자 화면을 캐시에 넣어버리는 단점이있고, 캐시에 들어가지 않도록 하려면, 의뢰인에게 세심한 주의가 필요했기 때문에 포기했다.

숫자 찾기

이제 숫자를 찾아내야 했다. 내가 만든 서비스라면 어디가 문제인지 알수 있을 텐데, 이 상황에서는 php5-fpm 과 nginx의 숫자를 조금씩 바꿔보는 것만이 내게 남은 유일한 튜닝이었다.

대상이 된 기계의 스펙은 16core, 16g mem 의 가상서버 2대. 클러스터를 만들고 앞단에는 ucloud 의 LB를 연결했다. haproxy까지는 하지 않았다.

이 상태에서 ab 테스트를 반복해보니 천명정도까지 무리없이 받을 수 있을 것 같았다. 하지만 실제 트래픽이 몰리면 300명이 넘는 순간 다운.

load impact

http://loadimpact.com에 돈을 내고 실 사용자랑 비슷한 트래픽을 만들어달라고 해보았다.

해보니… 실사용자가 300명 이상 접속하면 메모리가 꽉차고, cpu가 버벅거리더니 뻗어버리고 있었다. 딱맞는 숫자를 찾아서 한땀 한땀 나아갔다.

최대한 접속 가능한 클라이언트의 숫자를 높이다보면 안정성이 떨어지는 경향이 있다. 안정적 응답을 최우선으로 하고, 잘 안될것 같으면, ‘다음에 접속해 주세요’라고 빠르게 안내하는게 속편할 듯.

어쨌든 그래서 gist 에 올려놓은 현재의 설정은 1300명까지는 거의 완벽하게 수용하는 설정이다. (분명 아직도 더 수용할 수 있는데… 아직 못찾겠다…)

혹시나 fastcgi 로 php를 쓰시는 분이 계시면 도움되시길. 그리고, 더 좋은 설정을 찾으신 분이 계시면 공유도 부탁드려요.

추가 튜닝

조금 더 작업을 해서 현재 상태는 1900명까지 밀리초단위의 응답을 보인다.

GIST 링크 https://gist.github.com/jinto/1acb06abe74fad3f4ba5


seong jin : 혹시 위 설정에서 변경된 것 있는지 알수 있나여? 많이 도움을 얻긴 했는데 좀 여쭤 볼것들이 있는데..보시게 되면 답변좀 부탁드릴게요 (2016-06-02 23:50:50)

jinto : 어떤 도움을 드릴 수 있을까요? (2016-06-06 18:10:23) > seong jin : max_execution_time = 120인데 request_terminate_timeout 이 설정 하신것은 안보여서요. 구글링하면 같이 설정 하라고 나와서 여쭤봅니다. 동접수가 폭주할때, recv() failed (104: Connection reset by peer) 오류가뜨면서 느려지는 현상이 발생하는데 서버의 자원은 남아 돌거든요, 구글링하면 많은 게시물에서는 … (2016-06-15 11:55:24)

fastcgi_buffering               on;
fastcgi_buffer_size             16k;
fastcgi_buffers                 16 16k;
fastcgi_connect_timeout         600s;
fastcgi_send_timeout            600s;
fastcgi_read_timeout            600s; 
이렇게 컨피그를 삽입하면 된다고 하는데 전혀 나아지지 않아서요
 
세팅은 위 내용과 비슷한데
저 같은 경우 
pm.max_children = 1024
pm.start_servers = 512
pm.min_spare_servers = 512
pm.max_spare_servers = 1024
pm.max_requests = 9000 (php.ini의 max_execution_time = 30 디폴트 사용중 )
request_terminate_timeout = 100 으로 하다가 변경하면서 테스트 중입니다. 현재는

pm.max_children = 2048 
pm.start_servers = 1024
pm.min_spare_servers = 1024
pm.max_spare_servers = 2048
pm.max_requests = 9000

이렇게 상향조절 하니까 동접이 폭주할때도 서버의 자원이 남아돌던것이 2배정도 소모가 되면서, 조금은 더 동접을 받더라구여. 현재 위 설정으로 얼만큼의 동접을 받는지 궁금합니다.

jinto : 어떤 설정에서 동접이 얼마라고 말씀드리기는 힘든 일인 듯합니다. 설치하신 모듈이나, 서버 성능에 따라 달라지겠지요. 최적의 설정이 무엇인지. 숫자들을 조정하시면서 찾아가시면 될듯합니다. 저는 loadimpact 서비스가 원하는 동접을 시뮬레이션 하는데 도움이 되었습니다. 의견드리자면.. (2016-06-15 14:20:59)

1. 일단 동접얼마를 원하시는지 정하시고, loadimpact 따위로 시뮬레이션 하시고.
2. 데이터베이스 서버를 분리하시고, 순수하게 드루팔만 올라가있는 상태에서 디비서버와 드루팔서버의 CPU등을 모니터링 하면서
3. 숫자를 조정해서 원하는 속도나 접속을 이루는지 확인하시면 어떨까요.

그리고, 별로 하는 일도 없는데 CPU를 너무 많이 먹길래, 기본 모듈만 설치한 상황부터 시작해서 하나씩 사용하는 모듈들을 추가해가면서 문제를 일으키는 모듈을 찾아내서 없애는 식으로 최적화를 하기도 했었습니다. 기능이 좋아보여서 설치했지만, 알고보니 모듈을 엉망으로 짜서 서버에 부하를 주는 녀석들이 종종있습니다.

성공하시길 바랍니다.

seong jin : 답변 남겨 주셔서 감사드려요 웹서버와 DB는 분리 되어 있고, 마스터 슬레이브 구조의 Mysql 리플리케이션을 사용하는 구조예요 클라우드 사용하는것도 거의 비슷하고, 전체적인 설정이 많이 비슷하여 여쭤봤던건데..그렇죠 어떻게 설정을 하였을때 MaxClient, TPS 등이 나오더라 라는것은 사이트 마다, 서비스마다 다르기에 딱 집어서 말하기 어려운 부분이 있죠.. 일단 리눅스의 FD, 커널 TCP/IP 파라미터 튜닝, Nginx와 FPM의 설정 조정, Mysql의 맥스커넥션, TimeWait, InnoDB 버퍼 이정도를 설정 변경해 가면서 작업 중이예요 loadimpact 한번 찾아 보겠습니당. 감사드려요~ (2016-06-20 09:55:33)