Problems with APC on publish - php

We've recently enabled APC on our servers, and occasionally when we publish new code or changes we discover that the source files that were changed start throwing errors that aren't reflected in the code, usually parse errors describing a token that doesn't exist. We have verified this by running php -l on the files the error logs say are affected. Usually a republish fixes the problem. We're using PHP 5.2.0 and APC 3.01.9. My question is, has anyone else experienced this problem, or does anyone recognize what our problem is? If so, how did you fix it or how could we fix it?
Edit: I should probably add in some details about our publishing process. The content is being pushed to the production servers via rsync from a staging server. We enabled apc.stat_ctime because it said this helps things run smoother with rsync. apc.write_lock is on by default and we haven't disabled it. Ditto for apc.file_update_protection.

Sounds like a part-published file is being read and cached as broken. apc.file_update_protection is designed to help stop this.
in php.ini: apc.file_update_protection integer
apc.file_update_protection setting
puts a delay on caching brand new
files. The default is 2 seconds which
means that if the modification
timestamp (mtime) on a file shows that
it is less than 2 seconds old when it
is accessed, it will not be cached.
The unfortunate person who accessed
this half-written file will still see
weirdness, but at least it won't
persist.
Following the question being edited: One reason I don't see these kinds of problems is that I push a whole new copy of the site (with SVN export). Only after that is fully completed does it become visable to Apache/Mod_php (see my answer How to get started deploying PHP applications from a subversion repository? )
The other thing that may happen of course, is that if you are updating in place, you may be updating files that depend on others that have not yet been uploaded. Rsync can only guarantee atomic updates for individual files, not the entire collection that is being changed/uploaded. Another reason I think to upload the site en-mass, and only then put into use.

It sounds like APC isn't preforming or getting the correct file stat info. You could check it to make sure the APC configuration apc.stat is set correctly. Another thing you could do it force the cache to clear with apc_clear_cache() when you publish new code.

Never saw that before, even if i'm a huge user of APC.
Maybe try to trigger a script that empty the APC opcode everytime you send new code on the server ?

When you get a file with a parse error, back it up, then repubish. Take that same file that now works and do a diff against the file with the parse error.

ctime means creation time. You will want to manually flush your entire cache every time you do updates.
You can easily do this, by putting the apc.php script somewhere on your server. This script gives you cache statistics, and will allow you to drop the cache altogether.
The script comes with APC.
Hopet his helps,
Evert

This is probably happening because there's a mismatch between your code, and the cached versions of the code.
For example, APC has a cached version of User.php, but you made changes to User.php or to the data that User uses. The cached version is still running even after your deploy, because it hasn't expired yet.
If you clear your APC cache entries when you deploy, this issue should disappear.

Related

Suspected Caching Issue with CakePhp 4

I'm recently getting back into programming after taking a break for quite some time. I'm currently trying to rebuild my CakePhp 2.X apps for CakePhp 4.X. I'm developing in a local environment using Bitnami WAMP stack.
The issue is that development is very slow because changes do not seem to be taking effect immediately. I have tried disabling all caching by using
Cache::disable();
I've tried placing this line in various places
config/boostrap.php
config/app.php
config/app_local.php
src/application.php
How this is impacting me: I'll make an update, for instance, to a model table file or controller file. I'll go refresh my site to preview the change and either there is no update or there might be an error. To fix the error, I try to undo the changes I made. I go back to my browser and hard refresh the page. I continue to see the same error for 10+ minutes. This often leads me to wanting to undo previous steps but I know that those previous steps didn't cause the issue and it was only the most recent change that caused it. It's making it difficult to keep track of what changes are causing issues and what solutions are working. Even something as simple as updating my navigation element (templates/elements/nav.php) to add a new link does not show on the page when I refresh. I've also tried clearing my browser cache (I use Chrome).
Did you try to clear all keys? You can do it with:
// Will clear all keys.
Cache::clear();
Cache::disable() should work also.
You can also delete the contents of /tmp/cache/ if the caching is set on File.
Maybe the problem is Bitnami WAMP itself. Try to disable the server cache:
https://docs.bitnami.com/installer/infrastructure/wamp/administration/disable-cache/
If you are developing on top of an AMP Stack or customizing any
Bitnami Stack, your files (like JavaScript files) may be cached by the
server and even you modify them your changes will not appear to be
applied.
In order to disable the cache in the server and let the files be
served each time, disable PageSpeed for Apache and OPCache for PHP,
enabled by default

