KUSANAGI データベースが落ちたときの対応

  • ---

    LINEで送る
  • -

    ブックマーク
  • -

    pocket
  • -

    rss
超高速仮想マシン KUSANAGI
by 写真AC一部筆者加工

KUSANAGIが推奨メモリ以下だと結構な頻度でデータベースが落ちます。(メモリ2Gで検証。)

『Systemdの自動リカバリ(Restart)でいいじゃん。』とも思ったのですが、そうはいきませんでした。

追記。kusanagiコマンド

どこかのえんじにあ さんからご指摘がありました。(くわしくは下記コメント)

kusanagi configure

を実行すればいいと。

このコマンドは環境に最適な設定をするようですね?

クラウドのスケールアップ(CPU, メモリの増設)・スケールダウンをしたときに必ず実行したほうが良いです。

そういえば、自分のときは忘れていたような...。

(2年以上前なので覚えていない。)

初期設定では月間1.5万PVはきつい

KUSANAGIはWebサイトで使うアプリケーションの集合体で、それらの設定がすでに最適化されています。

『爆速』の環境は特別なことはしていません。(ただし、その設定が絶妙。)

でもこの設定は、月間20万とか30万PVのサイトでも速く処理をさばくように設定されています。だから推奨メモリ4G以上なんですね?

月間ウン十万PVもさばくとなると、それを想定したプロセスが必要で、リクエストがほぼない状態でも待機しているプロセス数が多くメモリ消費量は大きいです。

KUSANAGIのメモリ消費のほとんどはphp-fpmとDB

月間1.5万PVくらいのサイトのメモリ消費量です。

メモリを消費する常駐プロセスが多いアプリ

アプリ消費メモリ割合(%)
php-fpm1プロセス5~6%。
10~13プロセスくらい常駐。
トータル55%。
MariaDB
(データベース)
46%
Nginx
(Webサーバー)
0.1%

合計消費メモリ: 1.7Gくらい。

php-fpmはPHPプログラム(WordPressなど)が処理する根幹の部分。

KUSANAGIでのNginx(Webサーバー)は、php-fpmに丸投げして結果を受ける程度の仕事しかしない。

(専門的にいうとNginxはリバースプロキシサーバー。)

(もちろん設定次第ではリバースプロキシのいろんな仕事をする。)

『php-fpm = (Webサーバーのメモリ消費量)』と考えていい。

月間1.5万PVくらいのサイトでメモリの消費量はつねにシステムメモリの80~90%を使っています。

これくらいなら待機しているプロセスでリクエストをさばくので、サイトアクセスが多くなってもメモリの消費量は増えません。

ただし、集中的にアクセスが増えるとがんばろうとしてプロセスを増やすので消費メモリが増えます。

こうなるとメモリ2Gではどこかしら悲鳴を挙げます。その影響を受けやすいのがデータベースです。

なぜDBが落ちるのか?

消費メモリが足りなくなるのは、ほぼこんな感じ。

短期間にアクセスが集中。
  ↓
大量のアクセスを処理しようとしてphp-fpmの仕事が増える。
  ↓
php-fpmのプロセスが増える。
  or
処理速度が落ちてなかなかphp-fpmのプロセス開放が起きない。
  ↓
結果、php-fpmが多くのメモリをつかんで離さない。
  ↓
メモリ不足

php-fpmの処理速度は、DBクエリーが大量の処理に耐えられなくて遅くなることが多いです。結果、php-fpmの処理が遅くなります。

KUSANAGIでは、メモリ負荷が原因のシステム異常はこのように出ます。

(だいたいは。)

Webサーバー503 Service Unavailable。
たまに
502 Bad Gateway。
メモリ不足でphp-fpmのプロセス生成が限界。

php-fpmの処理が遅くなる。
or
php-fpmが処理を受け付けられない。
DB落ちる。
強制シャットダウン。
DBが使うメモリが不足。
バッファ確保失敗。

DBクエリとphp-fpmの処理はお互いに影響し合うのでどっちが悪いというものでもありません。

DBクエリ遅延
 ↓
php-fpm遅延
 ↓
メモリ使用増

php-fpmがメモリを使用
 ↓
DBが十分なメモリを使えない。
 ↓
DBクエリ遅延
 ↓
php-fpmの処理が遅くなりメモリが開放されない
 ↓
メモリ使用増

メモリの総量は有限なので、DBとphp-fpmのメモリ配分がむずかしいです。

(2年以上の運用経験談。)

Webサーバーがエラーレスポンスを返すのも問題ですが、やっかいなのはデータベースで、メモリ不足が起きると強制シャットダウンします。

(今のところDBサーバーの手動起動しかない。)

プロセスの増大を抑えるチューニング

そこで、設定のチューニングを変えました。

データベースの設定

php-fpmの設定

Webサーバーの設定

細かい設定の説明は省略しますが、チューニングの内容は

サイトの速度を犠牲にしてでもプロセスの増大を抑える。

php-fpm、DBは処理するプロセスが足りなくなると数を増やします。

(もちろんプロセスはメモリを食う。)

その増やす分の数を初期設定より少なくしました。『できるだけ少ないプロセスでがんばってくれ。』ってことですね?

そのほか、Webサーバーのキャッシュ機能も使っています。データベースのクエリキャッシュも増やしました。

(キャッシュはファイル処理なので処理速度は落ちる。)

KUSANAGIの設定から独自にチューニングするのはオススメしません。よっぽどのレベルでないと、まちがいなくKUSANAGI全体の性能が落ちます。

ボクの場合、『メモリ2Gで月間数万PVに最適化』するための性能落ちは想定内です。

KUSANAGIのデータベースはsystemdじゃない

それでも推奨メモリ以下なので限界があります。3ヶ月に1回程度、DBが落ちます。そこで

