CPU:
16 vCore
RAM:
65536 MB
Storage:
400 GB SSD

 

안녕하세요. 일방문자 5만명 정도의 팬클럽 커뮤니티를 운영중입니다.

그누보드를 사용하는 사이트이고 주로 글은 운영자만 쓰는 형태이고

게시글당 1,000~2,000 가량의 글이 달립니다.

현시간 CPU사용량은 300프로 정도됩니다.

 

최근 갑자기 게시물 본문 들어갈때 ttfb가 20초가 나옵니다.

게시물을 하나 보려면 20초가량을 기다려야 합니다.

답답하여서 설정을 좀 고쳐보았는데 마구잡이로 숫자만 올린것 같아

수정할 부분이 있을지 봐 주시면 감사하겠습니다.

 

user  www-data;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  4096;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

 

 

server {
    listen       80;
    server_name  rocketman.com www.rocketman.com rocketman.net rocketman.pw www.rocketman.net www.rocketman.pw;
    root   /home/rocketman/www;
 
    access_log /var/log/nginx/rocketman.com.access.log;
    error_log off;
    server_tokens off;
    client_max_body_size 30M;
    location / {
        index  index.php index.html;
    }
location ~ \.(jpe?g|png|gif)$ {
        valid_referers none blocked www.rocketman.com rocketman.com *.rocketman.com;
        if ($invalid_referer) {
            rewrite ^(.*)$ /img/logo.png redirect;
        }
    }

    location = /img/logo.png {
    }
 
    # Block dot file (.htaccess .htpasswd .svn .git .env and so on.)
    location ~ /\. {
        deny all;
    }
 
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }
 
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
 
    # Block .php file inside upload folder. uploads(wp), files(drupal, xe), data(gnuboard).
    location ~* /(?:uploads|files|data)/.*\.php$ {
        deny all;
    }

    #board list, board detail rewrite and redirect rules.
    rewrite ^/([a-zA-Z0-9_]+)$ /bbs/board.php?bo_table=$1 permanent;
    rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)$ /bbs/board.php?bo_table=$1&wr_id=$2 permanent;
    rewrite ^/tb/([a-zA-Z0-9_]+)$ /bbs/board.php?bo_table=$1 permanent;
    rewrite ^/tb/([a-zA-Z0-9_]+)/([0-9]+)$ /bbs/board.php?bo_table=$1&wr_id=$2 permanent;

        # Add PHP handler
    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        fastcgi_pass unix:/run/php/rocketman.sock;
        fastcgi_index index.php;
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
        proxy_read_timeout 300;
        send_timeout 300;
        include fastcgi_params;

    }

}
 

 

[rocketman]
 
user = rocketman
group = rocketman
 
listen = /run/php/rocketman.sock
 
listen.owner = rocketman
listen.group = www-data

#pm.max_children      = 1024
#pm.start_servers     = 128
#pm.min_spare_servers = 128
#pm.max_spare_servers = 128
#pm.max_requests      = 12000
pm = dynamic
pm.max_children =4096 
pm.start_servers = 2048 
pm.min_spare_servers = 1924
pm.max_spare_servers = 3152 
pm.max_requests = 9000

php_admin_value[session.cookie_httponly] = 1

;php_flag[display_errors] = off
;php_admin_value[error_log] = /var/log/fpm-php.www.log
;php_admin_flag[log_errors] = on
 
;php_admin_value[memory_limit] = 128M
;php_admin_value[max_execution_time] = 120
;php_admin_value[max_input_time] = 300
 
;php_admin_value[post_max_size] = 25M
;php_admin_value[upload_max_filesize] = 25M

 

머리아픈 my.cnf 파일입니다.

# MariaDB database server configuration file.
#
# You can copy this file to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0

