-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keep-alive connections keep threads occupied infinitely #368
Comments
I think that Hyper must have something like KeepAliveTimeout in Apache. |
@andor44 I think that you may try to use nginx as a reverse proxy in front of Rustless/Huper to work-around the issue. Nginx could handle a big amount of connections without any issues and it has usable keep-alive settings. I think nginx is required for blocking servers anyway. |
@s-panferov I'll give that a shot. Here's the relevant part of the code. I'm not sure how deep down the rabbit hole this should be handled though. Probably as deep as this though I'm not sure how easily you can specify a timeout in the current Hyper architecture. |
The current IO doesn't provide a way to specify a timeout, which makes this harder. |
@andor44 have you tried to use a reverse proxy already? Has it helped? |
Yes. I am using nginx, and it uses HTTP 1.0 for reverse proxying requests, which doesn't have keep-alive as part of the spec, and it works perfectly. |
When will this bug be fixed? timeout should be an urgent feature. |
Timeouts won't be supported by TcpStreams until Rust 1.1, which would be In the mean time, I suggest putting nginx in front of your server, which On Sat, Apr 18, 2015, 10:24 AM Young Woo [email protected] wrote:
|
All right, thanks. But what about the client? Are there any good ways to On 2015年4月19日周日 上午2:15 Sean McArthur [email protected] wrote:
|
This error is still apparent in v0.6. My server hangs sometimes and it is quite frequent, I know it's not my code because not even the Handler's I've switched to rust-http and my code works fine. This really needs to get fixed IMHO as this library does have a nice API. |
Is this issue the place to follow for updates on this bug? |
To overcome this bug: hyperium/hyper#368
FYI, for those who need a workaround for this issue while we wait for async:
This way you can still support keep-alive most of the time, but when things get really busy, your server won't "hang". I've tested this and it works well. |
I'm thinking of turning keep-alive off by default for hyper 0.6 servers, which is probably the right thing to do, and let people who have a solution turn it back on. However, that's a logical breaking change, even though code will continue to compile... Thinking of adding something like this to keep the current behavior: Server::http(addr).unwrap().keep_alive().listen(handler) |
No solution for the problem itself? |
@juanibiapina the best solution is asyncio, tracked in #395. With synchronous IO, your only options are 1) set a timeout, which can be done currently, but still means the connection could block to the full length of the timeout, or 2) don't try to read on kept-alive connections. |
It feels a bit like sweeping it under the rug, but it's about as good as any other workaround. It may become a gotcha in its own way, though. Probably less obvious, but still... |
In iron at least I can attempt to implement the |
I'm going to try the way Apache does it: if you want keep-alive, a timeout will be used when trying to read on the kept-alive connection. This is really the only thing that is possible on blocking sockets. server.keep_alive(Duration::from_secs(5));
server.listen(...) Of course, this will require activating the |
I concur. I think the number of people who find hyper "locks up" is sufficiently high to justify disabling keep-alive by default for 0.6. It could be considered a DoS security vulnerability as it currently stands. The performance benefit of keep-alive can't really be achieved under blocking I/O anyhow without an enormous number of threads, or being under very low load. |
You could make a new release without the keep-alive, like you suggested, since this is still 0.x. Then you could implement the timeout when 1.4 comes out. As a user of the lib, I don't mind because I would be actively upgrading a not 1.0 dependency. |
@mikedilger you beat me to it xD |
Doing the connection counting trick will at least let users choose a balance, but tune it the wrong way and your thread pool may be filled up with idle favicon connections and your server basically reverts to single thread mode. I implemented it in Rusful and it prevents lock-ups, but not much more. Disabling |
A co-worker of mine wrote a tool to benchmark hyper-based servers, and which is annoying in just the right ways to inspect keep-alive related behaviour: http://github.com/alanstockwell/hyperspank (shout out to @alanstockwell) |
Server keep-alive is now **off** by default. In order to turn it on, the `keep_alive` method must be called on the `Server` object. Closes #368
Proposed fix is in #661 |
Server keep-alive is now **off** by default. In order to turn it on, the `keep_alive` method must be called on the `Server` object. Closes #368
On IRC, @reem pointed out to me that it's possible to do a little more in this area. With the timeout solution, a scenario is still possible that all the threads are used to each deal with a connection that is using keep-alive, and even though they aren't blocked by a stalled connection, while they are active no other connections can be handled. I'm not sure if this scenario should still be considered part of this bug, or more of a general improvement. Also, once non-blocking io is merged, this issue goes away automatically. A solution here would be to have an acceptor thread, and a work queue. The acceptor would push all TcpStreams into the queue, and the workers would process 1 request/response pair. If keep-alive is true, that Stream could be placed at the back of the work queue. |
As discussed in rustless/rustless#35, suggested by @reem, Hyper seems to be too "literal" about keep-alive, keeping threads in a keep-alive loop, essentially DDoSing a Hyper server. My temporary workaround is to use many threads to delay running out of threads for the time being.
The text was updated successfully, but these errors were encountered: