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

最新の投稿
HowTo2022.02.13Ubuntu Server のシステム更新
書籍執筆2022.02.10ARKitの物理シミュレーション
書籍執筆2022.02.04ARKitでコリジョンとアニメーション
HowTo2022.01.30MayaからUSD, USDZを書き出す方法