Posts Tagged ‘Apache’

Optimizing your web server: Part 1 – Gzip

November 22nd, 2009

This will be the first blogpost in a compilation of posts about optimizing your webserver.

Everyone likes their website to go fast right?, So did I.

Something that can give you an easy performance boost is gzip compression.

This compresses the data that is being send to the user with mod_deflate(apache).
Because of the way xml and html is structured, it contains allot of repeating data.
So this means it’s the perfect candidate to compress.

By enabling compression your webpages can become up to 80% smaller.
A downside is that it does use a little cpu and memory to do the compression, this scares allot of people, thinking that the machine isn’t powerfull enough to do the gzip compression.
But, this uses almost nothing if configured correctly. Make sure you only compress files that benefit from it, for example xml, html, css, js, … and leave out those that do not, jpg, gif, png, mpg, mov, flv, zip, rar, …

Images and movies are already compressed, so compressing them a second time would be pointless.

An extra advantage that gzip gives is that requests are processed faster(files are smaller), because of this, extra cpu time and memory becomes available faster than before. So the cpu time required to do the compression of the files is won back.

A practical example of http://crazytje.be:

Original Size: 42.91 KB
Gzipped Size: 8.08 KB
Data Savings: 81.17%

So how do we go about configuring gzip?
Normally mod_deflate is already supplied with your apache installation, it only requires you to enable it:

LoadModule deflate_module modules/mod_deflate.so
<Location />
# Insert filter
SetOutputFilter DEFLATE
 
# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html
 
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
 
# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
# the above regex won't work. You can use the following
# workaround to get the desired effect:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
 
    # Don't compress
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI dl.php$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI FileDownload$ no-gzip dont-vary
 
    SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.avi$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.mov$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.mp3$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.mp4$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.rm$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \.plist$ no-gzip dont-vary
 
 
    AddOutputFilterByType DEFLATE text/plain text/xml application/xml application/xhtml+xml text/javascript text/css application/x-javascript
    AddOutputFilterByType DEFLATE application/x-httpd-php
    AddOutputFilterByType DEFLATE application/x-httpd-fastphp
    AddOutputFilterByType DEFLATE application/x-httpd-eruby
    AddOutputFilterByType DEFLATE text/html
 
    SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
 
    # Make sure proxies don't deliver the wrong content
    Header append Vary User-Agent env=!dont-vary
</Location>

I don’t think it requires any explination, depending on the content being served you might want to add some extensions to compress or not to compress.

Optimizing your web server: Part 1 – Gzip
Optimizing your web server: Part 2 – Keep Alives
Optimizing your web server: Part 3 – Opcode Caching
Optimizing your web server: Part 4a – PHP
Optimizing your web server: Part 4b – XDebug Profiler

Apache: mod_rewrite redirect when part of querystring matches

October 28th, 2009

Recently a friend asked how to do a redirect with apache’s mod_rewrite if a part of the url’s query string matches.

After allot of trail and error I came to a solution.

Original Url:
htpp://example.com/old/index.php?param1=first&param2=sometext

In this url the param1=first is static so won’t change.
The second parameter is not static, so it must not match this.

Redirect it to:
http://example.com/new/

There was no requirement to pass the query string to the new location.

So how to go about it?, won’t spend much time explaining(as I will most likely explain it wrong).
This is how to get the job done:

RewriteEngine On
 
RewriteCond %{QUERY_STRING} ^(.*&)?param1=first(&.*)?$ [NC]
RewriteCond %{QUERY_STRING} ^(.*&)?param2=[^&]+(&.*)?$ [NC]
RewriteRule ^(index\.php)?$ http://example.com/new/? [R=301,L]

Hope this will save some people time

PHP Opcode caching: Why use an opcode cacher?

October 18th, 2009

Why use an opcode cacher?

When users surf to the website(s) hosted on your machine, the php files are compiled each time.
Compiling the php code you worked so hard to develop takes time, and the more files you have, the longer it takes.

This is especially the case when using PHP frameworks(personally I use CakePHP) or when using a CMS.

So what an opcode cacher does, is cache the compiled code, saving your server the time of compiling the php files each time.

The result is less work to be done for each request and as an end result your users will be shown the pages allot faster.

Using an opcode cacher has more advantages then only the loading time.
Or more like, because the loading times are lower, more advantages show up.

A small list of why opcode cachers are good:

  1. Beter loading times
  2. Less cpu usage(no need to compile the files every time)
  3. Less ram usage – because the requests are done faster, new memory is available faster

A fourth advantage:

The possibility to store data in the memory in stead of fetching it in each request.
When your site had allot of static data, then it’s perfect to keep it in memory. For example a configuration file for your website that you read in every request.
This is a perfect example of ’settings’ that you can just keep in memory.

