I have a problem wtih session_start() on primary server. When I load page for the first time, it takes less than 1 second to complete request. If I'll wait for approximately 12-15 seconds and then reload page, time of loading will be the same. But when I'm trying to refresh page after, for example, 3 or 5 seconds after initial loading, time of the server's response equals 10 seconds.
I made some tests to define a bottleneck in my script and I found out, that function session_start() executes for 9.8 seconds. I'm using PEAR package HTTP_Session2. Here is code snippet:
HTTP_Session2::useCookies(SESSION_USE_COOKIE);
/* Next line was added to make logging of execution time possible. */
self::writeToFile('HTTP_useCookies(1) -> '.self::getWorkTime());
HTTP_Session2::start("SID");
self::writeToFile('HTTP_start(2) -> '.self::getWorkTime());
HTTP_Session2::setExpire(time() + SESSION_EXPIRE);
self::writeToFile('HTTP_setExpire(3) -> '.self::getWorkTime());
Text of the logs:
//First loading (13:34:35)
HTTP_useCookies(1) -> 0.00038
HTTP_start(2) -> 0.00077
HTTP_setExpire(3) -> 0.00090
// Second loading (13:34:39)(4 seconds later)
HTTP_useCookies(1) -> 0.00029
HTTP_start(2) -> <<<<<< 10.80752 >>>>>
HTTP_setExpire(3) -> <<<<<< 10.80780 >>>>>
//Third loading (13:34:56)
HTTP_useCookies(1) -> 0.00041
HTTP_start(2) -> 0.00071
HTTP_setExpire(3) -> 0.00083
So I found, that problem is in the HTTP_Session2::start() function. Code of the function HTTP_Session2::start():
public function start($name = 'SessionID', $id = null)
{
self::name($name);
if (is_null(self::detectID())) {
if ($id) {
self::id($id);
} else {
self::id(uniqid(dechex(rand())));
}
}
session_start();
if (!isset($_SESSION['__HTTP_Session2_Info'])) {
$_SESSION['__HTTP_Session2_Info'] = self::STARTED;
} else {
$_SESSION['__HTTP_Session2_Info'] = self::CONTINUED;
}
}
I can't understand what is the cause of time delay. Probably, there are wrong Apache settings on the server. Or, maybe, there are some 'locks' on files with session information.
Maybe, someone has already encountered such problems and can help to solve it.
The file containing the session's informations is locked during the time PHP serves a request.
So, if you have one PHP script (using a session) that's currently being executed, and the same user sends another request, the second request will wait until the first is finished.
Related
I've script which get some values from XML record.
There's code:
<?php
//Data
$xml_data = '<image_process_call><image_url>https://i.pinimg.com/originals/e4/41/54/e44154308e3466d987665c6d50887f06.jpg</image_url><methods_list><method><name>collage</name><params>template_name=Nun Face in Hole;</params></method></methods_list><result_format>jpg</result_format><result_size>800</result_size><template_watermark>false</template_watermark></image_process_call>';
//Settings
$app_id = '';
$key = '';
$sign_data = hash_hmac('SHA1', $xml_data, $key);
//Send request
$request_url = 'http://opeapi.ws.pho.to/addtask?data='. $xml_data .'&sign_data='. $sign_data .'&app_id='. $app_id;
$request_xml = simplexml_load_file($request_url);
$request_id = strval($request_xml -> request_id);
if (isset($request_id)) {
$result_url = 'http://opeapi.ws.pho.to/getresult?request_id='. $request_id;
sleep(6);
$result_xml = simplexml_load_file($result_url);
$result_status = strval($result_xml -> status);
$result_img = strval($result_xml -> result_url);
if (isset($result_img)) {
echo $result_img;
} else {
echo 'Result image not found';
}
} else {
echo 'Request ID not found';
}
?>
The problem depends on time to generate the second XML file. $result_xml took few seconds so I have to use sleep(6) function.
If I remove this, I need to refresh the page (minimum three times) to get a link to generated image from second XML.
Do you have an idea how to do it more professionally? I can't be sure that every image will be generated in 6 seconds (sometimes shorter sometimes longer).
Is there any method for genereting the result only after receiving $result_img? Thanks in advance for your help!
I think it is worth writing.
In practice, it looks like this:
Script does $request_xml and XML from site return:
<image_process_response>
<request_id>2d8d4dec-4344-4df0-a1e1-0c8df304ad11</request_id>
<status>OK</status>
<description/>
<err_code>0</err_code>
</image_process_response>
Script gets request_id from this XML and do $result_xml. However, this is XML and script doesn't get image's url immediately. It needs to wait a few seconds.
After three times refreshing the page or using sleep(6) function finally we get:
<image_process_response>
<request_id>2d8d4dec-4344-4df0-a1e1-0c8df304ad11</request_id>
<status>OK</status>
<result_url>
http://worker-images.ws.pho.to/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</result_url>
<result_url_alt>
http://worker-images.ws.pho.to.s3.amazonaws.com/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</result_url_alt>
<limited_image_url>
http://worker-images.ws.pho.to/i1/3F797C83-2C2E-401C-B4AF-C4D36BBD442D.jpg
</limited_image_url>
<nowm_image_url>
http://worker-images.ws.pho.to/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</nowm_image_url>
<duration>2950.879097ms</duration>
<total_duration>2956.124067ms</total_duration>
</image_process_response>
Edit:
After trying to immediately generate the image I get such an XML:
<image_process_response>
<request_id>e615f0a1-ddee-4d81-94c4-a392f8f123e8</request_id>
<status>InProgress</status>
<description>The task is in progress, you need to wait for sometime.</description>
</image_process_response>
So this is reason why I see blank page...
Do someone have an idea how to force a script to reconnect with the second XML until it finds a result_url?
The problem depends on time to generate the second XML file.
$result_xml took few seconds so I have to use sleep(6) function. If I
remove this, I need to refresh the page (minimum three times) to get a
link to generated image from second XML.
Do you have an idea how to do it more professionally? I can't be sure
that every image will be generated in 6 seconds (sometimes shorter
sometimes longer). Is there any method for genereting the result only
after receiving $result_img? Thanks in advance for your help!
According to Pho.to API, An add task request is a queued POST request.
In my opinion, Send request in while-loop, but wait for smaller time instead of fixed 6 seconds, Check the status in image_process_response, Keep looping until it is not InProgress, After that, You can safely send second request to get processed image result.
You may encounter timeout issue due to low timeout configuration for DoS protection if you run this script on web server (via CGI/FastCGI), To resolve this situation, You need a queue for adding task in your HTTP request, and then process it offline (means without web environment).
I can not understand why only part of the links are returned without sleep(1); function. Although the script works synchronously and after $web_driver->executeScript the object is already loaded, all links have already been loaded.
<?php
require_once('vendor/autoload.php');
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
$caps = array("platform"=>"SIERRA", "browserName" => "chrome", "version" => "69");
$web_driver = RemoteWebDriver::create(
"http://localhost:4444/wd/hub",
$caps
);
$web_driver->get("https://winestyle.ru/wine/gerard-bertrand/");
$web_driver->executeScript('window.scrollTo(0,document.body.scrollHeight);');
sleep(1);
$element = $web_driver->findElements(WebDriverBy::cssSelector(".bg-text[title='Артикул']"));
foreach ($element as $e){
echo $e->getText().'<br>';
}
$web_driver->quit();
?>
return without sleep:
Артикул:в101222
Артикул:в99863
Артикул:в99981
Артикул:в101225
Артикул:в101212
Артикул:в101224
Артикул:в101211
Артикул:в92722
Артикул:в92723
Артикул:в101208
Артикул:в101210
Артикул:в99979
Артикул:в101223
Артикул:в101220
Артикул:в101213
Артикул:в101221
Артикул:в101227
Артикул:в101218
Артикул:в101217
Артикул:в101215
return with sleep:
Артикул:в101222
Артикул:в99863
Артикул:в99981
Артикул:в101225
Артикул:в101212
Артикул:в101224
Артикул:в101211
Артикул:в92722
Артикул:в92723
Артикул:в101208
Артикул:в101210
Артикул:в99979
Артикул:в101223
Артикул:в101220
Артикул:в101213
Артикул:в101221
Артикул:в101227
Артикул:в101218
Артикул:в101217
Артикул:в101215
Артикул:в101226
Артикул:в99980
Артикул:в85254
Артикул:в66382
Артикул:в66386
Артикул:в66387
Артикул:в85253
Артикул:в101214
Артикул:в101219
Most probably the page has implemented lazy loading - any extra information - new elements, are request through ajax only when the user scrolls to the end of the page.
And this is what's happening in your script - you've executed the js to scroll to the end. If you at that moment execute findElements without the sleep, the page would not have time to send the ajax request, wait for an parse the respone, and update the DOM. Thus you will get only the currently present elements.
With the sleep you give it that possibility.
Have in mind the hardcoded value 1s may sometimes work, and sometimes - not; if the backend takes more time to generate the response, or the network is slow - new data may not be received in time.
An alternative solution would be to poll the DOM for the number of target elements every X milliseconds, and continue once that number increases. This though must accommodate for the case where there are no more results (no more артикулы Russian? артикули Bulgarian? :), and to break out of the polling loop (could be done if there's a total results counter on the page, or similar).
I am making a php chat and am starting the php checking database part. So when a user types something into the chat, it gets recorded in the MySQL database, how would I check the database every 10 seconds so that one user's chat would update with new messages from other users. I know that you can use an ajax request to a page with an interval, but I want the php to be on the same page, instead of having to use numerous pages. This is the code for checking the database
<?php
$con = mysqli_connect('host','user','pass','database');
$query = mysqli_query($con,"SELECT * FROM `messages`");
while ($row=mysqli_fetch_assoc($query)) {
$user = $row['user'];
$message = $row['message'];
echo 'User: ',$user,' Message: ',$message;
}
?>
Thanks in advance anyone!
Use MySQL Event Scheduler.
Below link will guide you through .
http://www.9lessons.info/2012/10/mysql-event-scheduler.html.
I think best option in your case .
AJAX is probably the simplest solution. You can perform an AJAX request on the same page your PHP code is executing on if you really want to.
(function check() {
$.get('mypage.php', function(data) {
doSomethingWith(data);
setTimeout(check, 5000); // every 5 seconds
});
})();
PHP doesn't have a setInterval function. While I'm sure you can use a crontask to automate it on the server, you can also achieve this with some simple Javascript.
The concept you are trying to achieve is known as Short Polling. What you want to do is to have a setInterval function in Javascript that constantly makes AJAX requests to your PHP file which performs the check to the database for new messages. Your PHP should return that information to your script where you can then simply populate the user's screen.
There is also Long Polling where you simply maintain the connection and have a setTimeout to wait for messages to come in. You can find more information yourself and if you have questions, you can come back here.
A good video about this:
https://www.youtube.com/watch?v=wHmSqFor1HU
Hope this helps.
This is what you need. We need set time for ajax auto reload. Don't put everything in one page. Because you must reload page to refresh data. That is bad solution.
Call jQuery Ajax Request Each X Minutes
Make a while for 30 seconds, and check the db every second, once you find a record the while is being broken, also it is being broken when 30 secs are expired.
$sec = 1;
while($sec <= 30) {
if(has record)
Send to the user;
$sec++;
sleep(one sec here);
}
Use sleep for 10 secs in order to check every 10 secs...
I am working on a project, in which i need to announce an announcement when a txt file is created on the server and i need to notify all users through an audio announcement,the audio should be played at once on any client browsers that are currently on the pages. the playing of the announcement needs to be synchronized upto maximum accuracy.
the announcement is composed of multiple audio files (playlist).
after the announcement is played on all active clients the txt file will be deleted. and the server will be waiting/looking for another txt file.
for example:
client1 - server time: 19:22:01, Recieved announcement and playing the audio
Client2 - server time: 19:22:01, Recieved announcement and playing the audio
any recommendations? on how to accomplish the announcement at once on all clients, any technique? mysql database or
Flash, Applets, HTML5 audio, JQuery etc.
Thanks..
I wrote a long-poller technique with simple PHP, Ajax en MySQL:
The PHP code is as follows:
timeout = 600;
while (timeout > 0) {
$res = db_query("QUERY");
$return_value = create_value_from_result($res);
// see if the result changed
$db_hash = md5($return_value);
if ($_SESSION['hash'] == $db_hash) {
// the result didn't change -- sleep and poll again
// usleep take microseconds, 100000 is 100 millisecond
// this is the default database polling interval
usleep(100000);
$timeout--;
} else {
// the result changed -- reply the result and set the session hash
$timeout = 0;
$_SESSION['hash'] = $db_hash;
}
}
return json_encode($return_value);
And the Javascript is simple Ajax (dojo is this case):
function longpoll() {
dojo.xhrPost({
url: 'longpolling.php',
load: function (data, ioArgs) {
data = dojo.fromJson(data);
do_magic(data);
// use settimeout to avoid stack overflows
// we could also use a while(1) loop,
// but it might give browser errors such as 'script is
// running too long' (not confirmed)
setTimeout(longpoll, 0);
}
});
}
You need the 60 second timeout to make sure the browser doesn't timeout on the Ajax call.
This way, as soon as the result of QUERY changes (a record gets inserted, an update made on a record), the PHP call returns and the Ajax gets its result.
I have a fairly expensive server call that I need to cache for 30 seconds. It seems however that I can not get the cache to expire.
In the code below, after the first time it caches, it will never get past $return->cache_data, even after the time() + 30 seconds.
Note, I can even print $cache->expire and it is definitely set to a time past 30 seconds ago and never updates.
I've manually cleared cache many times to confirm I get the same results.
Does anything look wrong with this?
function mymodule_get_something($id) {
// set the unique cache id
$cid = 'id-'. $id;
// return data if there's an un-expired cache entry
// *** $cache ALWAYS gets populated with my expired data
if ($cache = cache_get($cid, 'cache_mymodule')) {
return $cache->data;
}
// set my super expensive data call here
$something = array('Double Decker Taco', 'Burrito Supreme');
// set the cache to expire in 30 seconds
cache_set($cid, $something, 'cache_mymodule', time() + 30);
// return my data
return $something;
}
There's nothing wrong with your code as such, I think the problem is in how cache_set behaves. From the docs page, passing a UNIX timestamp:
Indicates that the item should be kept at least until the given time, after which it behaves like CACHE_TEMPORARY.
CACHE_TEMPORARY behaves like this:
Indicates that the item should be removed at the next general cache wipe.
My best guess is that because you're not implicitly forcing that general cache wipe (using cache_clear_all()) the cache object will persist.
I think a simple way around it would just be to manually test the expiry time after your cache check, and let it fall through to re-setting that cache object if it has expired:
if ($cache = cache_get($cid, 'cache_mymodule')) {
if ($cache->expire > REQUEST_TIME) {
return $cache->data;
}
}