How to limit bandwidth with Nginx

There may be occasions when you need to limit the network speed when connecting via HTTP from an application you are developing. For example, when connecting from a very slow network or a foreign country with poor infrastructure, you want to ensure the connection works correctly.

If your web server is operating on Nginx, you have the ability to limit the network bandwidth via the Nginx settings, thus controlling the speed.

TOC

Nginx configuration file

For Docker containers running on official Nginx images, edit the /etc/nginx/conf.d/default.conf file. See the following article for instructions on how to copy files from the container and update the container.

Bandwidth Limit Settings

Use limit_rate to set the bandwidth limit.

limit_rate

Use the following example, limiting to 50KBPS (50K Bytes Per Second).

server {
    listen 80;
    server_name localhost;

    limit_rate 50k

    # Omitted below
}

limit_rate_after

You have the option to limit bandwidth by initially transferring at high speed and then reducing the rate for the remainder.

Use the following to limit bandwidth after 500KB transfer. The limit_rate can be used to simulate a slow start; the limit_rate_after can be used to simulate a stall in the middle of the transfer.

server {
    listen 80;
    server_name localhost;

    limit_rate_after 500k;
    limit_rate 50k;

    # Omitted below
}

Setting timeout in URLSession

I was doing a simulation test of bandwidth limiting. I noticed that I had made a mistake in setting a timeout when communicating from a client macOS app.

Two types of timeout

The timeout setting code was as follows.

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

Since I slowed down the bandwidth as much as possible with Nginx, the download is now taking about 3 minutes. URLSession has two different timeouts set with the properties.

  • timeoutIntervalForRequest (Timeout before the response is returned)
  • timeoutIntervalForResource (Timeout for download completion)

If the property is set as in the code above, the download will be interrupted at 2 minutes, which would take 3 minutes to download. The correct thing to do is either not set timeoutIntervalForResource and use the default value or set it to a sufficiently long value. How many values are long enough will vary from app to app. In my case, I erased one line and changed timeoutIntervalForResource to the default value.

At the same time, it was good to see that it worked correctly when the download was aborted due to a timeout.

Also check when the network is disconnected

A misconfigured timeout is a use case where the application aborts the download. Conversely, it should also be confirmed that the network is interrupted in the middle of the download, and the download cannot be performed.

Error handling when disconnected in the middle of a session

Bandwidth limiting is effective for this as well. Limit bandwidth to create a situation where the download takes a sufficient amount of time. Then, when the download has made some progress, execute the following command to bring the server down.

% docker-compose down

Verify that the app correctly executes the error handling and gets out of the download process. In my case, I also combined limit_rate_after and proceeded through to about halfway, then executed the command when it slowed down.

Once you have confirmed that error handling is working correctly and has been aborted, leave Nginx stopped and reconnect the application. You can also confirm that error handling works correctly when the server is not running.

Error handling when a file does not exist

After confirming this point, we will also try a case where the file does not exist: the file output by Nginx running on Docker is a file in the content_home folder locally placed. Change the file name of the file in this folder to intentionally cause an HTTP 403 File Not Found.

It is OK if the application can confirm error handling when the file does not exist correctly.

Conclusion

Combining Docker and Nginx makes it easy to simulate various networking-related problems. For example, it is very convenient to create a bandwidth limitation in a local machine because it is very difficult to prepare in a slow environment.

Create an application that is resistant to network errors.

Authored Books

Let's share this post !

Author of this article

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

TOC