Nginx: difference between sessions, connections and requests

When using the HttpLimitZoneModule or HttpLimitReqModule you have to define a zone. According to the manual:
> When the zone size is 1M then it is possible to handle 32000 sessions with 32 bytes/session.
You can then limit the number of connections with limitconn and/or requests with limitreq.

What is the difference of or the relationships between sessions, connections and requests?

Sessions are IP-based. Can I assume that connections are software based? Like in visiting a website with 2 browsers. 1 IP thus one session but 2 connections. And that requests are the files loaded together with a webpage (js, csss, png, …)?

So one session can have multiple connections and one connection can have multiple requests, but not the other way around?

Do you need to define a limitzone and/or a limitreq_zone for each virtual host?

7 Replies

You can have multiple requests per connection. Not at the same time, of course, but rendering a web page is a fairly lengthy process.

Best way to "experience" this is to fire up Wireshark and hit a moderately complex (HTTP) page with an empty cache. You'll see a slew of connections, and within each connection, you'll likely see a number of objects requested in series. You can sometimes see this a little bit with your browser's waterfall display, but it seems better at showing parallel connections than serial requests within a connection.

To summarize:

  • A session is… whatever they define a session to be. Sessions don't exist at HTTP or below. Resource usage for each session depends on what a session is.

  • A connection is a TCP-based reliable pipeline between two endpoints. Each connection requires keeping track of both endpoint addresses/ports, sequence numbers, and which packets are unacknowledged or presumed missing. There may be zero or more connections per session.

  • A request is a HTTP request for a given resource with a particular method. There may be zero or more requests per session. (Yes, web browsers can and do open connections without sending a request.)

  • A "page view", i.e. the thing you do when you enter a URL and hit Enter, or click on a plain ol' hyperlink, is a collection of zero or more requests over a time period from the user's button push to the cessation of spinning by that little spinny thing, although more than one "page view" could occur without the spinning having stopped, and things could happen later on that cause it to start spinning again and could very well be considered part of the same page view. Like sessions, page views don't exist at HTTP or below.

If sessions are IP-based, then a connection would necessarily only belong to one session, as would a request. A "page view," however, may span multiple connections and thus multiple IP addresses. Also, an IP-based session could include traffic from more than one user.

(This is why session cookies were invented.)

EDIT: hybinet stole my thunder, probably by getting a head start.

I'm not terribly familiar with those modules, but from those descriptions it seems that limitconn and limitreq can be used to limit simultaneous downloads, total number of downloads, etc. from the same IP address.

You don't need 2 browsers to open more than one connection to the same server. Most modern browsers open several connections at once, and download different files (images, css, js) at the same time to speed up the page load. Each connection can handle multiple requests (downloads), too. You should take that into account when using limit_conn. If you set it too low or attach it to the wrong location, the whole website will appear to be unresponsive while the user is downloading a video file for example.

So what is than the difference between connections and requests?

@pannix:

So what is than the difference between connections and requests?
A browser can open one connection to a server, and send multiple requests through the same connection. Each request usually corresponds to one downloaded file. In other words, browsers don't need to open a new connection for each file they download from your server. This saves time, because opening a new TCP connection takes a significant amount of time.

But in order to download multiple files through the same connection, the files must be downloaded one after another. The HTTP protocol doesn't allow several files to be downloaded simultaneously through the same connection. That's why browsers also open several connections to the same server. That way, they can download several files at the same time (using multiple connections) AND download more files once the initial downloads complete (using multiple requests per connection).

Since most web pages are made of dozens of files (images, css, js), this makes web pages load faster overall.

Compare:

  • Opening 25 connections, one after another, and downloading 1 file through each connection (slowest)

  • Opening 1 connection and downloading 25 files through it (slow)

  • Opening 5 connections and downloading 5 files through each connection (fast)

  • Opening 25 connections and downloading 1 file through each connection (waste of resources)

So if you limit the number of connections or the number of requests too much, you will slow down your page load speeds.

Thanks hoopycat & hybinet.

Gonna give wireshark a try.

The main reason for limiting connections/request is that while I was doing performance testing using ab, autobench and httperf I saw that you could bring a server on its knees with that. Although compared to online available charts (for ab & autobench), my Linode512 did fairly well. All it takes is one punk to bring your server on it's knees or make you receive Linode alerts that your exceeding your outbound traffic rate (averaging 7.39 MB/s for the last 2 hours will make you receive those emails). I mainly want to prevent that.

Is there any rule of thumb for the number of files in a pageview (wordpress) to the number of connections to allow? Maybe limiting it to 3 connections as I have seen in some examples could reduce page load and 25 might be overdoing it?

Gonna experiment some more to see the influence of the number of workerconnections, workerprocesses and php-fpm children and spare_servers on performance.

You can't protect yourself from a really good attack. Large corporate sites are taken down to DDOS attacks and they have full time staff. So don't stress and be happy.

Now on the other hand… if I were to do this to your site:

ab -n 1000000 -k http://yoursite.com

is your site going to keep trying to answer 1000000 requests on one connection from one IP as fast as it can using all possible resources? You can set nginx limit_req to 20 requests per second so that no legitimate user could possibly hit your cap. Modern browsers only send 2-8 parallel requests simultaneously for resources and then wait til those resources are finished downloading and then request 2-8 more. So depending on your latency with a particular client and the sizes of the files and transfer speed, that's probably only a max of 10 requests per second. Unless of course you're a mile from the server requesting 0 byte files.

On the other hand, as we mentioned, modern browsers download 2-8 files at a time. The number has been going up. Especially if we use subdomains to increase the speed our page renders. That means that your server is opening 2-8 connections to a client at once. If I do this to your site:

ab -n 1000000 -k -c 1000 http://yoursite.com

is your server going to allow me to open 1000 connections to your server? nginx happens to be really good and handles thousands of connections quite well with low resources, but it still takes resources. If you're using apache2-prefork with phpmod then each connection is going to use more resources. Again though, ask yourself the question, what is the maximum number of open connections a legitimate user might open with my site and then pad it. A limitconn of 20 or 30 is pretty safe. (see https://calomel.org/nginx.html for their explanation of why they set this at 5) And one guy with ab won't be able to totally mess with your site.

A special case might be if a particular page will take huge resources. For example your site has a search system that uses mysql. Searching your whole site on mysql is pretty taxing, since mysql sucks at search. (see apache solr) That's much different resource-wise than downloading your css and js files. So you might want to limit_req to 0.333 requests per second but only on /search. One IP can make 1 search every 3 seconds, or they get a 503 page. (Hopefully a nice customized pretty and apologetic 503 page.) You can do that within nginx location definitions.

Both of those directives involve coming from 1 IP. If you piss off some guy with a botnet of thousands of nodes and each hits your server for the maximum number of connections coming from thousands of IPs, you're still going to be screwed.

Set them up, give them nice generous limits. Get some sleep.

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct