Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long Polling with Ajax and PHP - Apache freezes

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.

like image 232
ex3v Avatar asked Apr 18 '13 10:04

ex3v


2 Answers

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!

like image 169
ex3v Avatar answered Oct 13 '22 02:10

ex3v


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 ;)

like image 3
Joseph Orlando Avatar answered Oct 13 '22 01:10

Joseph Orlando