High traffic connection between Php and Redis - php

I have backend on php, that works with Redis.
But when requests increased and they more than 2000 request per sec I receive an error:
99 - Cannot assign requested address
All sockets in TIME_WAIT.
Connecting example:
$this->_socket = #stream_socket_client(
'tcp://' . $this->hostname . ':' . $this->port,
$errorNumber,
$errorDescription,
ini_get('default_socket_timeout'),
STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT
);
I find solution: http://redis4you.com/articles.php?id=012&name=redis
But /proc/sys/net/ipv4/tcp_tw_recycle I can't set in 1.
Don't want to loss packets on the network between application and redis.
Php on new request from API create a new socket.
Any ideas?

I don't know your whole design, but here something you could do :
Create a PHP page that always run (with a while(true) loop)
This page would wait for content from your initial page (where the socket code was before)
Using the pipelining technique, you would send all requests using the same socket.
Only thing missing is how to pass data from the initial page to this new page.
For that last part I see multiple solutions (not sure if they all work though) :
Using APC to store data from initial page and still use it to get it from the new one.
Create a SESSION in the new page which would than have two modes : Processing, Submitting. You should then call this page using your local server inside the initial page.
In both solutions, one instance of this new page shall be executed locally so the 'Processing/Waiting' is activated.

Fixed problem.
Use tcp reuce and time waite for socket sets in 10 seconds. Php work with socket in persistent mode
STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT
So even in 2 000 request per second it use not more then 61 sockets.

Related

PHP NATS Client disconnects after some idle time

I have been using this library repejota/phpnats for developing a NATS Client that can subscribe to a particular channel. But after connecting, receiving few messages and having some 30 secs idle time, it gets disconnect itself without any interruption. However my Node.js client is working good with the same NATS server.
Here is how I am subscribing...
$c->subscribe(
'foo',
function ($message) {
echo $message->getBody();
}
);
$c->wait();
Any suggestions/help???
Thanks!
Was this just the default PHP timeout killing it off?
Maybe something like this:
ini_set('max_execution_time', 180); // gives about 3 minutes for example
By default, PHP scripts can't live forever as PHP shall be rather considered stateless. This is by design and default life span is 30 seconds (hosters usually extend that to 180 secs but that's irrelevant really). You can extend that time yourself by setting max_execution_time to any value (with 0 meaning "forever") but that's not recommended unless you know you want that. If not, then commonly used approach is to make the script invoke itself (ie via GET request) often passing some params to let invoked script resume where caller finished.
$options = new ConnectionOptions();
$options->setHost('127.0.0.1')->setPort(4222);
$client = new Connection($options);
$client->connect(-1);
You need to set connect parameters as -1

Use a socket on several pages

