How to limit bandwidth with Nginx

Sometimes you want to limit the network speed when connecting with HTTP from an application you are making. For example, when connecting from a very slow network or from a foreign country with poor infrastructure, you want to make sure that the connection works correctly.

If your web server is running Nginx, you can limit the network bandwidth in the Nginx settings to reduce 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 can limit bandwidth by transferring quickly at first and slowing down the rest.

Use the following to limit bandwidth after 500KB transfer: limit_rate can be used to simulate a slow start; 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 and 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 I could with Nginx, the download is now taking about 3 minutes. URLSession has two different timeouts, which are set in the properties.

  • timeoutIntervalForRequest (Timeout before 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 when it 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. 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 all the way 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 from 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 a variety of networking-related problems. It is very convenient to be able to create a bandwidth limitation in a local machine, because it is very difficult to prepare a slow environment.

Create an application that is resistant to network errors.

Let's share this post !

Author of this article

Akira Hayashiのアバター Akira Hayashi Representative, Software Engineer

I am an application developer loves programming. This blog is a tech blog, its articles are learning notes. In my work, I mainly focus on desktop and mobile application development, but I also write technical books and teach seminars. The websites of my work and books are here -> RK Kaihatsu.

TOC