Nginxで帯域制限を行う方法

作っているアプリからHTTPに接続するときに、ネットワークの速度を制限したいことがあります。例えば、とても遅いネットワークや日本国外のインフラが整備されていない地域から接続されるようなときに、正しく動くかを確認したいようなときです。

Nginxで動かしているときは、Nginxの設定でネットワークの帯域を制限して、速度を抑えることができます。

スポンサーリンク

Nginxの設定ファイル

Nginxのオフィシャルイメージで動いているDockerコンテナの場合は、/etc/nginx/conf.d/default.confファイルを編集します。コンテナからファイルをコピーして、コンテナを更新する方法については次の記事を参照してください。

関連記事

Webサーバーと通信アプリを作っているとき、デバッグ中は本当のサーバーに接続するよりも、ローカルマシン内にDockerで作ったテストサーバーと通信した方が便利です。次の記事で作り方を紹介しました。 [sitecard subtitle[…]

帯域制限の設定

帯域制限の設定は、limit_rateを使います。

limit_rate

次のように使います。50KBPS (50K Bytes Per Second) に制限している例です。

server {
    listen 80;
    server_name localhost;

    limit_rate 50k

    以下省略
}

limit_rate_after

最初は早く転送して、残りは遅くするというような帯域制限をかけることができます。

次のように使います。500KB転送した後は帯域を制限します。limit_rateは最初から遅いというシミュレーションができますが、limit_rate_afterは途中で失速するようなケースのシミュレーションに使えると思います。

server {
    listen 80;
    server_name localhost;

    limit_rate_after 500k;
    limit_rate 50k;

    以下省略
}

URLSessionでのタイムアウトの設定

帯域制限のシミュレーションテストを行っていて、クライアントのMacアプリから通信するときにタイムアウトの設定をミスしていたことに気がつけました。

2つのタイムアウト

タイムアウトの設定コードが次のようになっていました。

let config = URLSessionConfiguration.ephemeral
config.timeoutIntervalForRequest = 120
config.timeoutIntervalForResource = 120

Nginxで帯域を思いっきり遅くしたので、ダウンロードには3分ほどかかる状態になっています。URLSessionには2種類のタイムアウトがあり、プロパティで設定します。

  • timeoutIntervalForRequest (レスポンスが返ってくるまでのタイムアウト)
  • timeoutIntervalForResource (ダウンロード完了までのタイムアウト)

上のコードの様にプロパティを設定してしまうと、ダウンロードに3分かかるようなときに、2分でダウンロードが中断されてしまいます。正しくは、timeoutIntervalForResourceは設定しないでデフォルト値を使うか、十分に長い値にするかです。十分に長い値がいくつかは、アプリによって異なるでしょう。私の場合は一行消してtimeoutIntervalForResourceはデフォルト値に変更しました。

それと同時に、ダウンロードをタイムアウトで中止してしまったときにも正しく動くことは確認できたことは良かったです。

ネットワーク側が途切れたときも確認する

タイムアウトの設定ミスは、アプリ側からダウンロードを中止するユースケースです。逆に、ネットワークが途中で途切れてしまって、ダウンロードできないということも確認するべきでしょう。

途中で切断したときのエラー処理

これにも帯域制限が有効です。帯域制限を行って、ダウンロードに十分時間がかかる状態を作ります。ある程度ダウンロードが進んだところで、次のコマンドを実行し、サーバーをダウンさせてしまいましょう。

$ docker-compose down

アプリが正しくエラー処理を実行して、ダウンロード処理を抜けられることを確認します。私の場合はlimit_rate_afterも組み合わせて、半分程度まで一気に進めて、遅くなったところでコマンドを実行しました。

正しくエラー処理が動いて、中止できたことを確認できたら、そのままNginxは停止させたまま、アプリから再接続します。サーバーが動いていないときに正しくエラー処理ができることも確認できます。

ファイルが存在しないときのエラー処理

ここまで確認したら、ついでにファイルが存在しないケースも試します。Dockerで走っているNginxが出力するファイルは、ローカルに置いてあるcontent_homeフォルダ内のファイルです。この中のファイルのファイル名を変更して、意図的にHTTP 403 File Not Foundを発生させます。

アプリで正しくファイルが存在しないときのエラー処理が確認できればOKです。

まとめ

DockerとNginxを組み合わせると、ネットワーク絡みの色々なシミュレーションが手軽にできます。帯域制限は実際に遅い環境などを用意するのは一苦労なので、ローカルマシン内で作れてしまうのはとても便利です。

ネットワークのエラーに強いアプリを作りましょう。

スポンサーリンク
最新情報をチェックしよう!
>現役のプログラマーが書くプログラミング情報

現役のプログラマーが書くプログラミング情報

日々の開発の中での学びや分かったこと、調べたことなどを書いていくブログです。

CTR IMG