Apache or PHP keeps the HTML output in some kind of cache for a couple of minutes?

I recently ditched XAMPP on my Windows 10 machine and re-installed Apache (2.4), PHP 7 and MySQL manually (I followed the instructions given here in order to be able to switch between PHP versions easily).
Everything works fine, except that now when I make a change in a PHP file and hit Refresh in the browser, the change often doesn't appear immediately in the browser. No matter how hard I hit F5 (or Ctrl+F5), I still get the non-modified source code, and I have to wait a couple of minutes before those change are finally visible to the browser.
Needless to say, it's quite annoying when developing. And it didn't happen when I was using XAMPP.
So there seems to be some kind of cache somewhere, but I can't find where it is. I don't know if it's Apache or PHP, although I suspect it might be PHP, because the CSS or JS files are not affected by this problem (as far as I can tell).
Any idea what's causing this behavior and how to disable it?
EDIT: I did some more testing.
I created the simplest PHP file possible. Just:
<?php
echo 'test1';
I can confirm that the problem occurs even in this simple case (changing "test1" to "test2": the browser still shows "test1" for a while).
Opening the same page in another browser still shows the outdated code (test1 instead of test2).
Clearing the browser cache doesn't help.
So the problem doesn't seem to happen on the client side.
However, if I do the same test with an HTML file instead of a PHP file, then the problem doesn't occur. Any change done to that file is visible immediately in the browser (of course I'm still accessing this file via Apache, so http://localhost/some-path/test.html)
So the problem seems to affect only PHP files.
It seems the problem was caused by the OPCache module, which I had to enable in order to work on another (drupal 8) project.
In php.ini, the following line:
; How often (in seconds) to check file timestamps for changes to the shared
; memory storage allocation. ("1" means validate once per second, but only
; once per request. "0" means always validate)
opcache.revalidate_freq=60
Changing 60 to 1 (and restarting Apache) basically solved the problem.

Handling Symfony's cache in production

