1時間あたり3,600万件のクエリ、10,000以上の常時動作するクライアント、1つのサーバー、nginx + mysql

状況は、かなり大きな負荷で動作するプロジェクトに参加していることです。 すでに書かれているように-1時間あたり3,600万のリクエスト。 過去1か月間、サーバーをセットアップして多くのことを読んで試しました。 このような構成でうまく機能するものを、簡潔かつコンパクトに抽象的に提供したいと思います。



私が最初に気づいたのは、重い負荷の下ですべてをセットアップする方法に関する多くのヒントでした。 よく読んでください。通常は、1日あたり1万〜2万人の顧客の「高負荷」について話していることがわかります。 毎日約100万人の顧客が活動しています。



私たちにはお金がなく、私たち自身の費用ですべてをするので、節約します。 結論-100万人の顧客全員が1台のサーバーでサービスを提供しています。このサーバーではhetznerのEX-60を使用しています。



クライアントを介して誤ってDDoSアナログを作成しましたが、設定の結果、4000のPHPプロセスがあり、4000未満のOSもロードしたときに、多くの構成を試して、最も機能する構成を見つけることができました。 彼らはソフトウェアのエラーに対処しました。現在、これらの1秒あたり10〜12,000の要求は、3.92、3.22、2.85の平均負荷で処理されています。 もちろん、単一のサーバーではありませんが、1つのサーバーに対しては良い結果が得られると思います。



OS-CentOS 7.1、64ビット。 最小インストール、さらにiptables、nginx、php-fpm、mysql。 kernel-mlからの4番目のバージョンのカーネル。



高圧tcp接続のカーネル設定の調整:



/etc/sysctl.conf
fs.file-max = 1000000

net.ipv4.ip_local_port_range = 1024 65535

net.ipv4.conf.all.accept_redirects = 0

net.ipv4.conf.all.secure_redirects = 0

net.ipv4.conf.all.send_redirects = 0

net.ipv4.tcp_max_orphans = 65536

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_keepalive_time = 1800

net.ipv4.tcp_keepalive_intvl = 15

net.ipv4.tcp_keepalive_probes = 5

net.ipv4.tcp_max_syn_backlog = 65536

net.ipv4.tcp_synack_retries = 1

net.ipv4.tcp_mem = 50576 64768 98152

net.ipv4.tcp_rmem = 4096 87380 16777216

net.ipv4.tcp_wmem = 4096 65536 16777216

net.ipv4.tcp_orphan_retries = 0

net.ipv4.tcp_syncookies = 0

net.ipv4.netfilter.ip_conntrack_max = 1048576

net.ipv4.tcp_timestamps = 1

net.ipv4.tcp_sack = 1

net.ipv4.tcp_congestion_control = htcp

net.ipv4.tcp_no_metrics_save = 1

net.ipv4.route.flush = 1

net.ipv4.conf.all.rp_filter = 1

net.ipv4.conf.lo.rp_filter = 1

net.ipv4.conf.eth0.rp_filter = 1

net.ipv4.conf.default.rp_filter = 1

net.ipv4.conf.all.accept_source_route = 0

net.ipv4.conf.lo.accept_source_route = 0

net.ipv4.conf.eth0.accept_source_route = 0

net.ipv4.conf.default.accept_source_route = 0

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_window_scaling = 1

net.ipv4.tcp_rfc1337 = 1

net.ipv4.ip_forward = 0

net.ipv4.icmp_echo_ignore_broadcasts = 1

net.ipv4.icmp_ignore_bogus_error_responses = 1

net.core.somaxconn = 262144

net.core.netdev_max_backlog = 1000

net.core.rmem_default = 65536

net.core.wmem_default = 65536

net.core.rmem_max = 16777216

net.core.wmem_max = 16777216



サーバーにユーザーがいないため、ファイルの制限を調整します。



/etc/security/limits.conf
*ソフトnproc 65535

*ハードnproc 65535

*ソフトnofile 100000

*ハードnofile 100000

ルートソフトnofile無制限

ルートハードnofile無制限



モンスターは知っていますが、長い間、私は管理しておらず、*がルートで機能しないことを認識していなかったため、個別に調整する必要があります。



これですべてです。



筋肉の設定。 Percona-56がインストールされています。



その結果、InnoDBで選択が行われ、TokuDbを試しましたが、大量の一定の挿入が行われ、1時間あたり3,600万の95%があります。 InnoDBの動作は改善されており、perkonのテストでも同じことが言えます。



MySQL設定:



/etc/my.cnf
[mysql]

ポート= 3306

ソケット= /var/lib/mysql/mysql.sock

[mysqld]

