Nginxで帯域制限を行う方法

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

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

目次

Nginxの設定ファイル

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

帯域制限の設定

帯域制限の設定は、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でのタイムアウトの設定

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

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

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

著書紹介

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

目次