Webシステムのパフォーマンス設計に関するベストプラクティス(OS編(Linux))

 ITシステムがブラックボックス化している現代においてインフラエンジニアの需要は縮小していくという人もいますが、私は必ずしもそうではないと考えています。特にパフォーマンス分野のエンジニアは今後も絶対になくならない職種のひとつだと言ってよいでしょう。なぜならシステムがいくらブラックボックス化したとしても各システムの特性に適した難易度のパフォーマンスチューニングが必要不可欠だからです。しかしその分難易度も高く、どういった設計をしたらよいのか一般的なノウハウがあまりないように思いましたので、本記事にてパフォーマンス設計のベストプラクティスをまとめてご紹介しようと思います。今回はLinuxを想定したOSレイヤの要素に関するパフォーマンス設計についてご紹介しますのでぜひご参照ください。

    1. はじめに

     今回のシリーズでは、LinuxシステムにおけるWeb3層のオンラインシステムを想定したパフォーマンスベストプラクティスをご紹介させていただきます。システムパフォーマンスを向上させるには、システムを構成するあらゆる要素を考慮する必要があります。たとえばミドルウェアのチューニングが完璧でもネットワークの通信速度が出ていなくて処理遅延につながることもあります。したがってパフォーマンスエンジニアはあらゆる要素に対する知見をもって対応する必要があります。一般的にシステムを動作させるために必要な要素を下図に記載します。

    今回の記事では、Operating System(OS)レイヤ、特にLinuxに関するパフォーマンス設計について記載させていただきます。基本的にどのLinuxディストリビューションであっても初期設定で最適に動作されるように調整されているパラメータが多いですが、システム特性や使用するミドルウェアによっては調整が必要なパラメータがありますので、内容を理解しておくことを推奨します。

    2.1 カーネルパラメータ設計

    チューニングを検討すべきKernelパラメータを下記に記載します。

    カテゴリパラメータ説明
    カーネルkernel.msgmaxメッセージキューに書き込まれるひとつのメッセージの最大バイト数。
    ※1 メッセージキュー関連のパラメータの概念に関する説明が記載されているサイトを共有します。
    https://actcrp.com/actdepo/service/learning/actperf/ipcinfo.htm
    kernel.msgmnbひとつのメッセージキューに保持できるメッセージの最大値。
    kernel.msgmniメッセージキューIDの最大値。デフォルト値はメモリ値により可変。
    kernel.shmallシステム全体で使用可能な共有メモリの総量(単位:4kページ)
    kernel.shmmax利用可能な共有メモリの最大サイズ(単位:byte)。
    物理メモリの量と同じ値に設定することが推奨されています。
    kernel.shmmni共有メモリセグメントの最大数。
    kernel.sem排他制御に使用するセマフォの数。
    デフォルトだと値が小さいので増やすことを検討しましょう。
    kernel.threads-maxシステム全体のプロセス数の上限値。
    ネットワークnet.ipv4.ip_local_port_range使用するポートを選択する範囲の指定。
    TCPコネクション数がボトルネックにならないようにデフォルトから範囲を増やすことを検討しましょう。
    net.ipv4.ip_local_reserved_ports予約ポート。
    製品がポート指定して使うといった理由で使用されたくないポートがある場合は、本パラメータに設定して自動的に使用されないようにしておきましょう。
    net.ipv4.tcp_keepalive_time接続してからKeepAliveパケットが送信されるまでの時間。
    デフォルトだと7200秒(2時間)と長めになっています。TCPコネクションをかけ続けることでサーバに負荷がかかることがありますので、必要に応じて時間を短くすることを検討してみて下さい。
    net.ipv4.tcp_wmem1接続あたりのメモリ送信バッファサイズの値。
    net.ipv4.tcp_rmem1接続あたりのメモリ受信バッファサイズの値。
    net.ipv4.tcp_moderate_rcvbufバッファサイズの自動調整設定。「1」を設定することでバッファサイズの自動調整を有効にすることができます。
    net.ipv4.tcp_window_scalingウィンドウサイズの最大値。「1」を設定することでウィンドウサイズが最大で1GBのサイズまでスケールされます。
    net.ipv4.tcp_max_syn_backlogソケットあたりのSYNを受け付けてACKを返却していない状態のコネクションのキューサイズ。Listen Backlogキュー以上の値を設定します。
    net.core.somaxconnListen Backlogキューの値。
    net.ipv4.tcp_fin_timeoutFIN-WAIT2状態に保つ時間。
    ※多くのリクエストを受け付けるシステムにおいてはtimeout時間を短く設定してパフォーマンスを向上させることが有効です。TCP接続における各状態に関する説明が記載されているサイトを共有します。
    https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
    ipv4.tcp_tw_reuseコネクション再利用要否。
    「1」を設定することでTIME-WAIT状態となっているコネクションを再利用することができます。
    ファイルシステムfs.file-maxファイルディスクリプタのシステム全体の上限値。
    ファイルディスクリプタとはプログラムからファイルを操作する際に、ファイルに割り当てられる番号です。割り当てられるファイルディスクリプタが上限に達してしまうと、コネクションが張れなくなってユーザ影響出る可能性があるので、適切な値にチューニングしておきましょう。fs.file-maxと合わせてlimits.confを変更してユーザごとのファイルディスクリプタ数も変更しておきましょう。
    fs.aio-max-nrシステムが処理できる非同期I/O操作の最大数。
    Oracleなどのデータベースは非同期I/O操作が多くなりますので、デフォルトの値より大きい値を設定しておくことを推奨します。
    メモリvm.nr_hugepagesHugePageのページ数。
    HugePageとは、仮想アドレスと物理アドレスの変換を行うページテーブルのページサイズをデフォルト値の4KBより大きな値(デフォルト2MB)に設定する機能。 HugePageを利用することでページテーブル処理の削減によるCPUオーバヘッド軽減、ページ数削減によるメモリ使用量の削減が期待されるため性能向上が見込まれる。 特にOracleではSGAの領域に対してHugePageを利用することが多い。ただし、自動メモリ管理が利用不可になってしまうため注意が必要。
    vm.min_free_kbytes最小KByte数の空きメモリを確保数量に強制する設定。
    本値を設定することで、カーネルプロセスが必要なリソースを保持することで安定稼働につながります。メモリ不足(OOM)の状況を回避し、メモリの断片化を緩和することができます。
    各パラメータの詳細については下記を参照ください。
    https://github.com/torvalds/linux/blob/v4.15/Documentation/sysctl/kernel.txt

    ネットワーク関連のTCPチューニングに関する詳細情報は下記にも記載していますので、ぜひご参照ください。
    Webシステムのパフォーマンス設計に関するベストプラクティス(ネットワーク要素編)

    2.2 I/Oスケジューラ設計

    I/Oスケジューラとは、発行されたI/O要求を適切な順番に並び替えることで、スループットおよびレスポンスの短縮を実現する機能となります。I/Oスケジューラはいくつか種類がありますので、最適な設定を選択するようにして下さい。

    スケジューラ名説明
    noop特に何も処理をしない。IO要求をFIFOキューに書き込みそのままの順番で処理をする。他のスケジューラ設定と異なりオーバーヘッドがないため、ディスク性能の高いSSDを使う場合はnoopが最適な設定になり得る。
    deadlineレイテンシーのデッドラインを設け、それよりも前に処理が終わるようにI/Oスケジューラが調整する方式。つまりレイテンシーの外れ値を発生させないようにできる。Oracle ASMを使う際は本設定が推奨されている。
    cfqCompletely Fair Queuing。CPUのスケジューリングのようにプロセスにI/Oタイムスライスを割り当てる方式。

    まとめ

    OSレイヤ(Linux)に関するチューニングの説明は以上となります。Linuxカーネルのチューニングについては奥が深くまだまだ学ぶことが多いと感じていますので、適宜アップデートしていきたいと思います。
    ここまで読んでいただきありがとうございました。他の要素についての記事も書いているのでよかったら合わせて見てもらえると嬉しいです。
    Webシステムのパフォーマンス設計に関するベストプラクティス(システム構成・ハードウェア要素編)
    Webシステムのパフォーマンス設計に関するベストプラクティス(仮想化要素編(VMware))
    Webシステムのパフォーマンス設計に関するベストプラクティス(ネットワーク要素編)

    参考文献

    Red Hat Enterprise Linux 7 パフォーマンスチューニングガイド

    https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/pdf/performance_tuning_guide/red_hat_enterprise_linux-7-performance_tuning_guide-ja-jp.pdf

    Linuxカーネルパラメータのチューニング&設計

    Linux+DB2のパフォーマンスチューニング

    I/Oスケジューラ

    コメント