I have a Symfony2 website that I'm testing in production. I went ahead and cleared its cache because I've made and will probably make more modifications, however there is a small problem:
While the cache is being cleared and say, afterwards I want to warm it up, someone that accesses the website rebuilds the cache. That creates a small problem as the cache is being built, but not completely, while half of it gets deleted because the deletion is still in progress.
What happens afterwards is, the cache is built, but only a part of it. Symfony thinks that the cache is built entirely, and runs without trying to build it anymore, but it runs on a half-built cache. The deletion process is a bit long (~15 sec), so in this timeframe nobody must try and create the cache by accessing the website.
Either that, or the cache is completely built, it overwrites the old cache, and the system treats these new files as old ones, deletes part of them and some others remain. Not entirely sure, I'm not sure how to check this.
For instance, one of the errors that I'd get is
The directory "D:\xampp\htdocs\med-app\app\app\cache\dev/jms_diextra/metadata" does not exist.
If I wouldn't use that bundle I'd get another cache problem from Doctrine. This appears at every website access until I delete the cache again WITHOUT anyone accessing the website. it completely blocks access to the website and makes it non-functional.
Also, what about the warmup? That takes a while, too. What if someone accesses the website while the cache is being warmed up? Doesn't that create a conflict, too?
How to handle this problem? Do I need to close the apache service, clear and warm cache and then restart apache? How is this handled with a website in production?
EDIT
Something interesting that I have discovered. The bug occurs when I delete the cache/prod folder. If I delete the contents of the folder without deleting the folder itself, it seems the bug does not occur. I wonder why.
Usually it is good practice to lock the website into maintenance mode if you're performing updates, or clearing the cache for any other reason in the production. Sometimes web hosting services have this option to handle this for you, or there is a nice bundle for handling maintenance easily from the command line.
This way you can safely delete the cache and be sure no-one visits the page and rebuilds the cache incorrectly.
Usually if you have to clear the Symfony cache it means you're updating to a new version - so not only are you having to clear the cache, but you're probably having to dump assets and perform other tasks. In this case what I've done in the past that has worked very well is to treat each production release as its own version n its own folder - so when you install a new version you do it unconnected from the webserver, and then just change your webserver to point to the new version when you are done. The added benefit is if you mess something up and have to perform a rollback, you just immediately link back to the previous version.
For example, say your Apache config has DocumentRoot always points to a specific location:
DocumentRoot /var/www/mysite/web
You would make that root a symlink to your latest version:
/var/www/mysite/web -> /var/www/versions/1.0/web
Now say you have version 1.1 of your site to install. You simply install it to /var/www/versions/1.1 - put the code there, install your assets, update the cache, etc. Then simply change the symlink:
/var/www/mysite/web -> /var/www/versions/1.1/web
Now if the site crashes horribly you can simply point the symlink back. The benefit here is that there is no downtime to your site and it's easy to rollback if you made a mistake. To automate this I use a bash script that installs a new version and updates the symlinks with a series of commands connected via && so if one step of the install fails, the whole install fails and you're not stuck between version limbo.
Granted there are probably better ways to do all of the above or ways to automate it further, but the point is if you're changing production you'll want to perform the Symfony installation/setup without letting users interfere with that.

Manually filling opcode cache for entire app using apc_compile_file, then switching to new release

Does anyone have a great system, or any ideas, for doing as the title says?
I want to switch production version of web app-- written in PHP and served by Apache-- from release 1234 to release 1235, but before that happens, have all files already in the opcode cache (APC). Then after the switch, remove the old cache entries for files from release 1234.
As far as I can think of there are three easy ways of atomically switching from one version to the next.
Have a symbolic link, for example /live, that is always the document root but is changed to point from one version to the next.
Similarly, have a directory /live that is always the document root, but use
mv live oldversion && mv newversion live
to switch to new version.
Edit apache configuration to change the document root to newversion, then restart apache.
I think it is preferable not to have to do 3, but I can't think of anyway to precompile all php files AND use 1 or 2 to switch release.
So can someone either convince me its okay to rely on option 3, or tell me how to work with 1 or 2, or reveal some other option I am not thinking of?
Exactly why do you want to do this?
When I switch to a new release, I just stop my Apache, replace the PHP files on the server via checkout from my VCS and restart Apache. It mostly takes less than 30 seconds to pull this off, it's even scriptable. All that is executed at a time when there are few or no users. After that, the opcode cache is empty and will fill itself as soon as someone uses the files.
Maybe the first few hits will not have optimal performance but that should not be so bad. On my production systems no one ever noticed this short performance drop. And there are some really heavy load systems among them.
You can even place a simple "upgrading ... be back soon" screen on your server while replacing the files to avoid any disturbing error messages to your users.
Then after the switch, remove the old
cache entries for files from release
1234.
You can only clear the entire cache or none at all. It's not a selective process. This may change your approach to the problem. If precompilation is paramount you may be forced to bring down the server during the switchover.

Connection Interrupted. The connection to the server was reset while the page was loading