エンジニア
落ちても自動でリカバリすればいいじゃん

と考えました。systemdの設定はかんたんなので。

ただ残念なことが起きます。KUSANAGIのMariaDBはsystemdにサービス登録されていません。CentOS7では使わなくなったinit.dでのシェルからの起動です。

systemdの操作コマンドsystemctlでも確認できます。

systemctl status mysql
● mysql.service - LSB: start and stop MariaDB
   Loaded: loaded (/etc/rc.d/init.d/mysql; bad; vendor preset: disabled)
   Active: active (running) since 月 2020-01-20 09:07:23 JST; 7h ago
     Docs: man:systemd-sysv-generator(8)
  Process: 719 ExecStart=/etc/rc.d/init.d/mysql start (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/mysql.service
           tq1020 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --pid-file=/var/lib/mysql/kusanagi71.pid
           mq1261 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mys...

 1月 20 09:07:17 kusanagi71 systemd[1]: Starting LSB: start and stop MariaDB...
 1月 20 09:07:18 kusanagi71 mysql[719]: Starting MariaDB.200120 09:07:18 mysqld_safe Logging to '/var/log/mysql/mysqld.log'.
 1月 20 09:07:19 kusanagi71 mysql[719]: 200120 09:07:19 mysqld_safe Starting mysqld daemon with databases from /var.../mysql
 1月 20 09:07:23 kusanagi71 mysql[719]: .[  OK  ]
 1月 20 09:07:23 kusanagi71 systemd[1]: Started LSB: start and stop MariaDB.
Hint: Some lines were ellipsized, use -l to show in full.

CentOS7ではinit.dのサービスはsystemdにラッピングされます。ただし、systemdのサービスファイル(*.service)がありません。

init.dでサービスを起動すると内部でsystemdのサービスに登録される。ただし、サービスファイルの作成まではしない。

だから、systemctlのLoadedがサービスファイルではなくinit.dのシェルになる。

サービスファイルがあれば、その設定でDBが落ちたときに自動起動するリカバリ設定(Restart)ができるのですが、KUSANAGIではできません。

init.dのシェルを改造することになるので断念しました。

(独自のサービスファイル作成も考えたが、KUSANAGIアップデートに影響するので断念。)

一番効果があるのはスワップ

チューニングにも限界がありsystemdで自動起動の設定もできず、結局一番効果があったのはスワップです。

スワップはディスク領域(HDD, SSD)の一部をメモリとして使う機能で、『仮想メモリ増設』です。

ただし、ディスクの読み書きはメモリとは比較にならないくらい時間がかかるのでサイト速度が落ちます。

(ディスク読み書きでCPU利用率も大きくなる。)

これを許すならひとつの手段でしょう。『メモリ増設すれば?』で終わる話ですが。

(いままでの話がぜんぶ無意味...)

KUSANAGIの推奨メモリ4Gを月額3,000円台で提供しているクラウドサーバーもあります。

お金の面がクリアされるならメモリ増設が一番の方法です。

(メモリ4Gなら大概のサイトは耐えられる。何より初期設定で処理が速い。)

SNSでも記事を配信しています。

コメント

  1. どこかのえんじにあ より:

    Kusanagiが使用してるmariadbはsystemd管理でmariadb.service名で登録されてます。
    systemdでの自動起動で上がってこない場合はmonitがデフォルトで動いているのでmariadbプロセスを監視させるように設定することをおすすめします。

    oom-killerでDBが落ちるならまずはkusanagi configureでサーバースペックに対するkusanagiの自動設定を試してください。

    kusanagi configure実施後もphp-fpmのメモリ解放がうまく行かない場合はphp-fpmの設定を見直してください。

    pm.max_childrenを小さくする。
    pm.max_requestsを小さくしてメモリ解放を早めに行うなど。

    またDBに関してもquery_cache_sizeやbufferサイズを見直すなど自分で触れるところは多いです。
    slow_queryをみつつチューニングを試してください。

    1. owner より:

      いろいろなご指摘ありがとうございます。

      一言でチューニングと言いましたが、php-fpmのプロセス, dbキャッシュ、バッファ、etc...のことで、すでに実施済みです。

      ただ、kusanagi configureはしてませんでした。

      実行したところ、『mariadb.service』はないみたいですね?

      [xxx@xxx ~]# kusanagi configure
      mysql.service is not a native service, redirecting to /sbin/chkconfig.
      Executing /sbin/chkconfig mysql --level=5
      mysql.service is not a native service, redirecting to /sbin/chkconfig.
      Executing /sbin/chkconfig mysql off
      Failed to get unit file state for mariadb.service: No such file or directory
      innodb_buffer_pool_size = 768M
      query_cache_size = 192M

      Failed to get unit file state for mariadb.service: No such file or directory
      Failed to execute operation: No such file or directory
      mysql.service is not a native service, redirecting to /sbin/chkconfig.
      Executing /sbin/chkconfig mysql --level=5
      mysql.service is not a native service, redirecting to /sbin/chkconfig.
      Executing /sbin/chkconfig mysql on

      Failed to restart mariadb.service: Unit not found.

      MariaDBを再起動します
      php7 を使用します
      完了しました。

      [xxx@xxx ~]#

      自分の環境ではずっと『mysql.service』です。

      ふつうmariadbのサービス名は『mariadb.service』だし、なんでmysqlなんだろ?って思ってたんですけど、ますます不思議。

      どうしてinit.dのシェルなのかも。

      この環境は運用歴4年目に入ろうかというところなんですけど、いまのkusanagiとはちがうんですかね?

      といってもkusanagiのアップデートはしているのですが。

      PS.
      monitありました。聞いたことあったけど使ったことないので勉強していきます。

コメントを残す

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

top
この記事を気に入ったらぜひシェアも!!