Forum Moderators: coopster
The scenario is this: I am trying to write a php socket server to replace a traditional PHP script run by an httpd server. What it does it accept a small request from the client and then do some simple SQL work and return a regular http request.
Normally, I would have just kept the old code and let apache deal with the incoming requests, but the problem is that the simple SQL work (using mySQL) requires an UPDATE query. Even when using an InnoDB that only locks rows, this causes problems for other threads trying to access the same table and creates huge query queues (700+ connections) that cause the mySQL server to choke (and Apache for that matter, managing all the PHP threads).
So, the solution was to simply make a socket server that handles all of the requests in a single threaded environment (since, due to the UPDATE queries, which effectively locked the tables, it was already 'singlethreaded' in a way) I'd worked with php sockets before, so I have a general idea of what I was doing - but never at this scale (the socket server receives around 50 requests/sec). While the script execution time, when it actually receives the request properly, is excellent (<5ms), every few seconds a connection comes along that simply freezes on socket_read() for anywhere between 500 ms to 30 seconds. Obviously, this has something to do with the connection on the other end disconnecting before transmitting all of its data, but socket_read() has no built in timeout function (that I am aware of) to deal with this problem, and at 50 requests a second, a 10 second lockup suddenly means there's 500 connections waiting in queue. Eventually the backlog fills up and begins to reject connections.
Any insight as to how to force a (short) timeout on socket_read()? If this is simply not possible, I will be looking into using fork() to overcome this problem, but I would prefer not, as thread chaos is what inspired me to create this socket server in the first place. :)
Here's the basic code:
if(($socket = socket_create(AF_INET, SOCK_STREAM, 0)) < 0)
die("Socket could not be created!");
if(socket_bind($socket, $address, $port) < 0)
die("Socket could not bind on port $port @ $address!");
if(@socket_listen($socket, 100)< 0)
die("Socket cannot listen on $port!");
while(1)
{$request_headers = "";
if(($request = socket_accept($socket)) > 0)
{
$start = gettimeofday();
socket_getpeername($request, $addr);
while(($buf = socket_read($request, 2048))!== false)
{
$request_headers .= $buf;
if(preg_match("'\r\n\r\n$'s", $request_headers)) // only need to get headers
break;
}
// do stuff here
socket_shutdown($request);
socket_close($request);
}
}
Thanks in advance,
-ethernal