I managed to display the status of a server using FSOCKOPEN.
<?php
$ip = "0.0.0.0";
$port = "1337";
$online = '<font class="online" title="Server Online!">ONLINE</font>';
$offline = '<font class="offline" title="Server Offline!">OFFLINE</font>';
if (! $sock=#fsockopen($ip, $port, $num, $error, 0.25))
{echo "$offline";}
else
{echo "$online";}
?>
If the server with the IP "0.0.0.0" sends an error or does not respond within 1/4th of a second after the page has been loaded the Output will return OFFLINE, else it will return ONLINE.
The server status will update when the user refreshes the page.
Now I want to make it to update in real time (less than 7 seconds delay)
I know there is a very easy method to do that using <meta http-equiv=”refresh” content=”5" /> in the head tag.
But its pretty annoying that the COMPLETE page have to refresh and load everything again and its causing some unnecessary traffic.
Is there an easier way to do it?
You can use ajax and javascript in the client to open the PHP Script in the background and then update the element in the page with the result based on success/failure.
Take a look at jQuery and other library to do this easily.
Another option would be a simple <iframe /> to open another website as an element on the website.
Dont use ajax or any direct polling mechanism that will put more load on your server in terms of traffic.
What you can use is websockets to push data to a stream and read it in frontend
https://socket.io/
This can be done near realtime and your page will not be reuired to get updated every min.
Put PHP script in cron to run at required interval and end of it just push the output to sockets and catch them on frontend.
Related
I have a Wordpress website with a working order system. Now I want to make an Android app which displays every new order in a list view as soon as the order was made.
The last two days I thought about the following solutions:
Simple HTTP GET requests every 10 seconds
Websockets
MySQL binary log + Pusher Link
Server Sent Events
My thoughts (working with a LAMP stack):
Simple HTTP requests are obviously the most ineffective solution.
I figured out that websockets and Apache aren't working well together.
Feels quite hacky and I want to avoid any 3rd party service if I can.
4. Looks like this is the optimal way for me, however there are some problems with Apache/php and Server Sent Events from what I experienced.
I tried to implement a simple demo script but I don't understand why some of them are using an infinite while loop to keep the connection open and others don't.
Here is an example without a loop and here with an infinite loop, also here
In addition to that, when I tested the variant with the infinite loop, my whole page won't load because of that sleep() function. It looks like the whole server freezes whenever I use it.
Does anyone have an idea how to fix that? Or do you have other suggestions?
That is the code that causes trouble (copied from here) and added a missing curly bracket:
<?php
// make session read-only
session_start();
session_write_close();
// disable default disconnect checks
ignore_user_abort(true);
// set headers for stream
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Access-Control-Allow-Origin: *");
// Is this a new stream or an existing one?
$lastEventId = floatval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
if ($lastEventId == 0) {
$lastEventId = floatval(isset($_GET["lastEventId"]) ? $_GET["lastEventId"] : 0);
}
echo ":" . str_repeat(" ", 2048) . "\n"; // 2 kB padding for IE
echo "retry: 2000\n";
// start stream
while(true){
if(connection_aborted()){
exit();
}
else{
// here you will want to get the latest event id you have created on the server, but for now we will increment and force an update
$latestEventId = $lastEventId+1;
if($lastEventId < $latestEventId){
echo "id: " . $latestEventId . "\n";
echo "data: Howdy (".$latestEventId.") \n\n";
$lastEventId = $latestEventId;
ob_flush();
flush();
}
else{
// no new data to send
echo ": heartbeat\n\n";
ob_flush();
flush();
}
}
// 2 second sleep then carry on
sleep(2);
}
?>
I'm thankful for every advice I can get! :)
EDIT:
The main idea is to frequently check my MySQL database for new entries and if there is a new order present, format the data nicely and send the information over SSE to my android application.
I already found libraries to receive SSEs on android, the main problem is on the server side.
Based on your question I think you could implement SSE - Server sent events, which is part of HTML5 standard. It is a one-way communication from server to client. It needs html/javascript and a backend language, e.g PHP.
The client will subscribe on events and when subscription is up and running the server will send any updates from the input data. As standard the update will be visible each 3 seconds. This can be adjusted though.
I would recommend you to first create a basic functioning web-browser-client as a start. When and if it is working as you expect, only then you would judge about the effort of building the client as an app.
You would probably need to add functions on the client-side, such as start/stop the subscription.
My understanding of users not recommending the combination of (server sent events) and Apache is the lack of control how many open connections there are and what would control the continuously need of closing of connections. This could lead to sever server performance problems.
Seems using for example node.js would not cause that problem.
Here are some start link:
MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
Stream Updates with Server-Sent Events:
https://www.html5rocks.com/en/tutorials/eventsource/basics/
im experimenting with JSON Api's with PHP.
Im using a free Bitcoin price ticker api from Blockchain.
Its working but to refresh the data i need to refresh the page.
Would it be possible to auto-update the data without refreshing the page?
This is what i got now (its working)
<?php
$json = file_get_contents('https://blockchain.info/ticker');
$data = json_decode($json,true);
$priceUSD = $data['USD']['last'];
echo $priceUSD;
Thanks in advance, have a nice day!
King regards,
L Kenselaar
In order to refresh the data in your PHP array, you'll have to run a new HTTP request against your API from within the PHP code.
Without refreshing the page where your PHP renders, you would need to keep the connection open (which will only last for as long as your php.ini max_execution_time is and PHP can't edit data it has already sent, so the closest you could get is a news ticker that appends new lines at the bottom)
If all you want is a self-refreshing website, you'll have to use JavaScript (that can run infinitely and request new data from your PHP backend in regular intervals). Look for AJAX or XMLHttpRequests in general.
If you must stick to PHP you might want to run an independent process in background (checkout nohup or disown on Linux/Unix).
Your script would do something like:
<?php
while(true){
try {
$json = file_get_contents('https://blockchain.info/ticker');
$data = json_decode($json,true);
$priceUSD = $data['USD']['last'];
// Do the internal handling
// update your database, etc
}
catch (Exception $e) {
echo 'Error: ' . $e->getMessage() . "\n";
}
// wait for 5 seconds
sleep(5);
}
Keep in mind that PHP code runs in a blocking thread and this means that this process has to run aside of your web server.
However, if you wanted to both tasks at the same time (fetching and serving requests), you would have to consider alternatives like NodeJS.
I have a PHP script that has to reload a page on the client (server push) when something specific happens on the server. So I have to listen for changes. My idea is to have a text file that contains the number of page loads for the current page. So I would like to monitor the file and as soon as it is modified, to use server push in order to update the content on the client. The question is how to track the file for changes in PHP?
You could do something like:
<?php
while(true){
$file = stat('/file');
if($file['mtime'] == time()){
//... Do Something Here ..//
}
sleep(1);
}
This will continuously look for a change in the modified time of a file every second. If you don't constrain it you could kill your disk IO and may need to adjust your ulimit.
This will check your file for a change:
<?php
$current_contents = "";
function checkForChange($filepath) {
global $current_contents;
$new_contents = file_get_contents($filepath);
if (strcmp($new_contents, $current_contents) {
$current_contents = $new_contents;
return true;
}
return false;
}
But that will not solve your problem. The php file that serves the client finishes executing before the rendered html is sent to the client. That client will need to call back to some php file to check for a change... and since that is also a http request, the file will finish executing and forget anything in memory.
In order to properly solve this, you'll probably have to back off the idea of checking a file. Either the server needs to know when and how to contact currently connected clients, or those clients need to poll a lightweight service at a regular interval.
This is sort of hacky but what about creating a cron job that sucks in the page, stores it in a scope or table, and then simply compares it every 30 seconds?
I have noticed a few websites such as hypem.com show a "You didnt get served" error message when the site is busy rather than just letting people wait, time out or refresh; aggravating what is probably a server load issue.
We are too loaded to process your request. Please click "back" in your
browser and try what you were doing again.
How is this achieved before the server becomes overloaded? It sounds like a really neat way to manage user expectation if a site happens to get overloaded whilst also giving the site time to recover.
Another options is this:
$load = sys_getloadavg();
if ($load[0] > 80) {
header('HTTP/1.1 503 Too busy, try again later');
die('Server too busy. Please try again later.');
}
I got it from php's site http://php.net/sys_getloadavg, altough I'm not sure what the values represent that the sys_getloadavg returns
You could simply create a 500.html file and have your webserver use that whenever a 50x error is thrown.
I.e. in your apache config:
ErrorDocument 500 /errors/500.html
Or use a php shutdown function to check if the request timeout (which defaults to 30s) has been reached and if so - redirect/render something static (so that rendering the error itself cannot cause problems).
Note that most sites where you'll see a "This site is taking too long to respond" message are effectively generating that message with javascript.
This may be to do with the database connection timing out, but that assumes that your server has a bigger DB load than CPU load when times get tough. If this is the case, you can make your DB connector show the message if no connection happens for 1 second.
You could also use a quick query to the logs table to find out how many hits/second there are and automatically not respond to any more after a certain point in order to preserve QOS for the others. In this case, you would have to set that level manually, based on server logs. An alternative method can be seen here in the Drupal throttle module.
Another alternative would be to use the Apache status page to get information on how many child processes are free and to throttle id there are none left as per #giltotherescue's answer to this question.
You can restrict the maximum connection in apache configuration too...
Refer
http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients
http://www.howtoforge.com/configuring_apache_for_maximum_performance
This is not a strictly PHP solution, but you could do like Twitter, i.e.:
serve a mostly static HTML and Javascript app from a CDN or another server of yours
the calls to the actual heavy work server-side (PHP in your case) functions/APIs are actually done in AJAX from one of your static JS files
so you can set a timeout on your AJAX calls and return a "Seems like loading tweets may take longer than expected"-like notice.
You can use the php tick function to detect when a server isn't loading for a specified amount of time, then display an error messages. Basic usage:
<?php
$connection = false;
function checkConnection( $connectionWaitingTime = 3 )
{
// check connection & time
global $time,$connection;
if( ($t = (time() - $time)) >= $connectionWaitingTime && !$connection){
echo ("<p> Server not responding for <strong>$t</strong> seconds !! </p>");
die("Connection aborted");
}
}
register_tick_function("checkConnection");
$time = time();
declare (ticks=1)
{
require 'yourapp.php' // load your main app logic
$connection = true ;
}
The while(true) is just to simulate a loaded server.
To implement the script in your site, you need to remove the while statement and add your page logic E.G dispatch event or front controller action etc.
And the $connectionWaitingTime in the checkCOnnection function is set to timeout after 3 seconds, but you can change that to whatever you want
i have this function that gives me an output of a number. (the number is my total amount of downloads from my iphone themes.)
because the code has to make so many requests, it loads the page very slowly.
what would be the best way for me to go about the code loading into a variable and than calling it on the second page refresh. so it dosnt take so long to load?
or any other method will do. i just want it to not take so long to load!
also this isnt on my server so i cant use $.ajax
<?php
function all_downloads() {
$allThemes = array(
'com.modmyi.batterytheme',
'com.modmyi.connectiontheme',
'com.modmyi.icontheme',
'com.modmyi.percenttheme',
'com.modmyi.statusnotifiertheme',
'com.modmyi.cnote',
'com.modmyi.iaccescnotekb',
'com.modmyi.cnotelite',
'com.modmyi.multibrowsericon',
'com.modmyi.changeappstoreiconwithinstallous'
);
$total = 0;
foreach($allThemes as $com_modmyi){
$theme = file_get_contents( "http://modmyi.com/cstats/index.php?package=".$com_modmyi.'&output=number');
$theme = str_replace(",","", $theme);
$almost_done += $theme;
$rock_your_phone = 301; //From c-note and Multi Lock Screen Theme on Rock Your Phone
$total = ($almost_done + $rock_your_phone);
}
echo number_format($total);
}
?>
call the function with AJAX !
Th basic idea of using ajax is to to help make web applications function more like desktop applications
most actions that an end-user takes in his or her browser send a request back to the web server. The server then processes that request, perhaps sends out further requests, and eventually responds with whatever the user requested. <--whats your problem is ** **(slow !)
with AJAX you can call a PHP function with out reloading a page
please go though this tutorial which is really simple