One of my front-end developer co-workers asked for my help because of the browser not sending HTTPS requests asynchronously. At least that is what he thought at first.
By opening up the Firefox networking tab, I realized that the requests get sent asynchronously, but for some reason, only six HTTPS requests are allowed to be sent parallel.
I assume this is a technical limit of the HTTPS protocol, though I do not know the cause.
I searched for the cause on the web, but I have not been able to find it so far.
In the following picture, the red parts of the lines mark the duration spent being blocked by another request:
My understanding is that this is a courtesy to the server you're connecting to. You wouldn't want to overload a server and prevent others from simultaneously connecting to it.
Depending on the browser, the limit changes as well.
See also: Max parallel http connections in a browser?
Related
I've been googling around and I cannot seem to find a straight answer to this question, and some people offer contradictory answers.
Most browsers have a 6 connection limit for each domain. So for example, if your website is example.com and it initializes a persistent Server Sent Event connection on page load, then the end user can open that tab five more times, but the sixth tab won't load at all, because the 6 persistent TCP connection has been reached for that domain.
Now, I see some people saying that this is just a perennial problem with SSE, and the only alternative is hacky workarounds involving detecting this connection limit and then either closing the connections in hidden tabs or closing those connections in those tabs and switching to long polling.
However, some people claim that HTTP2 solves this with multiplexing, such that you can have as many open tabs of that website as you'd like, as all the tabs multiplex onto the same TCP connection. I cannot find a primary source for this claim, nor anyone with significant authority making it either.
So, is it true? Does HTTP2 multiplexing solve the issue of the common 6 connection limit for website domains? Or is one basically required to instead use websockets if they would like to support many open tabs to their site?
I have implemented HTTP/2 in Jetty.
As explained in this answer, with HTTP/2 the max number of concurrent requests that a browser can make to the server is largely increased - not infinite but increased from 6-8 to about 100.
So yes, multiplexing solves this issue in practice (unless you open more than 100 or so tabs).
Note that this value is configured by servers, so it's possible that a server sends to the client a configuration with max number of concurrent requests set to a small number, but in practice servers have settled on a number around 100.
Having said that, you want to also read this other answer for a discussion about SSE vs WebSocket.
The limit is applied in the browser (not server-side), and varies per browser.
At least it did as of http/1.1. I've been unable to find any configuration specific to http/2, so I think we have to assume the limits are still there. I would assume they've been kept to prevent abuse, or accidental DoS attacks.
https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Mozilla_networking_preferences
See network.http.max-persistent-connections-per-server. (You can also see it in about:config.)
Here are all the settings I see (in Firefox) filtering for "connections":
I wonder if SSE is governed by http.max-connections or the websocket.max-connections? (Ignoring any per-domain limit, for the moment.)
You could also just try it, of course (there were example scripts in my above-linked question). But unless you control the configuration of all clients, you have to assume some people will be running with a limit of 6.
I had the following issue on a system that I supported ~7 years ago. We never got to the bottom of it, and focus shifted onto other issues. I was recently reminded of it, and wondered if anyone would know what was going on. But alas I'll be a little short on details. Sorry.
The Setup
I had a farm of web servers sitting behind a load balancer. The servers were hosting a system that would receive HTTP requests (XML &/or SOAP) from clients, then for each one kick-off a bunch of further HTTP requests to 3rd-party-suppliers, wait for the suppliers' responses, process and combine the results and respond to the client's request.
Think insurance comparison, but as Business-To-Business XML service.
The whole processing would take 5s of seconds, from receiving the initial client request to them sending back a response to that original HTTP request, and the server would be processing 10s or 100s of requests in parallel (i.e. at any given point, a given webserver would have many client Requests that had come in, and been logged, but not yet been responded to.)
We had detailed logging which record the reciept of the requests, including origin IP and which server was processing the request, and record when a response was sent.
All client requests were sent to a single IP address (well, URL), which was the address of the loadbalancer, which would then forward requests to the webservers, which weren't individually accessible to the internet (they didn't have public IP addresses).
Our load balancer would allow us to take individual web-servers out of rotation, for maintenance.
When we did that we could watch the DB logs, and see new requests stop coming in, and the existing request gradually get completed, until there were now outstanding requests and the server was idle.
The problem
We found that sometimes, when we took a server out of rotation ... it wouldn't entirely stop receiving requests. You could see the large bulk of request suddenly stop coming in, but it would still receive a trickle of fresh requests (I don't know ... maybe 0.1% of normal load, maybe less?). I think the longest we left it going was maybe ... 10 minutes?
Notably we realised that all of those requests were coming from a single client/IP address (I don't remember which).
I forget whether other (still-in-rotation) webservers were still receiving requests from this client, but I think they were?
If we rebooted the webserver, no further requests would come in after restarting.
Web stack was Windows, IIS, ASP.NET; pretty old school even at the time. All servers individually owned and configured.
What was happening?
We vaguely waved our hands and asserted that the client's integration with us was "holding an HTTP tunnel open and sending multiple requests through it", rather than sending each request separately, and thus was maintaining that tunnel even after the LB stopped sending new requests to that server. But that was BS-waffle, and since we never needed to actually understand what was going on, we ignored it and moved on with our lives :)
But I'd still like to know what we were seeing, if anyone can diagnose it from that description.
We vaguely waved our hands and asserted that the client's integration with us was "holding an HTTP tunnel open and sending multiple requests through it", rather than sending each request separately, and thus was maintaining that tunnel even after the LB stopped sending new requests to that server.
That sounds like a good explanation.
Normally, a LB will refuse new connections to a removed server, but will allow open connections to live on until they naturally close. This is known as "connection draining" or "graceful shutdown".
If one of your clients had HTTP keepalive on, and was holding a TCP connection open and sending HTTP requests through it for a long time, it would give the symptoms you describe.
Most LBs will have a configuration knob for how long to wait for connections to close before force-closing them during this "connection draining" time. You can set a timeout here to avoid this scenario if it is a problem for you.
The HTTP connection handling behaviour of clients will vary at the client's discretion, to a large extent. Perhaps most of your clients were of one type (say, web browsers) and weren't holding open a single connection for 10 mins, but perhaps one client was different (say, a programmatic HTTP API client)?
Further reading about "connection draining" on AWS Load Balancers here (the exact details will vary by LB vendor): https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/config-conn-drain.html
Further reading about HTTP keep alive here: https://en.wikipedia.org/wiki/HTTP_persistent_connection
I'm using uIP along with mbed TLS to run a simple web server on a microcontroller, and host an HTTPS page.
The problem is: my chip only has enough RAM to handle one TLS connection at a time, but Firefox (and Chrome) tries to open multiple connections at once to load the images on the page. If I tell uIP to abort or close additional connections, Firefox assumes an error and gives up loading the rest of the page.
I can tell uIP to limit the total connections to 1, and in that case it just drops new SYN packets if there is already a connection. This actually works, as Firefox will wait and try again until the page is fully loaded. I can't use this a solution however, since I do need to allow more than 1 TCP connection total in order to handle other types of connections (I can serve a regular HTTP web page at the same time, for example). If I could tell uIP to limit connections on a specific port to 1 at a time, that may solve the problem, but I don't think uIP has that capability. I also don't see a way to force uIP to drop certain packets.
I've looked all over the web, but I can't find any information on running a web server using just one TCP connection at a time.
Does anyone have any ideas?
Thanks!
Marlon
Just ignore the SSL connection until you are ready to process it. Browsers should tolerate this.
I am using Firefox, but I'd like to know how browsers decide this in general.
It seems that when I access the same URL twice in a short amount of time, my browser tries to re-use the TCP same connection for both requests (this is called keep-alive). However, when I access two different URLs (but still served by the same server), the browser sometimes decides to open up a new connection for each request. Obviously, the browser does not use a one-connection-per-URL policy.
I am asking this because I am trying to implement a web service that uses long polling. I can imagine that a user might want to open this service in multiple tabs on the same browser. However, with keep-alive, the second long poll request does not get sent until the first one completes (at least in Firefox), because the browser is trying to shove both of them into the same socket, which I did not expect when I designed the service. Even if the browser implements pipe-lining, there is no way that I can respond to the second request before I respond to the first, because HTTP mandates that I complete the responses in order.
When using HTTP/1.1, by default, the TCP connections are left open for reuse. This is for better performance than starting a new connection per request. The connection can be reused but the connection could close at any time by any of the parties.
You should read HTTP1.1 and the part on persistent connections.
In your case it is not even using HTTP pipelining (not broadly supported) because the next request is sent after the response of the first.
The browsers have a connection pool and reuse it per hostname. Generally speaking, a browser should not reuse a single connection for multiple hostnames, even if those hostnames actually resolve to the same IP address.
Most browsers allow the user to configure or override the number of persistent connections per server; most modern browsers default to six. If Firefox is truly blocking the second request because there's already a connection active, this is a bug in Firefox and should be filed in their bug tracking system. But if such a bug existed, I think you'd see many sites broken.
I am implementing a minimalistic web server application on a Microcontroller. When I have several images (or CSS/JS) on the web page, the browser creates several connections and fetches them. But the Microcontroller can not catch up with this. Is there a way to tell the browser to stop pipelining and fetch them one by one ?
Note :: "Connection: close" is already in place.
I think Connection:close is exactly the wrong message. When the browser creates multiple connections, it precisely does not pipeline its requests - so ISTM that you want the browser to pipeline, instead of creating parallel connections.
So one step towards that would be to use HTTP 1.1, and keep the connection open. The browser would then reuse the TCP connection for further requests. This should allow the microcontroller to catch up.
Now, the browser might still try to create additional, parallel connections. The best reaction to that is to not accept any of these connections. So limit the number of parallel connections that you are serving (independent of client), and only read new requests when you are done reading the previous ones. In doing so, prefer to read from established connections over accepting new connections.
If you have access to the TCP stack of the controller, you might be able to tell what host a connection comes from, so you can accept connections from other browsers while limiting the number of connections from the same browser (something that you cannot do in the regular socket API).
"Pipelining" is something else; it means that the user agent sends additional requests on the same connection although the first one didn't complete yet (see http://greenbytes.de/tech/webdav/rfc2616.html#pipelining).
"Connection: close" doesn't seem to be relevant; that being said: is there a reason why you don't want the connection reused?
With respect to your question: no, I don't think you can prevent clients from doing that. Did you try limiting the maximum number of open connections on your server?
Same problem... However, Firefox loads my site very fast unlike Opera. I have not invented anything better than rejecting connections at an initial stage: SYN. I'm just answering with RST flag. But probably it doesn't suit Opera.
My device supports only two simultaneous connections.