I am calling a PHP-Script belonging to a MySQL/PHP web application using FF3. I run XAMPP on localhost. All I get is this:
Connection Interrupted
The connection to the server was reset while the page was loading.
The network link was interrupted while negotiating a connection. Please try again.
There are a number of possible solutions ... depends on the "why" ... so it ends up being a bit of trial and error. On a fresh install, that's tricky to determine. But, if you made a recent "major" change that's a place to start looking - like modifying virtual hosts or adding/enabling XDebug.
Here's a list of things I've used/done/tried in the past
check for infinite loops ... in particular looping through a SQL fetch result which works 99% of the time except the 1% it doesn't. In one case, I was using the results of two previous queries as the upper and lower bounds of a for loop ... and occasionally got a upper bound of a UINT max ... har har har (vomit)
copying the ./php/libmysql.dll to the windows/system32 directory (Particularly if you see Parent: child process exited with status 3221225477 -- Restarting in your log files ... check out: http://www.java-samples.com/showtutorial.php?tutorialid=1050)
if you modify PHP's error_reporting at runtime ... in certain circumstances this can cause PHP to degenerate into an unstable state if, say, in your PHP code you modify the superglobals or fiddle around with other deep and personal background system variables (Nah, who would ever do such evil hackery? ahem)
if you convert your MySQL to something other than MyISAM or mysqli
There is a known bug with MySQL related to MyISAM, the UTF8 character set and indexes (http://bugs.mysql.com/bug.php?id=4541)
Solution is to use InnoDB dialect (eg sql set GLOBAL storage_engine='InnoDb';)
Doing that changes how new tables are created ... which might slightly alter the way results are returned to a fetch statement ... leading to an infinite loop, a malformed dataset, etc. (although this change should not hang the database itself)
Other helpful items are to ramp up the debug reporting for PHP and apache in their config files and restart the servers. The log files sometimes give a clue as to at least where the problem might reside. If it happens after your page content was finished it's more likely in the php settings. If it's during page construction, check your PHP code. Etc. etc.
Hope the above laundry list helps somebody someday ... probably myself when I run into it again and come back here looking for "how the heck did I fix it last time?" ... :)
It's possible that your script could be caught in an infinite loop. If that doesn't apply, then I'd check the error logs like TimB suggested.
It sounds like the PHP script you're calling is failing without returning a valid response. Depending on the level of logging that you have set up, this should generate an error in the Apache logfile, which will give you some idea of the problem. I'm not familiar with XAMPP, but you should be able to find out where the logs are, and look for an error that occurred at the time you made your request to the PHP script.
copying libmysql.dll to apache\bin folder may help you overcome this strange error
I solved this problem Upgrading the xampp\php\ext\xdebug\php_xdebug.dll
(changed to php xdebug v.2.0.5-5.3-vc9 )
I had the same problem and this is what i did.
I issued the http get command through php cli script, and as it turns out I had declared one class twice somewhere.
By the way , i use AMPPS on an mac
Hope this helps some one!
Try doing the request with Firebug enabled and see what info you can get out of that; I always find that using wget is helpful for seeing the raw HTTP interaction without worrying about Firefox's UI elements interfering.
If you are using certificates for ssl in Windows 2008 Server(iis 7) from old selfssl tool(iis 6), that is the problem. Sometimes Microsoft releases patches which can destruct all these old certificates. The solution is to generate them again.
copying libmysql.dll to apache\bin folder may help you overcome this strange error
Indeed this helped me to solve this problem
The connection to the server was reset while the page was loading.
Incase the issue is not working this did the trick for me.
1. I got a new zip directory for PHP and connected it with apache
2. I searched for the libmysql in the new php and inserted this to the apache/bin
its this libmysql.dll that is needed there and not the one form mySQL/bin.
ok at least thats the one that worked.
I experienced a very similar issue - which doesn't apply to the person who asked this question - but may be of help to others who are reading this page...
I had an issue where in certain cases PHP 5.4 + eAccelerator = connection reset. There was no error output in any log files, and it only happened on certain URLs, which made it difficult to diagnose. Turns out it only happened for certain PHP code / certain PHP files, and was due to some incompatibilities with specific PHP code and eAccelerator. Easiest solution was to disable eAccelerator for that specific site, by adding the following to .htaccess file
php_flag eaccelerator.enable 0
php_flag eaccelerator.optimizer 0
(or equivalent lines in php.ini):
eaccelerator.enable="0"
eaccelerator.optimizer="0"

Categories