질문/조언질답게시판
Extra Form
PHP PHP 7.0
CMS GnuBoard

클라우드플레어 무료 플랜을 사용중입니다.

서버는 단독서버이며 우분투18.04 nginx php7.0 innodb 가 돌아가고 있습니다.

서버상에 사이트가 4개가 돌아가며 4개의 전체접속자는 일방문 5만이 안되는 유머사이트들입니다.

며칠전 매월 서버비용을 감당할 수 없어 사이트를 서버 하나로 모두 모아 이전하였습니다.

오늘 오후부터 사이트 접속을 하니 nginx 500에러와 클라우드플레어 502 bad gateway가 뜨면서 에러가 나네요.

 

nginx 에러로그는 아래처럼 초당 로그를 찍어내고

24: Too many open files 관련하여 해결법들을

https://www.cyberciti.biz/faq/linux-unix-nginx-too-many-open-files/

위 처럼 적용해도 해결이 되지 않습니다.

2020/01/08 17:16:25 [crit] 2297#2297: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2302#2302: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2299#2299: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2305#2305: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2303#2303: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2304#2304: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2301#2301: accept4() failed (24: Too many open files)
2020/01/08 17:16:25 [crit] 2300#2300: accept4() failed (24: Too many open files)
2020/01/08 17:16:28 [crit] 2300#2300: accept4() failed (24: Too many open files)
2020/01/08 17:16:28 [crit] 2301#2301: accept4() failed (24: Too many open files)
2020/01/08 17:16:29 [crit] 2304#2304: accept4() failed (24: Too many open files)

 

그래서 혹시나 해서 가장 접속자가 많은 사이트를

클라우드플레어쪽에 디도스방어기능으로 5초이후 접속하는 기능을 온 했더니

다른곳 다 사이트 접속과 글읽기등이 문제없이 되네요.

 

php7.0-fpm.log 로그입니다.

[08-Jan-2020 17:24:59] WARNING: [pool tab10] server reached pm.max_children setting (50), consider raising it
[08-Jan-2020 17:26:59] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 42 total children
[08-Jan-2020 17:27:00] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 47 total children
[08-Jan-2020 17:27:01] WARNING: [pool tab10] server reached pm.max_children setting (50), consider raising it
[08-Jan-2020 17:27:46] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 42 total children
[08-Jan-2020 17:27:47] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 47 total children
[08-Jan-2020 17:27:48] WARNING: [pool tab10] server reached pm.max_children setting (50), consider raising it
[08-Jan-2020 17:29:27] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 42 total children
[08-Jan-2020 17:29:28] WARNING: [pool tab10] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 47 total children
[08-Jan-2020 17:29:29] WARNING: [pool tab10] server reached pm.max_children setting (50), consider raising it
 

 

서버사양이며 Xeon E3-1246v3
메모리 16 GB
하드 240 GB SSD
대역폭 50 TB - 1 Gbps

아래는 php pool.d 설정파일 입니다. 서버 내 4개의 사이트 모두 동일한 설정을 줬습니다.

 

[tab10]
user = tab10
group = tab10

listen = /run/php/tab10.sock
listen.owner = tab10
listen.group = www-data

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

php_admin_value[session.cookie_httponly] = 1
php_admin_value[session.use_strict_mode] = 1

; save std error to /var/log/php7.3-fpm.log
catch_workers_output = yes

; save slow process
slowlog = /var/log/php-fpm.tab10.slow.log
request_slowlog_timeout = 10

; php only timeout
php_admin_value[max_execution_time] = 30

; all timeout (php+mysql+exec+fopen+...) (use it carefully.)
;request_terminate_timeout = 90

;php_admin_value[post_max_size] = 25M
;php_admin_value[upload_max_filesize] = 25M

;php_admin_value[session.name] = "MY_SESSION_ID"
;php_value[session.save_path] = /home/myuser1/.php-session

;access.log = /var/log/php-fpm.tab10.access.log
;access.format = "%t %{REMOTE_ADDR}e \"%m %r%Q%q\" %s %f TIME:%{mili}dms MEM:%{kilo}MK CPU:%C%%"

;php_admin_flag[log_errors] = on
;php_admin_value[error_log] = /var/log/php-fpm.tab10.error.log

;php_admin_value[memory_limit] = 128M
;php_admin_value[max_input_time] = 90

 

 

my.cnf 설정파일 일부입니다.

 

# * Fine Tuning
#
max_connections         = 2048
connect_timeout         = 200
wait_timeout            = 300
max_allowed_packet      = 16M
thread_cache_size       = 128
sort_buffer_size        = 4M
bulk_insert_buffer_size = 16M
tmp_table_size          = 32M
max_heap_table_size     = 32M
transaction-isolation = READ-COMMITTED
 

# * MyISAM
#
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched. On error, make copy and try a repair.
myisam_recover_options = BACKUP
key_buffer_size         = 128M
#open-files-limit       = 2000
table_open_cache        = 400
myisam_sort_buffer_size = 512M
concurrent_insert       = 2
read_buffer_size        = 2M
read_rnd_buffer_size    = 1M
 

default_storage_engine  = InnoDB
innodb_buffer_pool_size = 12G
innodb_log_buffer_size  = 256M
innodb_file_per_table   = 1
innodb_open_files       = 800
innodb_io_capacity      = 1000
innodb_flush_method     = O_DIRECT
 

 

 

Xeon E3-1246v3
메모리 16 GB
하드 240 GB SSD
대역폭 50 TB - 1 Gbps

 

위 서버의 사양으로 일접속자 500명에서 3만명까지 토탈 일 4만정도의

사이트를 4개 돌리고 있습니다. (php 설정 모두 동일하게 각각의 conf파일)

클라우드플레어의 디도스어택 페이지를 실행하면 우선 에러는 멈추는데요.