I am working on a php application that is sending data through a socket. On my main page I establish the connexion with the client, and I would like to send data from another page of the web app.. but I don't know how to do that.
I am currently trying to use $_SESSION variables [close your eyes this is not pretty]
main page :
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
$result = socket_bind($socket, $host, $port);
$result = socket_listen($socket, 3);
$_SESSION['mySocket'] = socket_accept($socket) ;
socket_read($_SESSION['mySocket'], 1024);
second page :
socket_write($_SESSION['mySocket'], "myText", 6) ;
But it does not work because $_SESSION['mySocket'] is not a ressource anymore on the second page (just 0)... If I use the write command on the main page it works fine, but not on another page. Do you have any idea why ? Is there a cleaner way to do that than using $_SESSION variables (surely there is) ?
EDIT : maybe my real question is : when does a socket connexion close (if I didn't ask for it) ?
Sockets are really only for CLI programming, and there you don't have a $_SESSION object available.
Additionally, it doesn't make sense that you will want to share the socket in the first place, because the socket is a means of IPC. If you pass the socket handle between scripts, then what use is the socket anyway?
If you are trying to communicate between one script and the other, you will want to have the first script listen on a socket (as you did), and then create an infinite loop where the script listens for requests.
In the second script, you connect to the same socket, but don't listen to it.
So I guess what you actually want to do, is to have a third file config.php:
And in both scripts use
You will want to expand this later to make the $host configurable independently, if you want to communicate between computers on a network.
All in all, this is quite advanced programming and you will need to read a lot more about sockets. If I haven't scared you off enough, you could read up on some example code as it is shown in the PHP manual.

Updating page info using jQuery from a PHP script that performs an external connection

I have a PHP script that performs a connection to my other server using file_get_contents, and then retrieves and displays the data.
//authorize connection to the ext. server
$xml_data=file_get_contents("http://server.com/connectioncounts");
$doc = new DOMDocument();
$doc->loadXML($xml_data);
//variables to check for name / connection count
$wmsast = $doc->getElementsByTagName('Name');
$wmsasct = $wmsast->length;
//start the loop that fetches and displays each name
for ($sidx = 0; $sidx < $wmsasct; $sidx++) {
$strname = $wmsast->item($sidx)->getElementsByTagName("WhoIs")->item(0)->nodeValue;
$strctot = $wmsast->item($sidx)->getElementsByTagName("Sessions")->item(0)->nodeValue;
/**************************************
Display only one instance of their name.
strpos will check to see if the string contains a _ character
**************************************/
if (strpos($strname, '_') !== FALSE){
//null. ignoring any duplicates
}
else {
//Leftovers. This section contains the names that are only the BASE (no _jibberish, etc)
echo $sidx . " <b>Name: </b>" . $strname . " Sessions: " . $strctot . "<br />";
}//end display base check
}//end name loop
From the client side, I'm calling on this script using jQuery load () and to execute using mousemove().
$(document).mousemove(function(event){
$('.xmlData').load('./connectioncounts.php').fadeIn(1000);
});
And I've also experimented with set interval which works just as well:
var auto_refresh = setInterval(
function ()
{
$('.xmlData').load('./connectioncounts.php').fadeIn("slow");
}, 1000); //refresh, 1000 milli = 1 second
It all works and the contents appear in "real time", but I can already notice an effect on performance and it's just me using it.
I'm trying to come up with a better solution but falling short. The problem with what I have now is that each client would be forcing the script to initiate a new connection to the other server, so I need a solution that will consistently keep the information updated without involving the clients making a new connection directly.
One idea I had was to use a cron job that executes the script, and modify the PHP to log the contents. Then I could simply get the contents of that cache from the client side. This would mean that there is only one connection being made instead of forcing a new connection every time a client wants the data.
The only problem is that the cron would have to be run frequently, like every few seconds. I've read about people running cron this much before, but every instance I've come across isn't making an external connection each time as well.
Is there any option for me other than cron to achieve this or in your experience is that good enough?
How about this:
When the first client reads your data, you retrieve them from the remote server and cache them together with a timestamp.
When the next clients read the same data, you check how old the contents of the cache is and only if it's older than 2 seconds (or whatever) you access the remote server again.
make yourself familiar with APC as a global storage. Once you have fetched the file, store it in the APC cache and set a timeout. You only need to connect to the remote server, once a page is not in the cache or outdated.
Mousemove: are you sure? That generates gazllions of parallel requests unless you set a semaphore clientside to not issue any AJAX queries anymore.

PHP - set time limit effectively

I have a simple script that makes redirection to mobile version of a website if it finds that user is browsing on mobile phone. It uses Tera-WURFL webservice to acomplish that and it will be placed on other hosting than Tera-WURFL itself. I want to protect it, in case of Tera-WURFL hosting downtime. In other words, if my script takes more than a second to run, then stop executing it and just redirect to regular website. How to do it effectively (so that the CPU would not be overly burdened by the script)?
EDIT: It looks that TeraWurflRemoteClient class have a timeout property. Read below. Now I need to find how to include it in my script, so that it would redirect to regular website in case of this timeout.
Here is the script:
// Instantiate a new TeraWurflRemoteClient object
$wurflObj = new TeraWurflRemoteClient('http://my-Tera-WURFL-install.pl/webservicep.php');
// Define which capabilities you want to test for. Full list: http://wurfl.sourceforge.net/help_doc.php#product_info
$capabilities = array("product_info");
// Define the response format (XML or JSON)
$data_format = TeraWurflRemoteClient::$FORMAT_JSON;
// Call the remote service (the first parameter is the User Agent - leave it as null to let TeraWurflRemoteClient find the user agent from the server global variable)
$wurflObj->getCapabilitiesFromAgent(null, $capabilities, $data_format);
// Use the results to serve the appropriate interface
if ($wurflObj->getDeviceCapability("is_tablet") || !$wurflObj->getDeviceCapability("is_wireless_device") || $_GET["ver"]=="desktop") {
header('Location: http://website.pl/'); //default index file
} else {
header('Location: http://m.website.pl/'); //where to go
}
?>
And here is source of TeraWurflRemoteClient.php that is being included. It has optional timeout argument as mentioned in documentation:
// The timeout in seconds to wait for the server to respond before giving up
$timeout = 1;
TeraWurflRemoteClient class have a timeout property. And it is 1 second by default, as I see in documentation.
So, this script won't be executed longer than a second.
Try achieving this by setting a very short timeout on the HTTP request to TeraWurfl inside their class, so that if the response doesn't come back in like 2-3 secs, consider the check to be false and show the full website.
The place to look for setting a shorter timeout might vary depending on the transport you use to make your HTTP request. Like in Curl you can set the timeout for the HTTP request.
After this do reset your HTTP request timeout back to what it was so that you don't affect any other code.
Also I found this while researching on it, you might want to give it a read, though I would say stay away from forking unless you are very well aware of how things work.
And just now Adelf posted that TeraWurflRemoteClient class has a timeout of 1 sec by default, so that solves your problem but I will post my answer anyway.

Strange timeout behaviour using php soap client

I'm trying to make a proxy-like page that forwards an AJAX request to a SOAP server.
The browser sends 2 requests to the same page (i.e. server.php with different query string) every 10 seconds.
The server makes a soap call to the soap server depending on the query string.
All is working fine.
Then I put a sleep (40 secs) in the soap server to simulate a slow response and I also put a timeout on the caller to abort the call after some seconds.
server.php: Pseudo code:
$timeout = 10;
ini_set("default_socket_timeout", $timeout);
$id = $_GET['id'];
$wsdl= 'http://soapserver/wsdl'
$client = new SoapClient($wsdl,array('connection_timeout'=> $timeout));
print($client->getQuote($id));
If the browser sends an ajax request to http://myserver/server.php?id=IBM
the request stops after the timeout I set.
If I try to make a second call before the first stops, the second one doesn't not respect timeout.
i.e.
Request:
GET http://myserver/server.php?id=IBM
and after 1 second
GET http://myserver/server.php?id=AAP
Response:
after 10 seconds:
No data
after 20 seconds:
No data
I also tried to not use PHP SOAP and use curl instead but I got the same results.
I also tried to open 3 tabs on my browser and call:
http://myserver/server.php?id=IBM
http://myserver/server.php?id=AAP
http://myserver/server.php?id=MSX
The first one stops after 10 seconds, the second after 20 seconds and the third after 30 seconds.
Is this a normal behaviour or I miss something ?
Thanks in advance
You are probably starting sessions, and session_start() blocks a second call to it until the other request has 'freed' the session (in other words: has finished and will not write any data to the session anymore). For time consuming requests, don't start a session if you don't need one, and if you DO need one, get all the data that you need and then call session_write_close() BEFORE you doing the time-consuming thing. If you need to write to the session afterwards, just call session_start() again.

Categories