ユーニックス総合研究所

  • home
  • archives
  • low-spec-django-uwsgi

低スペックサーバーでDjangoとuWSGIを動かす時の設定

  • 作成日: 2021-12-09
  • 更新日: 2023-12-24
  • カテゴリ: Django

低スペックサーバーでDjangoとuWSGIを動かす時の設定

低スペックサーバーで問題になるのがメモリだ。
安価なサーバーでは十分なメモリを用意することはできない。
1ギガバイト以下のメモリでサイトを運営することになる。

そういったサーバーでDjangoをNginxで動かすにはコツがいる。
ドキュメント通りの設定は、低スペックサーバーのことを考慮していないからだ。
ここでは低スペックサーバー向けのuWSGIの設定を紹介する。

運営サイトが不安定

筆者も例にもれずとあるサービスを低スペックサーバーで運営していた。
まだ1~2年ぐらいのサイトだ。
収益化も実現しておらず絶賛育成中のサービスである。

筆者はケチなので、このサービスのサーバーをもっとも低スペックなプランで用意した。
PVが増えてきたら高スペックにスケールしようと考えていたのだ。

しかし、この低スペックなプランは、Djangoをデプロイするにはあまりも低スペックすぎた。
Webにあるドキュメントの設定どおりDjangoをuWSGIを使ってNginxで稼働させると、不安定になってしまう。
具体的には起動後はちゃんとサイトが表示されるが、しばらくするとサイトが表示されなくなるという具合だ。
非常に奇怪な現象だが、原因をさぐってみるとどうやらメモリ不足が原因のように思えた。

このサーバーのfreeコマンドの出力結果はかつかつで、ろくに余裕がない。
そのためスケールしてスペックを上げたほうがいいのだが、私は予算があまりないためスケールは選択肢に入れなかった。
というのも最近低スペックな別のサーバーをスケールしたばかりで、立て続けにスケールをするという贅沢な運営は私にはできなかったのだ。

そのため低スペックなままでサイトを稼働させるという選択肢を取った。

余談: スケール費用とランニングコスト

ちなみにこれは関係のない余談だが、ランニングコスト(維持費)の見積もりはスケール費用を計算に入れるべきだ。
私はランニングコストをケチって低スペックなサーバーでサイトをスタートさせた。
しかし結局スペックが足りなくなってスケールをすることになった。

問題はこのスケールの費用だ。
使っているVPSのスケール費用はランニングコスト1年分になる。

つまり、低スペックなサーバーでサイトをスタートさせて、1年かそこらでスケールした場合は、倍のコストがかかるということになる。
これならスケールを見越したプランで最初から契約したほうが安く済むのだ。
私はこれを知らなかったためいくらか損することになった。

安物買いの銭失いを地で行く私。

🦝 < お金の使い方が下手ですね

uWSGIの設定

本題のuWSGIの設定だが、DjangoをNginxとuWSGIでデプロイするにはuWSGIのiniファイルを用意する必要がある。
これはデプロイの方針によるのだが、一般的にはiniファイルにuWSGIの設定を記述する。

iniファイルにはprocessesというキーを設定できる。
これはuWSGIのワーカープロセスをいくつ起動するかと言う設定項目だ。
一般的な設定ではこれの値が10ぐらいになっていること多い。

しかし、低スペックなサーバーでプロセスを10も起動させるとどうなるかというと、メモリの枯渇が起こる。
そのため低スペックなサーバーではこの値を小さくする必要がある。
よってiniの設定は以下のようになる。

# mysite_uwsgi.ini file  
[uwsgi]  

# Django-related settings  
# the base directory (full path)  
# mange.pyが存在するディレクトリを指定する  
chdir           = /path/to/base/dir/  

# Django's wsgi file  
# wsgiファイルの名前を指定する  
# このファイルはDjangoが作成してくれている  
module          = mysite.wsgi  

# the virtualenv (full path)  
# 仮想環境のディレクトリを指定する  
# この環境は python -m venv で作ることができる  
home            = /path/to/venv/  

# process-related settings  
# master  
master          = true  

# maximum number of worker processes  
# 稼働させるワーカープロセスの数  
# ここの値を10から5に低くすると安定稼働するようになった  
processes       = 5  

# the socket (use the full path to be safe  
# ソケットを使う場合はソケットを指定する  
socket          = /path/to/socket.sock  

# ... with appropriate permissions - may be needed  
# ソケットの権限  
chmod-socket    = 666  

# clear environment on exit  
vacuum          = true  

筆者の実験によると低スペックなサーバーでもprocesses5に設定するとサーバーが安定した。
freeの結果も余裕があるようになった。
稼働プロセスを減らすことでかつかつのメモリに余裕ができたわけだ。

ちなみにiniではなくコマンドのオプションでこのprocessesの値を設定することもできる。
その場合は以下のようにコマンドを打つ。

$ uwsgi --http :8000 --master --processes 5 --wsgi-file mysite.py  

ワーカープロセスは何をやってるのか?

ちなみにこのワーカープロセスだが、謎に満ちたプロセスだった。
公式のドキュメントにはただこう書いてあるだけである。

processes  
    argument: required_argument  
    shortcut: -p  
    parser: uwsgi_opt_set_int  
    help: spawn the specified number of workers/processes  
          指定の数のワーカープロセスを起動します  

推測だがワーカーというぐらいだからリクエストの処理をしてくれているのだろう。
マルチプロセスにすることで複数のリクエストを並行して処理できるため、早くなるというのが普通だと思う。

つまり今回のprocessesの設定は速さを犠牲にしてメモリを確保しているということになる。
そのためスケールして速度が必要になった場合はこの設定を見直す必要があるだろう。

おわりに

貧者に必要なのは工夫である。
低スペックなサーバーでもDjangoを安定稼働させることができた。
このような工夫が必要なくなるように空からお金が振ってきてくれることを何よりも望む。

🦝 < お金でサーバーをぶん殴る

🐭 < ぶん殴ってどうする