Category Archives: Servers

Servers

Installing ClusterControl with an existing cluster and Nginx

ClusterControl is a comprehensive tool for managing and monitoring MySQL and MongoDb clusters, more information can be found here: http://www.severalnines.com/clustercontrol

ClusterControl comes with some great scripts for automating deployment, however there are a number of hard coded dependencies (like Apache) which make it a rather more painful process to integrate with your existing systems.

Background info:

There are 3 components that make up ClusterControl:

ClusterControl UI: A CakePHP based GUI
CMON: A daemon process which monitors servers and writes to a MySQL database
CMON API: A PHP based API which reads data from the CMON database

ClusterControl UI and CMON API can be on the same or different hosts and the UI can talk to multiple instances of the CMON API (hence multiple CMON daemons).

The UI also makes AJAX calls to the API via a script in the path /access which simply sends the same request to the API with the addition of the API token.

There are several .htaccess files that rewrite requests to the UI, the access script and the API.

Installation process:

CMON can be installed by following this guide: http://support.severalnines.com/entries/20613923-installation-on-an-existing-cluster

The guide contains a section at the end to install the UI/API, this does install and configure Apache, but you can simply remove it again.

Making it work with Nginx:

After a bit of tinkering I’ve put together a config which works nicely for both the ClusterControl UI and CMON API:

server {
        listen 1.2.3.4:80;
        server_name mydomain.com;

        access_log /var/log/nginx/mydomain.com-access.log;
        error_log /var/log/nginx/mydomain.com-error.log;

        root /var/www;
        index index.php;

        location ~ \.htaccess {
                deny all;
        }

        location ~ \.php$ {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include /etc/nginx/fastcgi_params;
        }

        # Handle requests to /clustercontrol
        location /clustercontrol {
                alias /var/www/clustercontrol/app/webroot;
                try_files $uri $uri/ /clustercontrol/app/webroot/index.php;
        }

        # Equivalent of $is_args but adds an & character
        set $is_args_amp "";
        if ($is_args != "") {
                set $is_args_amp "&";
        }

        # Handle requests to /clustercontrol/accesss
        location ~ "^/clustercontrol/access/(.*)$" {
                try_files $uri $uri/ /clustercontrol/app/webroot/access/index.php?url=$1$is_args_amp$args;
        }

        # Handle requests to /cmonapi
        location ~ "^/cmonapi/(.*)$" {
                try_files $uri $uri/ /cmonapi/index.php?url=$1$is_args_amp$args;
        }

}

Making the UI work is straight forward, however the access script and API require the partial URL and the equivalent of the mod_rewrite [QSA] flag as the ? in the try_files directives stops Nginx from auto-appending the query string from the request, hence the need for the regex and appended args.

A small code change is also required to the library used by the access script which is located in /clustercontrol/app/Lib/Access.php as the API token header uses an underscore rather than a dash which results in Nginx ignoring it (which I think is correct behaviour, probably an RFC floating around somewhere which will clarify this).

Replace both instances of:

$headers[0] = "CMON_TOKEN: {$token}";

With:

$headers[0] = "CMON-TOKEN: {$token}";

Everything should now work!

Share

Some observations while upgrading Percona XtraDB Cluster from 5.5 to 5.6

I followed the Percona guide to upgrade my XtraDB Cluster (MySQL + Galera) from 5.5 to 5.6, details can be found here: http://www.percona.com/doc/percona-xtradb-cluster/5.6/upgrading_guide_55_56.html

The upgrade process

I included putting the upgraded nodes into read only mode and I performed an additional step to reconfigure the xinetd process used to run clustercheck after installing the new binaries:

server_args = clustercheck <password> 0 /var/log/mysqlchk.log 0

This sets available when donor and available when read only to off, by default with 5.6 the SST method is Xtrabackup, but my 5.5 cluster had been setup with rsync, more on this later.

The first 2 nodes upgraded just fine, however when I restarted the 3rd node the entire cluster crashed. Restarting MySQL on all nodes got things back up and running again.

After upgrading

Everything was initially working fine, but I noticed some odd behaviour on one node, it was repeatedly crashing when I was purging old data from one of the databases. The node would fail to restart with an rsync error, only resolved when I performed a rolling restart of the other 2 nodes.

Switching from rsync to Xtrabackup

Rysnc clearly is not the best option for a 5.6 based cluster, it worked fine for the last 18 months with the 5.5 cluster but there are good reasons why Xtrabackup is the default option with 5.6. The main benefit that I can see is that Xtrabackup is non-blocking so the node can continue to accept connections during SST.

Xtrabackup requires a username/password to login to another host to perform the transfer, hence you have to create an account with permission to access all databases from each server in the cluster. I simply ran CREATE USER and GRANT statements on a single node and allowed the cluster to replicate the new accounts to the other nodes.

It’s important that the datadir variable is defined in my.cnf, or Xtrabackup doesn’t work.

A test can be carried out from the shell before updating my.cnf:

innobackupex --host=<another node> --user=<user> --pass=<password> /tmp/

Finally my.cnf can be updated:

wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=user:password

Checking the MySQL log should show SST now using Xtrabackup.

Share

Passing backend server host name as a custom header with Nginx

When using load balanced web servers it’s often useful to know which server processed the request. There is a simple unobtrusive method to achieve this with the Nginx web server. Nginx conveniently populates the server’s real host name to the $hostname variable, meaning that you can simply output this to a custom header in the global config file:

