Long Polling with Ajax and PHP - Apache freezes
Asked Answered
C

2

5

We try to implement long-polling based notification service in our company's ERP. Similar to Facebook notifications.

Technologies used:

  • PHP with timeout set to 60 seconds and 1 second sleep in each iteration of loop.
  • jQuery for AJAX handling.
  • Apache as web server.

After nearly month of coding, we went to production. Few minutes after deployment we had to rollback everything. It turned out that our server (8 cores) couldn't handle long requests from 20 employees, using ~5 browser tabs each. For example: User opened 3 tabs with our ERP, with one long-polling AJAX on each tab. Opening 4th tab is impossible - it hangs until one of previous 3 is killed (and therefore AJAX is stopped).

'Apache limitations', we thought. So we went googling. I found some info about Apache's MPM modules and configs, so I gave it a try. Our server use prefork MPM, as apachectl -l shown us. So I changed few lines in config to look something like this:

<IfModule mpm_prefork_module>
    StartServers          1
    MinSpareServers       16
    MaxSpareServers      32
    ServerLimit          50%
    MaxClients          150
    MaxClients           50%
    MaxRequestsPerChild   0
</IfModule>

Funny thing is, it works on my local machine with similar config. On server, it looks like Apache ignores config, because with MinSpareServers set to 16, it lauches 8 after restart. Whe have no idea what to do.

Ciliary answered 18/4, 2013 at 10:38 Comment(3)
Although not that likely, but there's limit on maximum persistent connection per server implemented on various browsers. You may want to test if the 4th tab will hang whatever number of employees are connected.Gutshall
Don't sleep the pages that locks the apache/php thread. You'd need to increase your apache workers etc and threads all that crap. In my CRM platform I do it with a simple text file look up per userid. Timestamp of last check vs timestamp of now if difference > 60 then do poll else do nothing. Set script to run every second.Hideaway
Try using websocks for that, over python .Clow
C
6

Passerby in first comment of previous post gave me good direction to check out if we hit max browser connections to one server.

As it turns out, each browser has those limit and you can't change them (as far as I know). We made a workaround to make it work.

Let's assume that I was getting AJAX data from

http://domain.com/ajax

To avoid hitting max browser connections, each long-polling AJAX connects to random subdomain, like:

http://31289.domain.com/ajax
http://43289.domain.com/ajax

and so on. There's a wildcard on a DNS server pointing from *.domain.com to domain.com, and subdomain is unique random number, generated by JS on each tab.

For more information, check out this thread.

There's been also some problems with AJAX Same Origin Security, but we managed to work it out, using appropriate headers on both JS and PHP sides.

If you want to know more about headers, check it out here on StackOverflow, and here on Mozilla Developer's page. Thanks!

Ciliary answered 19/4, 2013 at 7:28 Comment(1)
Are you saying aside the browser limit on connection, long polling is working fine on your apache server?Oblong
E
3

I have successfully implemented a LAMP setup with long polling. Two things to keep in mind, the php internal execution clock for linux is not altered or incremented by the 'usleep()' function. Therefore, setting the maximum execution time would only be needed for rare edge cases where obtaining the data takes longer than normal, or possibly for a windows setup. In addition, with long polling bare in mind that once you go over 20+ seconds, you are vulnerable to having browser timeouts occur.

Secondly, you will need to verify that your sessions aren't locking up (if sessions are being used).

Apache really shouldn't have any issue with what you are looking to do. Though, I will admit that webservers like nginx or an ajax-specific webserver may handle the concurrent connections better. If you could post your code for the ajax handler, we might be able to figure out where the problem is.

Utilizing subdomains, or as other threads have suggested -- multiple webservers on separate ports, remember that you may encounter JavaScript domain security issues.

I say, don't change apache config until you encounter an issue and have exhausted all other options; be careful with the PHP sessions, and make sure AJAX is waiting for a response, before sending another request ;)

Expedition answered 4/9, 2013 at 23:27 Comment(1)
While developing my notifications service I've tried many things. I also did something similar to what you proposed. Turns out whole idea fails when you try to support hundreds (or more) of connections at one time - you will just kill the server. I found a better solution though - Node.js with Socket.io as connection protocol. I know it requires some time to learn new technology, but it's worth it. It's worth it so much, that I've spend half of a year describing it in my Master Of Computer Science Thesis :) You should try it! Have fun!Ciliary

© 2022 - 2024 — McMap. All rights reserved.