이것이 서버세팅의 문제인지, 한서버에 과도하게 많은 사이트를 운영중인건지

실제 디도스공격인건지가 좀 궁금합니다. 해결책이 있을지도요...

 

free -m 결과입니다. (서버구매시는 16기가로 적혀있었는데 32기가인거 같네요;;)

              total        used        free      shared  buff/cache   available
Mem:          32127        2395       23041          24        6690       29253
Swap:          7811           0        7811
 

  • profile

    일단 nginx 에러이므로 php-fpm이나 my.cnf 쪽은 보실 필요 없습니다. (pm.max_children을 늘리라는 메시지는 무시하는 것이 정석입니다.)

     

    링크하신 글은 10년 전에 작성된 것이어서 우분투 18.04 버전의 systemd 환경에 맞지 않고, 편집하라고 하는 설정파일 경로들도 모두 틀린 것 같습니다. 2018년 이후에 작성된 자료를 찾아보셔야 할 거예요. 리눅스는 종류별 버전별 차이가 크기 때문에, 사용하시는 특정 버전을 위해 작성된 튜토리얼 외에는 모두 패스하셔야 합니다.

     

    그것과 무관하게, 클플에서 I'm under attack 모드를 켰더니 문제가 해결되었다면 인간이 아닌 접속자가 꽤 많이 들어와서 문제를 일으키고 있다는 뜻일 수도 있습니다. 누군가가 님 사이트의 유머글을 긁어가고 있거나, 쓸데없는 검색로봇들이 많거나... 디도스는 아닙니다. 만약 디도스라면 에러화면도 안 뜨고 그냥 뻗습니다.

  • profile ?
    감사합니다. 대략 최신자 팁들도 비슷비슷해서 적용은 했는데
    디도스 풀면 똑같이 502가 뜨네요.
    그런데 디도스어택을 풀어도 다른 사이트들은 괜찮은것 같고
    접속자가 많은 한 사이트만 그러네요
  • profile
    pm = static
    pm.max_children = 400
    으로 바꾸고 php7.3-fpm 재시작 해보세요.
  • profile ?
    영광입니다 감사합니다. 위의 설정들도 라엘님의 블로그를 참고하여 세팅하였습니다.
    항상 많은 도움을 받고 있습니다.
    pm = static
    pm.max_children = 400

    으로 변경해봤지만 502만 뿜어네네요
  • profile profile
    램 최대 50기가까지 쓰라고요? ㄷㄷㄷ
  • ?

    nginx 로그인데요. 실제 page=69522043 페이지가 이만큼 존재하지가 않는데
    실시간 로그들이 보드별로 페이지를 길게 잡아서 나오네요;;

    2020/01/08 18:55:45 [error] 2290#2290: *5015004 connect() to unix:/run/php/tab10.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 39.115.243.81, server: testtab10.net, request: "HEAD /bbs/board.php?bo_table=title&page=69522043 HTTP/1.1", upstream: "fastcgi://unix:/run/php/tab10.sock:"

  • ? profile

    그러니까 아까 말씀드린 것처럼 누군가가 잔뜩 긁어가고 있는 것 같아요. 마지막 숫자를 조작하지 않았다면 저렇게 실제 존재하지 않는 페이지로 링크가 연결될 리 없거든요. 문제의 아이피는 로그에 딱 박혀 있으니, 저런 이상한 로그를 발생시키는 아이피들을 클플에서 차단해 버리면 많이 나아질 것 같습니다.

    유머사이트는 서로 긁어가고 긁히고 아주 난장판입니다. 파싱 프로그램도 잘 만들면 사이트 주인이 눈치채지 못하게 조용히 긁어갈 수 있는데, 그런 거 하는 사람들이 전문가일 리 없으니 상대방 사이트가 다운되든 말든 그냥 무조건 돌리는 거예요. ㅠㅠ

  • ? profile

    저렇게 무리하게 긁어가는 놈이 근본적인 원인이지만, 그렇다고 해서 서버가 에러를 뿜으면 안 되는데 계속 502 에러가 발생하는 것은 open files 갯수 제한 때문입니다. file이라고 했지만 사실은 하나의 프로그램이 동시에 감당할 수 있는 네트워크 커넥션의 갯수를 말합니다.

    nginx의 open files 갯수 문제에 대해서는 이미 알고 계신 것 같고, php-fpm과 unix socket으로 연동할 경우 sysctl.conf에서 net.core.somaxconn도 충분히 큰 값으로 늘려주어야 합니다. 프로세스 갯수가 아무리 많아도 저 값이 낮으면 실제로 그만큼 접속할 수가 없습니다.

    서버 한 대로 수천 명의 접속자를 처리하기 위해서는 저것 외에도 튜닝해 줘야 할 파라미터가 여러 개 있습니다. 기본 상태에서는 조금만 사람이 몰리거나 사이트를 긁어가는 녀석이 나타나면 에러나는 것이 정상입니다. 접속자가 많은 사이트를 운영하기 위해서는 서버 튜닝이 매우 중요한 이유입니다. 그러나 님 사이트는 전문적인 튜닝이 필요할 만큼 접속자가 많은 것이 아니라 페이지수를 조작해서 긁어가는 한두 명이 문제인 것 같으니, 그것만 차단하면 해결될 것으로 보입니다.

  • ? profile

    php 프로세스가 빨리 안끝나니까 오류가 생긴것이고, 이 경우 db 쿼리 문제일 겁니다.
    mysql slow query 를 기록하게 하고 살펴보세요.

    또는 디버거를 붙이면 확인할수 있어요.

    또는 클플에서 Rate Limiting 설정하면 되요.

  • profile
    nginx 에서 과다 접속 차단 해보시는게 좋을듯하네요