Nextcloud便利だけど重い
Nextcloud という「オープンソース のSynology」みたいな、ファイルサーバーベースのウェブアプリケーション スイート("self-hosted productivity platform")があります。
ウチではDropbox の代替として導入したところ、家族用のSlackを内部アプリのTalk で置き換え、Evernote 代替のJoplinの保存先として設定し…という感じで順調に依存度を高めてます。
ところが、これが動いてる家庭内サーバが遅い。HP Proliant Microserverという10年くらい前のSOHO用サーバで、NTT-X ストアで2万くらいで買えたために一時期流行ったモノ。ドライブベイが5本あってeSata 接続されてるので足回りはそこそこ速いものの、CPUが当時の省電力タイプ(AMD Athlon II)なので、NextCloudみたいな Web サーバ + PHP + DB構成の現代的なサーバープログラムを動かすにはいかにも力不足。*1
PHP のアップデートやキャッシングやJIT コンパイラ の導入など、できることはやりつくしました。
さすがにもうこのサーバは古すぎるなあ、新しいのほしいけど、この手の部内用サーバってクラウド に置き換えられて絶滅しちゃってるんだよなあ…。
高可用性への道
と思っていたところ、こんなドキュメントを見つけました。
An Insiders Look into scaling Nextcloud by Matthias Wobben
Nextcloud社はサーバをオープンソース で開発しつつ商用サポート版とかを売る商売をやってまして、これはそのセールスエンジニアが書いたプレゼンです。
アーキテクチャ 解説の部分に、こんな連続図がありました:
全体の構成
Nextcloudプログラム本体
データベース
ファイル群
分ける
ふむふむ・・・と見ていって、9ページでスパッと分かれたのを見たときは、思わず「かっけー!」って叫びましたね。なんかとろくさいと思ってたNextcloudは、実はキレイに分割できるアーキテクチャ になっていた。
Nextcloud社では、この形で(さらに負荷分散を加えることで)最大5万から10万ユーザーを実現してるとのこと。プレゼンの後半には実際の導入例とかが載ってました。
いやーすばらしい!
このスケーラビリティは、モダンなウェブアプリなら当然ちゃあ当然…なのかもしれませんが、オレは自分で実用的にいじってるものがきちんと分散できる状況にあったことがなく、むしろ複数のサーバを仮想化で1台にまとめるとかの事例ばかり見てきたわけです。
だから、眼の前のものを分割してパフォーマンスブーストができる、という事例を現実感を持って眺められたことで感動しました。こいつはやってみたい!!
家庭内ロードバランシングしてみる
それで自分ちのことを考えてみると、特に重いのがデータベース。MariaDB というMysql の派生プロジェクトのやつで、Mysql より(もちろんSQLite とかよりはずっと)速いらしいんですが、NextCloudを使っているときにtopで監視してると、
MariaDB がCPUを100%近く使う
数秒で落ち着くと、いくつも起動してるphp -fpmのチャイルドプロセスがそれぞれ20-50%ずつ使う
数秒で落ち着くと、手元の表示が出始める
というパターンが頻出します。データベースとphp が足を引っ張ってる。データベースが片方の足を、php がもう片方の足を引っ張って、思い切り沼に引き込まれてる感じ。
これらのCPU boundな処理を外注できれば高速化できそうです。
んで、データベースサーバは切り出すのに最適です。
まず、
である上に、
というデータベースサーバの条件が、
CPUパワーを余らせてる
ディスクは250GBで小さすぎ
というM1 Mac mini にピッタリだったから。
mimi(M1 Mac mini の hostname)、キミに決めた! 働いてもらうぜ!
さっそくmimiでport searchしてみるとmariadb -10.8-serverというのが見つかりましたのでインストール。元のサーバのmariadb データのバックアップを持ってきて流し込み、アクセス権を設定し、元のサーバのNextcloudのnextcloud/config/config.php を編集して接続できるようにしました。
それで動かしてみたら速い!…?
速いんだけど、思ったほどではないっすね~。php -fpmが処理の大部分の時間を使っていて、こちらのほうが重い。反応時間は2/3くらい。
それではこのクソ重いphp もmimiにまかせてしまいましょう。mimiにphp をインストールして、Webサーバのnginx.confのlocalhost :9000をMac mini に向ける…ん? 動かない。
オレは勘違いしてました。php -fpmの動いてるマシンにリダイレクトするだけで分散できるんだろうと。この勘違いは、nginx.confのphp -fpmの設定にあります。php の処理はlocalhost のポート9000に飛ばすようになっている→ということは、データも何もかも一緒に飛ばしてくれるんだよね? と。だってデータベースサーバってそういう分割なんですもん。
ところがphp -fpmは、php スクリプト を直接処理できないウェブサーバのための機構であり、php スクリプト とはもともと簡易な動的なページ生成(「ホームページ」を訪れたら中に現在時刻が出てるとか)のためにあります。ここらへんはデータベースサーバとは根本的に違った出自だからし ょうがない。
というわけで、これは処理部分だけ飛ばすわけにはいかず、プログラムやデータの入ったファイルシステム が見えている必要があります。(上の分割図でいうところのWebサーバ部分)。
で、元のサーバからこのあたりをnfs エクスポートしてmimiでマウントして実験してみると…なんかファイルシステム が見えない。index.php を処理しに行ったphp -fpmプロセスが返ってきません。
しかもここでトラブル発生。mimiのmariadb がCPUを使い切って暴走してます。元のサーバからのアクセスをそのままにして実験したのが悪かった? しかしデータベースなんて複数マシンから同時アクセスされるのが普通じゃないの??
とりあえずmimiのnginxを止めて、mariadb は再起動。
諦めてデータベースサーバの分散だけでよしとする…だがしかし
とりあえず調子良く動いているので安心していたところ、夜になって急にNextcloudの反応がなくなりました。504 Bad Gateway とか出る。
nginxのログを見てみるとphp -fpmがタイムアウト してます。これはデフォルト60秒なので、Nextcloudのアップデート時なんかには出ることがあるエラー。
そんなに負荷が高いのかと思って、サーバでtopを見てみると…静かなもんです。いつもよりぜんぜん使われてないというか、php -fpmが上に来てない。
ps auxw | grep php で見るとphp -fpmのプロセス自体は動いてる。なのにnginxに処理が戻らない。なんか起きてますな…。
変わったことといえばmariadb の分散…というわけでmimiを見てみると、なんかMariadb の負荷が高いですね…。ちょっと再起動してみる。反応変わらず。
とりあえずこの時点でデータベースのバックアップを取ってみる。テーブルが壊れてるとかならバックアップもまともに取れないだろうから、そのときは移行したときのバックアップまで巻き戻す…あれ? 普通にバックアップ取れる。データベースじゃないのか…。
php -fpmのエラーログを見ても、特にエラーは出てない模様。php .iniかなんかでログレベルをdebugまで上げてやると、チャイルドプロセスの展開状況を毎秒知らせてくるレベルでログを吐くんですが、これをやっても出ない。
サーバの環境がなにかぶっ壊れたかなあ、とphp を一旦アンインストールして再インストールしてみたり、はては
freebsd -update upgrade
までやってみたけど、やっぱりphp -fpmの処理が返ってこない状況は変わりません。
やっぱりやっぱりデータベースじゃないの?と思ってmysql コマンドで接続してみると、普通に接続できる。やっぱりデータベースじゃないのか…と諦めて寝ました。
もともと24/7 でまったく止まらずにちゃんと動いていたものが急に調子が悪くなり、しかも原因不明となれば、変えたところがおかしいに決まっているわけです。
しかし負荷分散してアプリを軽くする実験を後退させたくもない。
そしてデータベースサーバは本当に何にでもインストールできる。
というわけで翌朝。これもわりに遊んでるくせに高速な、図書室のWindows 10マシンにMariadb をインストールしてみました。管理の作法がいろいろ違っててめんどくさかったけど、サクッと入って快調に動作。
(軽くハマったのはデータベース本体の管理。「データベースサーバプログラムに接続できるように設定する」ということと「特定のデータベースに接続できるように設定する」ということって違うのね…。mimiに入れたときもやったはずだけど、まだ慣れてない)
それでこちらのデータベースに接続してみると…Nextcloud復活したよ!!
大人しくしてればいいものを実験を続けました。せめてphp を分散できないかなあと。
しかしMac のnginxがNFS マウントしたボリュームの中のファイルを全く読めない。
これはphp -fpmとの絡みを考えたくなかったので静的ファイルで実験したり、macOS 特有のファイルアクセス制限を逃れるために置き場(nginxのdocument root)をいろいろ変えたりしたんだけど、どうしても読めないんですね。nginxの設定そのものがおかしい?と思って/Users/me/Public/の下にindex.htmlを作ってやるとあっさり読めるんですが、同じファイルがNFS の中に入ると読めない。
しかもこれ、エラーはPermission DeniedではなくOperation not permittedが出る。
そうはいってもやっぱり権限問題なんじゃない?と思って sudo _www cat index.html とやると普通に読める…。
サーバ側の設定がおかしいのかもなあ…と思って、Pop!_OS(Ubuntu 派生のたいへん使いやすいデスクトップLinux )の入ったノートPCでnfs マウントしてみると、めちゃめちゃあっさりnginxから読めるw
というわけで、ブン投げました。Mac はサーバにならん。
さらに頑張ってなんとか動かしたとしても、またApple が破壊的な変更をやってくるだろうということが容易に予想がつくので、学習資源が再利用不能 すぎるんですよね。
なのでmimiはそういうことに使わないでよし。です。php -fpmの処理だけならRasPi4とかでも現行サーバよりは軽くなるはず。
ふりかえり
mimiのMariadb は最新版を入れたんですが、マシンがM1であることを考えると、バージョンが新しすぎたかも。次に実験するときは、よく枯れたやつを入れてみます。それでも十分速いはずだし、謎のエラーが出なくなるなら素晴らしい…しかし出なくなるかなw