A blog post I made about how to do this with APC can be found here.

Introduction

When you running a php driven websites on a linux machine that you have full access to, so a vps or a dedicated box. Then this is something for you.

There are many opcode cachers, a short list:

  1. Alternative PHP Cache
  2. eAccelerator
  3. ionCube PHP Accelerator
  4. Turck MMCache
  5. XCache
  6. Nusphere PhpExpress
  7. Zend Optimizer+
  8. Zend Platform
  9. Windows Cache Extension for PHP

I take no credit for the list, it’s copy pasted from wikipedia

But what accelerator is the best?

From the list above ionCube and MMCache have been discontinued while Nusphere PhpExpress and Zend is commercial, no free version is available.

The Windows Cache Extension for PHP is beta, not ready for production use. And as I’m running a CentOS anyway, so no windows.

So that leaves:

  1. Alternative PHP Cache
  2. eAccelerator
  3. XCache

The ’slowest’ one of the tree is APC, it is a bit slower and uses a bit more memory then the other two.
This should be taken lightly, there is about 300% increase in processing speed in each of them compared to pure php, the difference is almost zero(couple of mb and ms’s, nothing serious).

After saying the slowest one is APC, you’d think you should go for the other 2 right?, this is where stability comes into play. Both eAccelerator and XCache show allot of segmentation faults after only a day or so.

The conclusion was to go for APC.

Installing APC

The installation of apc is very easy, there are two ways:

  1. Use pecl
  2. Compile from source

Install using pecl:

The first one is the most easy, when logging in to you linux machine, type:

[crazy@crazymachine ~]# pecl install apc

Make sure you have httpd-devel installed before running the “pecl install apc”, it uses aspx and is supplied with the httpd-devel package, to install it type:

[crazy@crazymachine ~]# yum install httpd-devel

Once this is done you’ll see at the end

----------------------------------------------------------------------
Libraries have been installed in:
   /var/tmp/pear-build-root/APC-3.0.19/modules
 
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'
 
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
 
Build complete.
(It is safe to ignore warnings about tempnam and tmpnam).
 
running: make INSTALL_ROOT="/var/tmp/pear-build-root/install-APC-3.0.19" install
Installing shared extensions:     /var/tmp/pear-build-root/install-APC-3.0.19/usr/lib64/php/modules/
running: find "/var/tmp/pear-build-root/install-APC-3.0.19" -ls
72320221    4 drwxr-xr-x   3 root     root         4096 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19
72320280    4 drwxr-xr-x   3 root     root         4096 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19/usr
72320281    4 drwxr-xr-x   3 root     root         4096 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19/usr/lib64
72320282    4 drwxr-xr-x   3 root     root         4096 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19/usr/lib64/php
72320283    4 drwxr-xr-x   2 root     root         4096 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19/usr/lib64/php/modules
72320279  456 -rwxr-xr-x   1 root     root       461193 Oct 18 11:21 /var/tmp/pear-build-root/install-APC-3.0.19/usr/lib64/php/modules/apc.so
 
Build process completed successfully
Installing '/var/tmp/pear-build-root/install-APC-3.0.19//usr/lib64/php/modules/apc.so'
install ok: channel://pecl.php.net/APC-3.0.19
You should add "extension=apc.so" to php.ini

So what next?, now apc is installed on your machine, but it’s not enabled yet.
As you see in the last line after ‘pecl install apc’, “You should add “extension=apc.so” to php.ini”.

So open up the php.ini and add it:

[crazy@crazymachine ~]# vi /etc/php.ini
 
//scroll down the where the extensions are loaded and add:
 
extension=apc.so
apc.enabled=1
apc.shm_segments=1
apc.shm_size=128
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.enable_cli=1

Now restart apache and it’s ready for take off!:

[crazy@crazymachine ~]# service httpd restart

Manual installation:

Compiling APC by hand and installing it is not very hard. So if for some reason the pecl install does not work, this is the alternative.

As mentioned in the pecl installation, make sure the httpd-devel package is installed for apxs.

The steps to compile and install the apache module:

[root@crazymanga ~]# cd /tmp/
[root@crazymanga tmp]# wget http://pecl.php.net/get/APC-3.0.19.tgz
[root@crazymanga tmp]# tar xvf APC-3.0.19.tgz
[root@crazymanga tmp]# cd APC-3.0.19
[root@crazymanga APC-3.0.19]# phpize
[root@crazymanga APC-3.0.19]# ./configure
[root@crazymanga APC-3.0.19]# make
[root@crazymanga APC-3.0.19]# make install

If the apache modules are located on a none default location, then you can copy it manually, after the made the compiled version is located in “/tmp/APC-3.0.19/modules”

Hope this saves people some time and helps them understand that opcode caching can really improve the performance of a website.