[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc_messages_dir = /usr/share/mysql
lc_messages = en_US
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
#
# * Fine Tuning
# Connection Config 
key_buffer = 128M
max_allowed_packet = 16M
table_open_cache = 1024
max_connections = 2048
max_connect_errors = 20000
sort_buffer_size = 2M
read_buffer_size = 2M
myisam_sort_buffer_size = 2M
thread_cache = 512
query_cache_size = 512M
query_cache_type = 1
thread_concurrency = 16
tmp_table_size = 128M
max_heap_table_size = 128M
skip-name-resolve
character-set-server=utf8
default-storage-engine=InnoDB

log_warnings = 2
#
# Enable the slow query log to see queries with especially long duration
slow_query_log          = 1
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time         = 5
#log_slow_rate_limit = 1000
log_slow_verbosity = query_plan

#log-queries-not-using-indexes
#log_slow_admin_statements
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
#server-id = 1
#report_host = master1
#auto_increment_increment = 2
#auto_increment_offset = 1
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
# not fab for performance, but safer
#sync_binlog = 1
expire_logs_days = 1
max_binlog_size         = 100M
# slaves
#relay_log = /var/log/mysql/relay-bin
#relay_log_index = /var/log/mysql/relay-bin.index
#relay_log_info_file = /var/log/mysql/relay-bin.info
#log_slave_updates
#read_only
#
# If applications support it, this stricter sql_mode prevents some
# mistakes like inserting invalid dates etc.
#sql_mode = NO_ENGINE_SUBSTITUTION,TRADITIONAL
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
# you can't just change log file size, requires special procedure
#innodb_log_file_size = 50M
innodb_buffer_pool_size= 32G
innodb_additional_mem_pool_size=40M
innodb_write_io_threads = 16
innodb_read_io_threads = 16
innodb_thread_concurrency = 32
innodb_flush_log_at_trx_commit = 1
innodb_log_file_size = 256M
innodb_log_buffer_size = 32M
innodb_log_files_in_group = 2
innodb_flush_method=O_DIRECT
innodb_lock_wait_timeout = 120
innodb_io_capacity = 3000
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem

#
# * Galera-related settings
#
[galera]
# Mandatory settings
#wsrep_on=ON
#wsrep_provider=
#wsrep_cluster_address=
#binlog_format=row
#default_storage_engine=InnoDB
#innodb_autoinc_lock_mode=2
#
# Allow server to accept connections on all interfaces.
#
#bind-address=0.0.0.0
#
# Optional setting
#wsrep_slave_threads=1
#innodb_flush_log_at_trx_commit=0

[mysqldump]
quick
quote-names
max_allowed_packet = 128M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completion

[isamchk]
key_buffer = 16M

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/

 

  • ?

    메모리 사용량 입니다.

    root@--:~# free -m
    total used free shared buff/cache available
    Mem: 64429 50611 5318 27 8499 12772
    Swap: 0 0 0
    root@--:~#

     

    아 참고로 Vultr 시애틀, 클라우드플레어 프로(20달러)플랜 사용중입니다;;;;;

  • profile

    nginx는 어떻게 설정하든 페이지 로딩속도에 큰 영향을 주지는 않습니다.

     

    pm.max_children은 높이면 높일수록 역효과입니다. 반드시!!! 100 미만으로 유지하세요. 정상적인 사이트라면 100 정도만 해두어도 1만 명 이상의 동시접속자를 감당할 수 있습니다. 4096은 서버 자폭하라는 소립니다 ㅜㅜ

     

    모든 테이블이 InnoDB로 되어 있다면 DB 튜닝 상태도 괜찮아 보입니다. (Vultr는 모두 SSD이므로 innodb_io_capacity를 10000 이상으로 높여주셔도 됩니다.) 그러나 그누보드는 기본값이 MyISAM이므로 만약 일부 테이블이라도 MyISAM으로 되어 있다면 DB 튜닝 덕을 보지 못합니다. 있다면 모두 찾아서 InnoDB로 바꿔 주세요. InnoDB로 바꾸더라도 게시판을 새로 만들거나 하면 그누보드는 자동으로 MyISAM이 됩니다.

     

    CPU 16코어 중 3코어(300%) 정도를 사용하고 계시고, RAM 64GB 중에서 50GB 정도를 사용하고 계시니 이것도 정상입니다. pm.max_children을 합리적인 수준으로 낮추면 RAM은 좀더 여유가 생기겠지만, 지금도 부족하지는 않습니다.

     

    제일 큰 문제는 그누보드 쪽에서 찾으셔야 합니다. 그누보드는 처음에는 빠르지만 데이터가 어느 정도 쌓이고 사용자 수가 늘어나면 급격하게 느려지곤 하는데, 쿼리를 잘못 짜서 그런 경우가 90%입니다. DB 설정을 보니 슬로우 쿼리 로그를 켜놓으신 것 같네요. 슬로우 쿼리 로그를 계속 지켜보시면서 거기 등장하는 모든 쿼리를 다 잡아야 합니다. 대개 인덱스가 누락되었거나 불필요한 LIKE 조건이 있거나 뭐 그런 식입니다.