http {
    ...
    # Show server host name as header
    add_header X-Backend-Server $hostname;
}
Share

Showing the correct client IP in logs and scripts when using Nginx behind a reverse proxy

I’ve noticed when it comes to use of reverse proxies such as HAProxy to serve high availability websites that many people seem to struggle to get the real client IP address both in their server logs and scripting languages (e.g. PHP).

This is actually really easy to do, but it seems that the methods are not well known as there are numerous posts on forums and many people resort in attempting to resolve the problem by making code changes in their scripts and using custom logging settings on their web server.

With Nginx it’s EASY! I’m sure you can do it with other web servers too, but Nginx is my web server of choice these days due to it’s low memory footprint, speed and features.

For the sake of an example I’ll explain how this works in the context of the hosting that this website is running on. This is a pair of HAProxy servers in front of a pair of Nginx servers with PHP configured via FPM.

Firstly you need to configure HAProxy to pass the client IP address, which is quite simply done by adding the “forwardfor” and “http-server-close” options to the backend, ensuring that the real client IP reaches the backend web servers via the X-Forwarded-For header. Here is the configuration I’m using for my HTTP backend:

backend http
    mode http
    option httpchk GET /index.html
    balance leastconn
    option http-server-close
    option forwardfor
    server web1 <web1_ip>:80 check inter 1000 fastinter 500 downinter 5000 rise 3 fall 1
    server web2 <web2_ip>:80 check inter 1000 fastinter 500 downinter 5000 rise 3 fall 1

Secondly you need to configure Nginx to use the correct source for the client IP address using the HttpRealIP module.

There are 2 main directives you should define:

  • set_real_ip_from specifies the address of a trusted server (e.g. the load balancer) of which Nginx can replace this address with an untrusted address (the client IP)
  • real_ip_header specifies the source header to find the address to replace the trusted server with

These are also global directives, so can be placed in the main config in the ‘http’ section so that it takes effect for all virtual hosts.

Here is an example for a configuration using 2 load balancers:

http {
...
    set_real_ip_from <load_balancer1_ip>;
    set_real_ip_from <load_balancer2_ip>;
    real_ip_header X-Forwarded-For;
...
}

After making these simple changes (5 lines of configuration in total for a dual load balanced cluster) all http logs will display the correct client IP as will scripting languages see the correct IP in the REMOTE_ADDR header without requiring a single code change.

Share

Virtual and cloud server benchmarks

I’ve been running some benchmarks on a number of popular virtual and cloud service providers, to see what you really get for your money.

All tests are being run on an empty unused server, I have run each test more than once but have generally seen little variation so have only posted the best result for each instance tested.

The final test is taken from a local VM running on my MacBook Pro, just to put things in perspective.

