ipartola / hawkeye

An simple and fast USB webcam MJPEG streaming server.
Other
206 stars 28 forks source link

Multiple clients behind Apache proxy are not properly handled #9

Closed gkoh closed 7 years ago

gkoh commented 7 years ago

To provide a 'nice' path for my users, I put hawkeye behind an Apache reverse proxy, something like:

  ProxyPass http://localhost:8000
  ProxyPassReverse http://localhost:8000

Amongst other things this configuration also allowed me to use Apache supported credentials to authenticate users.

This worked fine during testing, but once it was opened to a few users, the video started to jump and lag. I noticed this in the hawkeye output log:

2017-01-10 10:21:36 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:36 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:38 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:38 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:38 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:40 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:40 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:40 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:42 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:42 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:42 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:44 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:44 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:44 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:46 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:46 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:46 INFO: Disconneting client from 127.0.0.1.
2017-01-10 10:21:48 INFO: Client connected from 127.0.0.1.
2017-01-10 10:21:48 INFO: Client at 127.0.0.1 requested GET /.
2017-01-10 10:21:48 INFO: Disconneting client from 127.0.0.1.

Lots and lots of connections and subsequent disconnections from 127.0.0.1. After digging around the code a bit, this doesn't look like a supported configuration due to hawkeye using the source IP of the client as the multiple client index.

Is it possible to change this client index to something besides the IP, perhaps a HTTP header that Apache can rewrite (eg. HTTP Host)

Regardless, thanks for this project.

ipartola commented 7 years ago

Thanks for reaching out. Hawkeye is built as a pretty rudimentary HTTP server, in that it disconnects the client after serving a static file. This is similar to how HTTP/1.0 worked and is often how reverse proxies are implemented. Since the main load on the Hawkeye server is usually from serving the streams, that's the code path that's optimized for continually and quickly serving the files.

The logs you are seeing show just the client getting the index.html, not the stream (GET / vs GET /streams/0, etc.) This means the issue is elsewhere.

Also, I am not sure where you are seeing that the clients are stored by IP. If you look at src/servers.c on line 174 in add_client, you'll see that it uses the standard socket number as the looking for the client's info. Thus multiple connections from the same client are fully supported.

Now, the actual problem you are seeing likely stems from apache doing some buffering on its side as well as apache's MPM module you are likely using. Since Hawkeye is stream-oriented, you want an event-based reverse proxy in front of it. You can use Apache's mpm_event. Personally, I prefer nginx. HAProxy is another fine choice.

To get better results, I would turn off all proxy and client buffering and let your reverse proxy just pass this stuff through as quickly as possible. I know I've gotten this configuration to work well with nginx before.

gkoh commented 7 years ago

Hi, thanks for being responsive.

I'll admit that I made some assumptions based on the log evidence I had and a cursory glance of the connection handling code. I apologise for that and defer to your knowledge of the code base.

My assumptions were made on the testing:

I will try disabling the proxy buffer to see if that fixes the problem, I had previously played with increasing the buffers and timeouts to no avail. I'll report back here once I get a chance to change the configuration.

gkoh commented 7 years ago

Apologies for taking a while to reply. You were correct, the Apache buffering appears to the be primary cause of the stuttering. That, coupled with some latency over a VPN caused the 'stream' of frames to chunk along. In the end, I was not able to completely disable the Apache proxy buffers, but reduced them to the minimum (512 bytes).

Thanks again for your input on this.