Nginxで帯域制限を行う方法

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

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でのタイムアウトの設定

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

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

投稿者プロフィール

林 晃
林 晃macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者
アールケー開発代表。macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者。ObjC/Swift/C++使い。豊富な開発実務経験を基に、教育コンテンツ開発、技術書執筆、技術指導、技術セミナー講師、企業内研修講師、行政・自治体職員研修講師も行います。

基礎から学ぶMetal


「基礎から学ぶMetal」を執筆しました。本書はMetalを使ってGPUプログラミングを行うための最初のステップを解説するMetalの解説書です。

私が初めてGPUプログラミングを行ったとき、どこから手をつけて、学んでいけば良いのか分からず呆然としました。もし、あのとき、これを教えてくれればという部分を解説しました。本書で解説している部分はMetalの基礎となる部分で、Metalを使うときに必ず触れることになる部分です。

詳細

基礎から学ぶSwiftUI


「基礎から学ぶ SwiftUI」というタイトルの本を執筆しました。

SwiftUIの入門書です。

SwiftUIのコンセプトは「ユーザーインターフェイスを作るための最短パスを提供する」「一度学べば(Appleのプラットフォームの)どこにでも適用できる」です。

SwiftUIの概要から始まって、一つ一つのテクノロジートピックに注目しながらSwiftUIとは何か?どんなことができるのか?どのようなコードを書けば良いのかなどを丸々一冊使って解説しています。

詳細

関連記事

  1. Parallels Desktopで古いmacOSゲストをセットアップ…

  2. インストーラのNotarization Service対応

  3. バイナリファイルに含まれるアーキテクチャを調べる

  4. 【2021/6/23更新】 Xcodeの動作環境

  5. Dockerを使ったAlfrescoのセットアップ方法

  6. NginxのPOSTの設定

最近の著書

  1. 基礎から学ぶ SwiftUI

最近の記事