Amazon EC2 small node
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 2.6.32-279.el6.x86_64 -- #1 SMP Wed Jun 13 18:24:36 EDT 2012
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU E5645 @ 2.40GHz (4000.1 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSCALL/SYSRET

------------------------------------------------------------------------
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables        9518989.8 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     1206.3 MWIPS (10.0 s, 7 samples)
Execl Throughput                                523.8 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks         91757.9 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           23763.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        287254.0 KBps  (30.0 s, 2 samples)
Pipe Throughput                              128363.0 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  24769.2 lps   (10.0 s, 7 samples)
Process Creation                               1061.1 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                    922.5 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    124.2 lpm   (60.4 s, 2 samples)
System Call Overhead                         139949.3 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0    9518989.8    815.7
Double-Precision Whetstone                       55.0       1206.3    219.3
Execl Throughput                                 43.0        523.8    121.8
File Copy 1024 bufsize 2000 maxblocks          3960.0      91757.9    231.7
File Copy 256 bufsize 500 maxblocks            1655.0      23763.0    143.6
File Copy 4096 bufsize 8000 maxblocks          5800.0     287254.0    495.3
Pipe Throughput                               12440.0     128363.0    103.2
Pipe-based Context Switching                   4000.0      24769.2     61.9
Process Creation                                126.0       1061.1     84.2
Shell Scripts (1 concurrent)                     42.4        922.5    217.6
Shell Scripts (8 concurrent)                      6.0        124.2    207.0
System Call Overhead                          15000.0     139949.3     93.3
                                                                   ========
System Benchmarks Index Score                                         174.8
Rackspace Cloud 256Mb first generation node
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

4 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

4 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

4 x Execl Throughput  1 2 3

4 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

4 x File Copy 256 bufsize 500 maxblocks  1 2 3

4 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

4 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

4 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

4 x Process Creation  1 2 3

4 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

4 x Shell Scripts (1 concurrent)  1 2 3

4 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 2.6.35.4-rscloud -- #8 SMP Mon Sep 20 15:54:33 UTC 2010
   Machine: x86_64 (unknown)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Quad-Core AMD Opteron(tm) Processor 2374 HE (4400.2 bogomips)
          Hyper-Threading, x86-64, MMX, AMD MMX, Physical Address Ext, SYSCALL/SYSRET
   CPU 1: Quad-Core AMD Opteron(tm) Processor 2374 HE (4400.2 bogomips)
          Hyper-Threading, x86-64, MMX, AMD MMX, Physical Address Ext, SYSCALL/SYSRET
   CPU 2: Quad-Core AMD Opteron(tm) Processor 2374 HE (4400.2 bogomips)
          Hyper-Threading, x86-64, MMX, AMD MMX, Physical Address Ext, SYSCALL/SYSRET
   CPU 3: Quad-Core AMD Opteron(tm) Processor 2374 HE (4400.2 bogomips)
          Hyper-Threading, x86-64, MMX, AMD MMX, Physical Address Ext, SYSCALL/SYSRET

------------------------------------------------------------------------
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       19153340.0 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     1985.4 MWIPS (9.9 s, 7 samples)
Execl Throughput                               1085.3 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        176018.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           47572.4 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        465995.5 KBps  (30.0 s, 2 samples)
Pipe Throughput                              291945.4 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  56698.9 lps   (10.0 s, 7 samples)
Process Creation                               1799.6 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   2981.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    863.4 lpm   (60.0 s, 2 samples)
System Call Overhead                         307516.1 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   19153340.0   1641.2
Double-Precision Whetstone                       55.0       1985.4    361.0
Execl Throughput                                 43.0       1085.3    252.4
File Copy 1024 bufsize 2000 maxblocks          3960.0     176018.5    444.5
File Copy 256 bufsize 500 maxblocks            1655.0      47572.4    287.4
File Copy 4096 bufsize 8000 maxblocks          5800.0     465995.5    803.4
Pipe Throughput                               12440.0     291945.4    234.7
Pipe-based Context Switching                   4000.0      56698.9    141.7
Process Creation                                126.0       1799.6    142.8
Shell Scripts (1 concurrent)                     42.4       2981.9    703.3
Shell Scripts (8 concurrent)                      6.0        863.4   1439.1
System Call Overhead                          15000.0     307516.1    205.0
                                                                   ========
System Benchmarks Index Score                                         396.6

------------------------------------------------------------------------
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables       76752699.2 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     7944.5 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3235.4 lps   (29.8 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        208027.6 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           54390.3 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        594047.8 KBps  (30.1 s, 2 samples)
Pipe Throughput                             1143949.0 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 210447.4 lps   (10.0 s, 7 samples)
Process Creation                               6401.8 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   7176.8 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    944.6 lpm   (60.2 s, 2 samples)
System Call Overhead                        1069117.6 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   76752699.2   6576.9
Double-Precision Whetstone                       55.0       7944.5   1444.5
Execl Throughput                                 43.0       3235.4    752.4
File Copy 1024 bufsize 2000 maxblocks          3960.0     208027.6    525.3
File Copy 256 bufsize 500 maxblocks            1655.0      54390.3    328.6
File Copy 4096 bufsize 8000 maxblocks          5800.0     594047.8   1024.2
Pipe Throughput                               12440.0    1143949.0    919.6
Pipe-based Context Switching                   4000.0     210447.4    526.1
Process Creation                                126.0       6401.8    508.1
Shell Scripts (1 concurrent)                     42.4       7176.8   1692.7
Shell Scripts (8 concurrent)                      6.0        944.6   1574.3
System Call Overhead                          15000.0    1069117.6    712.7
                                                                   ========
System Benchmarks Index Score                                         957.0
Dediserve cloud node 1 CPU 512Mb
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 3.2.0-29-generic -- #46-Ubuntu SMP Fri Jul 27 17:03:23 UTC 2012
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU E5620 @ 2.40GHz (4800.2 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET

------------------------------------------------------------------------
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       23542749.4 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     3071.0 MWIPS (10.0 s, 7 samples)
Execl Throughput                                998.5 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        205473.0 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           51552.4 KBps  (31.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        568092.0 KBps  (31.1 s, 2 samples)
Pipe Throughput                              337505.3 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  58392.7 lps   (10.0 s, 7 samples)
Process Creation                               2536.2 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   2530.3 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    338.4 lpm   (60.1 s, 2 samples)
System Call Overhead                         396422.8 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   23542749.4   2017.4
Double-Precision Whetstone                       55.0       3071.0    558.4
Execl Throughput                                 43.0        998.5    232.2
File Copy 1024 bufsize 2000 maxblocks          3960.0     205473.0    518.9
File Copy 256 bufsize 500 maxblocks            1655.0      51552.4    311.5
File Copy 4096 bufsize 8000 maxblocks          5800.0     568092.0    979.5
Pipe Throughput                               12440.0     337505.3    271.3
Pipe-based Context Switching                   4000.0      58392.7    146.0
Process Creation                                126.0       2536.2    201.3
Shell Scripts (1 concurrent)                     42.4       2530.3    596.8
Shell Scripts (8 concurrent)                      6.0        338.4    563.9
System Call Overhead                          15000.0     396422.8    264.3
                                                                   ========
System Benchmarks Index Score                                         419.1
Rackspace Cloud 512Mb next generation node
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 3.2.0-29-virtual -- #46-Ubuntu SMP Fri Jul 27 17:23:50 UTC 2012
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Quad-Core AMD Opteron(tm) Processor 2374 HE (4400.3 bogomips)
          Hyper-Threading, x86-64, MMX, AMD MMX, Physical Address Ext, SYSCALL/SYSRET

------------------------------------------------------------------------
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       16930050.9 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     2298.9 MWIPS (7.5 s, 7 samples)
Execl Throughput                                727.4 lps   (29.8 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        136192.8 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           36342.7 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        362103.7 KBps  (30.0 s, 2 samples)
Pipe Throughput                              235619.9 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  39268.0 lps   (10.0 s, 7 samples)
Process Creation                               1745.5 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   1868.0 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    256.6 lpm   (60.2 s, 2 samples)
System Call Overhead                         251351.2 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   16930050.9   1450.7
Double-Precision Whetstone                       55.0       2298.9    418.0
Execl Throughput                                 43.0        727.4    169.2
File Copy 1024 bufsize 2000 maxblocks          3960.0     136192.8    343.9
File Copy 256 bufsize 500 maxblocks            1655.0      36342.7    219.6
File Copy 4096 bufsize 8000 maxblocks          5800.0     362103.7    624.3
Pipe Throughput                               12440.0     235619.9    189.4
Pipe-based Context Switching                   4000.0      39268.0     98.2
Process Creation                                126.0       1745.5    138.5
Shell Scripts (1 concurrent)                     42.4       1868.0    440.6
Shell Scripts (8 concurrent)                      6.0        256.6    427.7
System Call Overhead                          15000.0     251351.2    167.6
                                                                   ========
System Benchmarks Index Score                                         292.6
Linode 1024Mb node
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

4 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

4 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

4 x Execl Throughput  1 2 3

4 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

4 x File Copy 256 bufsize 500 maxblocks  1 2 3

4 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

4 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

4 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

4 x Process Creation  1 2 3

4 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

4 x Shell Scripts (1 concurrent)  1 2 3

4 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 3.5.2-x86_64-linode26 -- #1 SMP Wed Aug 15 14:31:07 EDT 2012
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.6 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   CPU 1: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.6 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   CPU 2: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.6 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET
   CPU 3: Intel(R) Xeon(R) CPU L5520 @ 2.27GHz (4533.6 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET

------------------------------------------------------------------------
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       19461187.3 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     2676.3 MWIPS (10.0 s, 7 samples)
Execl Throughput                                804.1 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        233258.3 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           62975.5 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks        716054.5 KBps  (30.0 s, 2 samples)
Pipe Throughput                              367183.5 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  24187.2 lps   (10.0 s, 7 samples)
Process Creation                               1883.9 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   2890.1 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    748.0 lpm   (60.1 s, 2 samples)
System Call Overhead                         386542.8 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   19461187.3   1667.6
Double-Precision Whetstone                       55.0       2676.3    486.6
Execl Throughput                                 43.0        804.1    187.0
File Copy 1024 bufsize 2000 maxblocks          3960.0     233258.3    589.0
File Copy 256 bufsize 500 maxblocks            1655.0      62975.5    380.5
File Copy 4096 bufsize 8000 maxblocks          5800.0     716054.5   1234.6
Pipe Throughput                               12440.0     367183.5    295.2
Pipe-based Context Switching                   4000.0      24187.2     60.5
Process Creation                                126.0       1883.9    149.5
Shell Scripts (1 concurrent)                     42.4       2890.1    681.6
Shell Scripts (8 concurrent)                      6.0        748.0   1246.7
System Call Overhead                          15000.0     386542.8    257.7
                                                                   ========
System Benchmarks Index Score                                         412.9

------------------------------------------------------------------------
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables       48173573.7 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     9156.4 MWIPS (9.8 s, 7 samples)
Execl Throughput                               2730.0 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        370575.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks           97725.5 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1239482.7 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1270353.0 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 169366.3 lps   (10.0 s, 7 samples)
Process Creation                               5901.0 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   6655.8 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    875.8 lpm   (60.2 s, 2 samples)
System Call Overhead                        1344474.1 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   48173573.7   4128.0
Double-Precision Whetstone                       55.0       9156.4   1664.8
Execl Throughput                                 43.0       2730.0    634.9
File Copy 1024 bufsize 2000 maxblocks          3960.0     370575.5    935.8
File Copy 256 bufsize 500 maxblocks            1655.0      97725.5    590.5
File Copy 4096 bufsize 8000 maxblocks          5800.0    1239482.7   2137.0
Pipe Throughput                               12440.0    1270353.0   1021.2
Pipe-based Context Switching                   4000.0     169366.3    423.4
Process Creation                                126.0       5901.0    468.3
Shell Scripts (1 concurrent)                     42.4       6655.8   1569.8
Shell Scripts (8 concurrent)                      6.0        875.8   1459.6
System Call Overhead                          15000.0    1344474.1    896.3
                                                                   ========
System Benchmarks Index Score                                        1065.6
Parallels on OSX 1 CPU 512 Mb
   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: GNU/Linux
   OS: GNU/Linux -- 2.6.32-279.2.1.el6.x86_64 -- #1 SMP Fri Jul 20 01:55:29 UTC 2012
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Core(TM) i7-3720QM CPU @ 2.60GHz (5200.0 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSCALL/SYSRET

------------------------------------------------------------------------
1 CPU in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       38534338.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     4124.1 MWIPS (9.8 s, 7 samples)
Execl Throughput                               4404.0 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        800268.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          229568.8 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2024689.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                             2038687.3 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 309400.1 lps   (10.1 s, 7 samples)
Process Creation                              12695.4 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   5706.9 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    745.0 lpm   (60.0 s, 2 samples)
System Call Overhead                        2822468.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   38534338.6   3302.0
Double-Precision Whetstone                       55.0       4124.1    749.8
Execl Throughput                                 43.0       4404.0   1024.2
File Copy 1024 bufsize 2000 maxblocks          3960.0     800268.5   2020.9
File Copy 256 bufsize 500 maxblocks            1655.0     229568.8   1387.1
File Copy 4096 bufsize 8000 maxblocks          5800.0    2024689.9   3490.8
Pipe Throughput                               12440.0    2038687.3   1638.8
Pipe-based Context Switching                   4000.0     309400.1    773.5
Process Creation                                126.0      12695.4   1007.6
Shell Scripts (1 concurrent)                     42.4       5706.9   1346.0
Shell Scripts (8 concurrent)                      6.0        745.0   1241.7
System Call Overhead                          15000.0    2822468.9   1881.6
                                                                   ========
System Benchmarks Index Score                                        1467.4
Share

Migrating to MySQL 5.5 on Ubuntu

MySQL 5.5 has been GA since December 2010, however there are currently no deb packages available. Ubuntu takes all (or most of) it’s packages from the unstable Debian branch, hence the natural order of things is for Debian maintainers to do the leg work (e.g. creating the build scripts) and then Ubuntu can use this to build similar or newer minor versions for the Ubuntu OS. I suspect that as 5.5 is a major release and there are a considerable number of changes that the build scripts take a considerable amount of time to write and possibly some of the Debian modifications/patches need updates to ensure compatibility too, hence the long delay.

However, we can install MySQL 5.5 from the generic tarball and make a few “tweaks” to maintain the default Ubuntu structures and settings.

There are more straight forward ways to install MySQL, however the intention of this guide is to allow us to easily upgrade via multiple future available routes with minimal effort (e.g. via deb packages, or in their absence newer generic tar distributions).

1. Create user/group

Note: I manually chose system group ids looking at the latest system group id in /etc/passwd and /etc/group

groupadd -r -g 108 mysql
useradd -r -g mysql -u 106 mysql

2. Create folders

mkdir /var/lib/mysql
mkdir /var/log/mysql
mkdir /usr/lib/mysql
mkdir /usr/share/mysql
mkdir -p /etc/mysql/conf.d
mkdir /var/run/mysqld

3. Set a few folder permissions

chown mysql:adm /var/log/mysql
chmod 750 /var/log/mysql/
chmod g+s /var/log/mysql/
chown mysql:mysql /var/run/mysqld

4. Download the source and copy/move it to the default install folder in /usr/local. (This is not standard Ubuntu, however due to some of the compilation options on the tar package it avoids a few issues but maintains Ubuntu paths.)

wget http://www.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.8-linux2.6-x86_64.tar.gz/from/ftp://ftp.mirrorservice.org/sites/ftp.mysql.com/
tar xzf mysql-5.5.8-linux2.6-x86_64.tar.gz
mv mysql-5.5.8-linux2.6-x86_64 mysql
mv mysql /usr/local/

5. Move files to the Ubuntu locations and create simlinks “just in case” MySQL has something hard coded into the build that cannot be changed via the config.

cd /usr/local/mysql/
mv bin/* /usr/bin/
rmdir bin/
ln -s /usr/bin/
cp lib/libmysqlclient* /usr/lib
cp -r lib/plugin /usr/lib/mysql/
cp support-files/* /usr/share/mysql
cp -r share/* /usr/share/mysql
rm -r share
ln -s /usr/share/mysql share

6. Create the default data files and move them to /var/lib/mysql

scripts/mysql_install_db
cp -r data/* /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
chmod -R 700 /var/lib/mysql
rm -r data
ln -s /var/lib/mysql data

7. Copy the init script over to /etc/init.d and modify to suit our needs

cp support-files/mysql.server /etc/init.d/mysql

Edit with your favorite text editor and ensure the following are set:

basedir=/usr/local/mysql
datadir=/var/lib/mysql

8. Add my.cnf, the default 5.1 file will do, with 1 or 2 modifications. Specifically, check the basedir and datadir are set correctly, ensure Innodb is the default storage engine (as per 5.5) and note the new syntax for slow query logging (disabled by default). It would be advisable to set common Innodb options, e.g. pool size.

#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port            = 3306
socket          = /var/run/mysqld/mysqld.sock

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0

[mysqld]
#
# * Basic Settings
#

#
# * IMPORTANT
#   If you make changes to these settings and your system uses apparmor, you may
#   also need to also adjust /etc/apparmor.d/usr.sbin.mysqld.
#

user            = mysql
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr/local/mysql
datadir         = /var/lib/mysql
tmpdir          = /tmp
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address            = 127.0.0.1
#
# * Fine Tuning
#
key_buffer              = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover         = BACKUP
#max_connections        = 100
#table_cache            = 64
#thread_concurrency     = 10
#
# * Query Cache Configuration
#
query_cache_limit       = 1M
query_cache_size        = 16M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file        = /var/log/mysql/mysql.log
#general_log             = 1

log_error                = /var/log/mysql/error.log

# Here you can see queries with especially long duration
#slow-query-log
#slow-query-log-file     = /var/log/mysql/mysql-slow.log
#long_query_time         = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
#server-id              = 1
#log_bin                        = /var/log/mysql/mysql-bin.log
expire_logs_days        = 10
max_binlog_size         = 100M
#binlog_do_db           = include_database_name
#binlog_ignore_db       = include_database_name

#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
default_storage_engine  = InnoDB

#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem



[mysqldump]
quick
quote-names
max_allowed_packet      = 16M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completition

[isamchk]
key_buffer              = 16M

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/

9. Start the server!

/etc/init.d/mysql start

If the server fails to start, check /var/log/mysql/error.log for clues.

Share

Web server benchmark PHP – Apache vs Nginx vs Lighttpd

This is a quick benchmark of the 3 major *nix web servers, to see which gives the best performance.

Test system:

Hardware: vps247 cloud VPS node, 512Mb ram.
Software: Ubuntu 10.10 RC (kernel 2.6.35-22), Apache 2.2.16 (mod_php), Nginx 0.7.67 (php-fpm), Lighttpd 1.4.26 (php-cgi), PHP 5.3.3 with Xcache.
Site: LiteMVC 0.1 Hello World.

Test process:

Using ab with 10,000 requests, 10 concurrent requests.
Monitoring load/memory usage with htop.
All web servers with default configuration, 1 site enabled.
All tests were repeated 3 times.

Apache 2.2.16:

Test 1 Test 2 Test 3
Load at start: 0.03
Memory usage at start: 130 Mb
Load average max: 15.88
Memory usage max: 290 Mb
Requests per second: 400.04
Time per request: 2.5 ms
Longest request: 806 ms
Load at start: 0.07
Memory usage at start: 130 Mb
Load average max: 21.73
Memory usage max: 332 Mb
Requests per second: 395.49
Time per request: 2.529 ms
Longest request: 728 ms
Load at start: 0.06
Memory usage at start: 121 Mb
Load average max: 20.95
Memory usage max: 253 Mb
Requests per second: 385.82
Time per request: 2.592 ms
Longest request: 937 ms

Nginx 0.7.67:

Test 1 Test 2 Test 3
Load at start: 0.05
Memory usage at start: 129 Mb
Load average max: 0.77
Memory usage max: 157 Mb
Requests per second: 413.40
Time per request: 2.419 ms
Longest request: 239 ms
Load at start: 0.05
Memory usage at start: 152 Mb
Load average max: 0.93
Memory usage max: 169 Mb
Requests per second: 409.15
Time per request: 2.444 ms
Longest request: 232 ms
Load at start: 0.00
Memory usage at start: 163 Mb
Load average max: 0.61
Memory usage max: 169 Mb
Requests per second: 415.28
Time per request: 2.408 ms
Longest request: 250 ms

Lighttpd 1.4.26:

Test 1 Test 2 Test 3
Load at start: 0.00
Memory usage at start: 115 Mb
Load average max: 0.81
Memory usage max: 139 Mb
Requests per second: 427.92
Time per request: 2.337 ms
Longest request: 120 ms
Load at start: 0.09
Memory usage at start: 136 Mb
Load average max: 0.73
Memory usage max: 143 Mb
Requests per second: 447.10
Time per request: 2.237 ms
Longest request: 111 ms
Load at start: 0.03
Memory usage at start: 140 Mb
Load average max: 0.69
Memory usage max: 159 Mb
Requests per second: 454.13
Time per request: 2.202 ms
Longest request: 178 ms

Conclusions:

Lighttpd was the fastest overall in this test, however what probably stands out the most is the inefficiency of Apache with both server load and memory usage increasing considerably during the test. The reason for this may be down to Apache spawning additional processes when it is receiving a large volume of requests, which results in the higher memory usage. The memory usage with Nginx and Lighttpd increases by a much smaller amount because each of them runs a fixed number of PHP CGI processes (20 in this case).

Apache is definitely the winner in terms of module support and ease of configuration, but I may have a somewhat biased view as I’ve worked with Apache for years. Nginx is probably the hardest to setup and configure, however after switching from PHP-CGI to PHP-FPM this made things easier and it does seam there are more configuration examples floating around on the net than for Lighttpd. Lighttpd is notorious for memory leaks, I’m not sure if this is still an issue with current versions.

Share

Today is a confusing day for 32 bit PHP

As many people probable know, there are some glaring inconsistencies between 32 bit and 64 bit PHP, especially when it comes to large numbers and floats.

For some reason, best known to the PHP developers, 32 bit PHP is limited to the maximum signed 32 bit integer size of 2147483647, while 64 bit PHP uses the 64 bit equivalent of 9223372036854775807. Many languages overcome the 32 bit / 64 bit differences by storing 64 bit ints as 2 32 bit ints to allow the usage of 64 bit integers on 32 bit systems, hence providing complete consistency between the two platforms.

These inconsistencies similarly apply to floating point precession, presumably a float in 32 bit PHP is equivalent to a 32 bit float in C, whereas it appears that in 64 bit PHP it’s actually a double.

Here is a nice example of the inconsistency, today’s unix timestamp in float form:

32 bit:

php > echo (float) 1285200000;
1.2852E+9

64 bit:

php > echo (float) 1285200000;
1285200000

This is an important thing to remember with PHP, despite the fact it is a loosely typed language, they behaviour is equivalent to the C behaviour for the particular architecture of your server.

Share

Neat trick to beat the sendmail FQDN check

When you install sendmail on a local machine and want to test some mail sending feature of your project, sendmail has a tendency to hang for a couple of minutes each time you try and send mail.

Looking in the /var/log/mail.log will reveal it is trying to determine the fully qualified domain name:

Sep 16 09:20:01 MyHostName sm-msp-queue[14171]: My unqualified host name (MyHostName) unknown; sleeping for retry
Sep 16 09:21:01 MyHostName sm-msp-queue[14171]: unable to qualify my own domain name (MyHostName) -- using short name

Here is a quick fix which resolves the problem:

1. Edit /etc/hosts
2. Change the record for 127.0.0.1 so that it looks something like this

127.0.0.1 localhost.localdomain localhost MyHostName

3. Restart sendmail

This now makes sendmail think it’s FQDN is localhost.localdomain, and mail now sends instantly!

Share

Setting up MySQL replication with SSL

There are many posts out there on how to setup both MySQL replication and self signed SSL certificates but not really any that combine the 2 very well. This post is partly for my own reference and partly for anyone else who is interested in the subject.

To enable SSL replication both the client and server require signed certificates, these could be a purchased certificate from a common CA but really as they are only going to be used for private communication there is no need and a self signed certificate will do the job.

Please note, that for the section of this post which discusses the MySQL replication, I am assuming that you already know how to setup replication, including ensuring data is consistent on master/slave. The focus of his article is to document the additional configuration required to setup replication with SSL.

For the purpose of this example I will be configuring the following hosts:

master.example.com - The MySQL replication master
slave.example.com - The MySQL replication slave

Creating the certificates:

The first thing to do is to create a certificate authority in order to sign the certificates, this is based on the Ubuntu Documentation with a few changes.

First, create some directories to organise things and change into the new CA directory:

mkdir -p CA/private
mkdir -p CA/certs
cd CA

Create a certificate database:

echo '01' > serial  && touch index.txt

Create a configuration for the CA:

nano ca.conf
# Example CA config file
#
# Default configuration to use when one is not provided on the command line.
#
[ ca ]
default_ca      = local_ca
#
#
# Default location of directories and files needed to generate certificates.
#
[ local_ca ]
dir             = /home/<strong style="color:red">user</strong>/CA
certificate     = $dir/ca.pem
database        = $dir/index.txt
new_certs_dir   = $dir/certs
private_key     = $dir/private/cakey.pem
serial          = $dir/serial
#      
#
# Default expiration and encryption policies for certificates.
#
default_crl_days        = 365
default_days            = 1825
default_md              = md5
#      
policy          = local_ca_policy
x509_extensions = local_ca_extensions
#      
#
# Default policy to use when generating server certificates.  The following
# fields must be defined in the server certificate.
#
[ local_ca_policy ]
commonName              = supplied
stateOrProvinceName     = supplied
countryName             = supplied
emailAddress            = supplied
organizationName        = supplied
organizationalUnitName  = supplied
#      
#
# x509 extensions to use when generating server certificates.
#
[ local_ca_extensions ]
subjectAltName          = DNS:example.com
basicConstraints        = CA:false
nsCertType              = server
#      
#
# The default root certificate generation policy.
#
[ req ]
default_bits    = 2048
default_keyfile = /home/<strong style="color:red">user</strong>/CA/private/cakey.pem
default_md      = md5
#      
prompt                  = no
distinguished_name      = root_ca_distinguished_name
x509_extensions         = root_ca_extensions
#
#
# Root Certificate Authority distinguished name.  Change these fields to match
# your local environment!
#
[ root_ca_distinguished_name ]
commonName              = <strong style="color:green">My  Certificate Authority</strong>
stateOrProvinceName     = <strong style="color:green">London</strong>
countryName             = <strong style="color:green">GB</strong>
emailAddress            = <strong style="color:green">ca@example.com</strong>
organizationName        = <strong style="color:green">My Company Name</strong>
organizationalUnitName  = <strong style="color:green">IT Department</strong>
#      
[ root_ca_extensions ]
basicConstraints        = CA:true

You will need to change the user in red with your Linux username and the CA info in green.

Now generate the CA certificate with the following:

openssl req -x509 -newkey rsa:2048 -out ca.pem -outform PEM -days 1825 -config ca.conf

You will be prompted for a passphrase:

Generating a 2048 bit RSA private key
...............................................+++
...................................................................................+++
writing new private key to '/home/phil/CA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----

We now have a certificate and key which we can use to sign the certificates. The next stage is to create certificates for each of our 2 hosts (or more, if more than 2 hosts are being configured in the replication setup).

Create a config file for each host:

nano master.conf
#
# Config file for master.example.com
#

[ req ]
prompt                  = no
distinguished_name      = server_distinguished_name

[ server_distinguished_name ]
commonName              = <strong style="color:green">master.example.com</strong>
stateOrProvinceName     = <strong style="color:green">London</strong>
countryName             = <strong style="color:green">GB</strong>
emailAddress            = <strong style="color:green">ca@example.com</strong>
organizationName        = <strong style="color:green">My Company Name</strong>
organizationalUnitName  = <strong style="color:green">IT Department</strong>
nano slave.conf
#
# Config file for slave.example.com
#

[ req ]
prompt                  = no
distinguished_name      = server_distinguished_name

[ server_distinguished_name ]
commonName              = <strong style="color:green">slave.example.com</strong>
stateOrProvinceName     = <strong style="color:green">London</strong>
countryName             = <strong style="color:green">GB</strong>
emailAddress            = <strong style="color:green">ca@example.com</strong>
organizationName        = <strong style="color:green">My Company Name</strong>
organizationalUnitName  = <strong style="color:green">IT Department</strong>

Change the bits in green to your company name, the commonName must be the host name of the machine, this is important or the certificate will be invalid.

The next step is to create a certificate signing request (CSR) and private key for each of our hosts:

openssl req -newkey rsa:1024 -keyout master.key.pem -keyform PEM -out master.csr.pem -outform PEM -config master.conf

You will be prompted for a passphrase again:

Generating a 1024 bit RSA private key
..++++++
.++++++
writing new private key to 'master.key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----

Repeat for slave (and additional hosts):

openssl req -newkey rsa:1024 -keyout slave.key.pem -keyform PEM -out slave.csr.pem -outform PEM -config slave.conf
Generating a 1024 bit RSA private key
....................++++++
....++++++
writing new private key to 'slave.key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----

Now in their current form the keys we have just generated will require the passphrase every time we start the server, this is far from ideal as MySQL will have to be manually started every time the server is rebooted (intentionally or not).

We can create an unencrypted version of the keys so that the passphrase is not required for server starts:

openssl rsa < master.key.pem > master.dckey.pem
Enter pass phrase:
writing RSA key
openssl rsa < slave.key.pem > slave.dckey.pem
Enter pass phrase:
writing RSA key

Finally, we can sign the certificate requests for each host with our CA:

openssl ca -in master.csr.pem -out master.crt.pem -config ca.conf
Using configuration from ca.conf
Enter pass phrase for /home/phil/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :PRINTABLE:'master.example.com'
stateOrProvinceName   :PRINTABLE:'London'
countryName           :PRINTABLE:'GB'
emailAddress          :IA5STRING:'ca@example.com'
organizationName      :PRINTABLE:'My Company Name'
organizationalUnitName:PRINTABLE:'IT Department'
Certificate is to be certified until Aug 26 08:56:20 2015 GMT (1825 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
openssl ca -in slave.csr.pem -out slave.crt.pem -config ca.conf
Using configuration from ca.conf
Enter pass phrase for /home/phil/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :PRINTABLE:'slave.example.com'
stateOrProvinceName   :PRINTABLE:'London'
countryName           :PRINTABLE:'GB'
emailAddress          :IA5STRING:'ca@example.com'
organizationName      :PRINTABLE:'My Company Name'
organizationalUnitName:PRINTABLE:'IT Department'
Certificate is to be certified until Aug 26 08:57:52 2015 GMT (1825 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Configuring the servers:

We will need to copy 3 files to each machine:

ca.pem – The CA certificate

On the master:

master.crt.pem – The master certificate
master.key.pem or master.dckey.pem – Either the encrypted or decrypted version of the master private key

On the slave:

slave.crt.pem – The slave certificate
slave.key.pem or slave.dckey.pem – Either the encrypted or decrypted version of the slave private key

These files should be copied into /etc/mysql on the respective hosts.

On the master, create a user for replication:

CREATE USER slave@slave.example.com IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO slave@slave.example.com REQURE SSL;

Note that the addition of the ‘REQUIRE SSL’ at the end of the grant statement, this means insecure connections from the slave will not be possible.

Create the configuration on the master for replication:

server-id = 1
report_host = master
# These should be used for multiple masters
#auto_increment_increment = 2
#auto_increment_offset   = 1
log_bin = /var/log/mysql/binlog
log_bin_index = /var/log/mysql/binlog.index
sync_binlog = 1
expire_logs_days = 10
max_binlog_size = 100M
binlog_do_db = mydb
#binlog_do_db = myotherdb
binlog_ignore_db = mysql

Also we need to add the SSL configuration:

ssl-ca = /etc/mysql/ca.pem
ssl-cert = /etc/mysql/master.crt.pem
ssl-key = /etc/mysql/master.dckey.pem

Restart MySQL to apply the configuration:

sudo /etc/init.d/mysql restart

or (in newer versions with upstart):

restart mysql

Then configure the slave for replication:

server-id = 2
report_host = slave
relay_log = /var/log/mysql/relay-bin
relay_log_index = /var/log/mysql/relay-bin.index
relay_log_info_file = /var/log/mysql/relay-bin.info
master_host = master.example.com
master_user = slave
master_password = password
master_port = 3306
master_ssl = 1
master_ssl_ca = /etc/mysql/ca.pem
master_ssl_cert = /etc/mysql/slave.crt.pem
master_ssl_key = /etc/mysql/slave.dckey.pem
replicate_do_db = mydb
#replicate_do_db = myotherdb
replicate_ignore_db = mysql
read_only

Restart MySQL, and everything should be up and running.

From the master we should see something like this:

show master status\G
*************************** 1. row ***************************
            File: binlog.000001
        Position: 106
    Binlog_Do_DB: mydb
Binlog_Ignore_DB: mysql
1 row in set (0.00 sec)
show slave hosts\G
*************************** 1. row ***************************
        Server_id: 2
             Host: slave
             Port: 3306
Rpl_recovery_rank: 0
        Master_id: 1
1 row in set (0.00 sec)

And on the slave:

show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master.example.com
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000001
          Read_Master_Log_Pos: 106
               Relay_Log_File: relay-bin.000001
                Relay_Log_Pos: 253
        Relay_Master_Log_File: binlog.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: mydb
          Replicate_Ignore_DB: mysql
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 106
              Relay_Log_Space: 549
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: Yes
           Master_SSL_CA_File: /etc/mysql/ca.pem
           Master_SSL_CA_Path:
              Master_SSL_Cert: /etc/mysql/slave.crt.pem
            Master_SSL_Cipher:
               Master_SSL_Key: /etc/mysql/slave.dckey.pem
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
1 row in set (0.02 sec)

Note: The status info above I copy/pasted from a live replication setup and replaced with values that you can expect to see, values will likely differ (especially log file positions).

Share