ユーザー= mysql

default-storage-engine = InnoDB

ソケット= /var/lib/mysql/mysql.sock

pid-file = /var/lib/mysql/mysql.pid

キーバッファサイズ= 32M

myisam-recover = FORCE、BACKUP

最大許容パケット= 16M

最大接続エラー= 1000000

スキップ名解決

datadir = / var / lib / mysql /

tmp-table-size = 32M

最大ヒープテーブルサイズ= 32M

query-cache-type = 0

query-cache-size = 0

最大接続数= 15000

thread-cache-size = 5000

オープンファイル制限= 150000

テーブル定義キャッシュ= 1024

table-open-cache = 50000

innodb-flush-method = O_DIRECT

innodb-log-files-in-group = 2

innodb-log-file-size = 2G

innodb-file-per-table = 1

innodb-buffer-pool-size = 10G

innodb_flush_log_at_trx_commit = 0

log-error = /var/log/mysql/mysql-error.log

log-queries-not-using-indexes = 0

slow-query-log = 1

slow-query-log-file = /var/log/mysql/mysql-slow.log



この負荷がかかった状態でクエリキャッシュをオフにしてください。 システム全体が本当に遅くなります。 しかし、おそらくあなたの場合ではなく、遊んでみてください。しかし、私がこの瞬間に会った多くのテストやテキストでは、自宅で確認しました-それは、切断されたものでより速く動作します。



skip-name-resolveも良いブーストを提供します。



nginxの標準に関する追加設定:



fastcgi_params
fastcgi_param REDIRECT_STATUS 200;

fastcgi_buffer_size 4K;

fastcgi_buffers 64 4k;



私たちのニーズに応えるnginx tyunim:



nginx.conf
ユーザーnginx;

worker_processes 8;



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

pid /var/run/nginx.pid;



worker_rlimit_nofile 150000;



イベント{

worker_connections 8000;

multi_accept on;

epollを使用します。

}



http {

/etc/nginx/mime.typesを含めます。

default_type application / octet-stream;



log_format main '$ remote_addr-$ remote_user [$ time_local] "$ request"'

'$ステータス$ body_bytes_sent "$ http_referer"'

'"$ http_user_agent" "$ http_x_forwarded_for"';



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



gzipオフ;

sendfile on;

tcp_nopush on;

tcp_nodelay on;

reset_timedout_connection on;

server_tokens off;

client_body_buffer_size 128k;



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



}



8つのコアがあるため、兄弟ごとに8000の8つのワーカープロセスは、一度に64kを超えるサービスを提供できません。 より多くの同時接続がある場合、小さなキューがあります。



php-fpmを使用するサイトでは、ソケットを介して通信します。

/etc/nginx/conf.d/site.conf
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;

fastcgi_send_timeout 180s;

fastcgi_read_timeout 180s;



メイン設定php-fpm:



/etc/php-fpm.d/www.conf
listen = /var/run/php-fpm/php-fpm.sock

pm =オンデマンド

pm.max_children = 4000

pm.start_servers = 5

pm.min_spare_servers = 5

pm.max_requests = 0



ondemandは多くの場所で説明されていませんが、負荷が高い場合の動的よりも優れています。 そしてもちろん、静的はサーバーを殺すものであり、あまり好きではありませんでした。



ondemandは5から始まり、必要に応じて成長しますが、動的とは異なり、負荷を減らして、プロセスを強制終了せずに再構築しますが、ピーク時に値を修正し、不要なものをスタンバイモードにします。 そして、突然負荷が再び大きくなる場合-プロセスの準備ができている場合、誰もゼロから開始する必要はありません。



pm.max_requests = 0は、サードパーティソフトウェアのメモリリークに対処するのに役立ちます。



実際、これが1時間あたり3,600万のサービスを提供する方法であり、そのうち95%はデータの転送とデータベースへの書き込みです。 28億のクエリの場合、10〜16個のslow_queryがあり、それぞれが10秒以下であり、それらはすべて、多くのフィールドとテーブルでの結合の選択です。 残りのリクエストは即座に処理されます。



php-fpmの代わりに、一度にhhvmをコンパイルして使用しました。本当に賢く動作し、php-fpmよりはるかに高速ですが、問題があります-30〜40分ごとに、そしてしっかりと落ちます。



彼は開発者にgitに手紙を書きましたが、彼らは助けられず、理由を知りません。 その結果、バージョン5.6のphp-fpmに座っています。



すべてのソフトウェアはyumを介してインストールされ、メガチューニングを使用した種類のビルドも使用されません。



1つの場所の設定に関するこの情報は、誰かにとって役立つと思います。



All Articles