<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Shell Tips ! &#187; Case Study</title>
	<atom:link href="http://www.shell-tips.com/category/case-study/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.shell-tips.com</link>
	<description>Some useful tips about CLI tools, Shell scripts and batch files... GNU Bash, Windows XP, SQL, Help Sheets / Cheat Sheets, etc.</description>
	<lastBuildDate>Mon, 14 Jun 2010 08:56:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Graphing Java JMX Object values with Ganglia and Python using JPype</title>
		<link>http://www.shell-tips.com/2010/05/31/graphing-java-jmx-object-values-with-ganglia-and-python-using-jpype/</link>
		<comments>http://www.shell-tips.com/2010/05/31/graphing-java-jmx-object-values-with-ganglia-and-python-using-jpype/#comments</comments>
		<pubDate>Mon, 31 May 2010 10:00:54 +0000</pubDate>
		<dc:creator>Nicolas Brousse</dc:creator>
				<category><![CDATA[Case Study]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Ganglia]]></category>
		<category><![CDATA[graphing]]></category>
		<category><![CDATA[JMX]]></category>
		<category><![CDATA[JPype]]></category>
		<category><![CDATA[monitoring]]></category>

		<guid isPermaLink="false">http://www.shell-tips.com/?p=157</guid>
		<description><![CDATA[With Ganglia, graphing a large number of servers has never been so easy&#8230; Ganglia is a scalable distributed monitoring system for high-performance computing systems such as clusters and Grids. Ganglia let you create any kind of module in C/C++ or Python. You can also use the command line tool Gmetric and then the scripting language [...]]]></description>
			<content:encoded><![CDATA[<p>With <a title="Ganglia SF.net" href="http://ganglia.sourceforge.net" target="_self">Ganglia</a>, graphing a large number of servers has never been so easy&#8230; <em>Ganglia is a scalable distributed monitoring system for high-performance  computing systems such as clusters and Grids.</em> Ganglia let you create any kind of module in C/C++ or Python. You can also use the command line tool <a title="Gmetric Scripts" href="http://ganglia.sourceforge.net/gmetric" target="_self">Gmetric</a> and then the scripting language of your choice. The problem with Gmetrics is that you can&#8217;t keep your data organized by group and it&#8217;s getting harder to poll values in an efficient way. Few months ago I needed to monitor some <a title="JMX on Wikipedia" href="http://en.wikipedia.org/wiki/Java_Management_Extensions" target="_self">JMX</a> values returned by a Java daemon.</p>
<p><span id="more-157"></span></p>
<p>This post is quite succinct as I consider you already know Ganglia, Python and Java.</p>
<p>To monitor Java JMX values with Ganglia, I used <a title="JPype on SF.net" href="http://jpype.sourceforge.net" target="_self">JPype</a>. <em>JPype is an effort to allow python programs full access to java class libraries.</em> This allowed me to port easily the JMX <a title="Munin Project" href="http://munin-monitoring.org" target="_self">Munin</a> plugin, you can get this plugin on <a title="Munin Exchange" href="http://su.pr/2BxAab" target="_self">Munin Exchange</a>. The port, is really basic as I just converted few method to make sure I can publicly access them from the Python module. You can take a look at the <a href="http://www.shell-tips.com/wp-content/uploads/jmxquery.patch.txt">jmxquery.patch</a> or download <a href="http://www.shell-tips.com/wp-content/uploads/jmxquery.jar_.tar.gz">jmxquery.jar</a>.</p>
<pre class="brush:diff">diff -urBN jmxquery.a/src/jmxquery/src/org/munin/JMXQuery.java jmxquery.b/src/jmxquery/src/org/munin/JMXQuery.java
--- jmxquery.a/src/jmxquery/src/org/munin/JMXQuery.java	2007-05-14 01:07:44.000000000 -0700
+++ jmxquery.b/src/jmxquery/src/org/munin/JMXQuery.java	2010-01-15 15:40:00.000000000 -0800
@@ -61,7 +61,7 @@
 		this.password = password;
 	}

-	private void connect() throws IOException
+	public void connect() throws IOException
 	{
 		Map environment = null;
 		if (username != null &amp;&amp; password != null)
@@ -78,7 +78,18 @@
 		connection = connector.getMBeanServerConnection();
 	}

-	private void list() throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException
+	public void ping() throws IOException
+	{
+	  try {
+	    MBeanServerConnection testConnection = connector.getMBeanServerConnection();
+	    if (testConnection == null)
+	       this.connect();
+	  } catch (IOException e) {
+	    this.connect();
+	  }
+	}
+
+	public void list() throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException
 	{
 		if (config == null)
 		{
@@ -90,7 +101,7 @@
 		}
 	}

-	private void listConfig()
+	public void listConfig()
 	{
 		for (FieldProperties field : config.getFields())
 		{
@@ -107,7 +118,22 @@
 		}
 	}

-	private void output(String name, Object attr, String key)
+	public String output(String name, String JmxObjectName, String JmxAttributeName, String Key)
+	{
+    try
+    {
+      Object value = connection.getAttribute(new ObjectName(JmxObjectName), JmxAttributeName);
+      return output(name, value, Key);
+    }
+    catch (Exception e)
+    {
+      System.err.println("Fail to output " + name);
+      e.printStackTrace();
+    }
+    return null;
+	}
+
+	public String output(String name, Object attr, String key)
 	{
 		if (attr instanceof CompositeDataSupport)
 		{
@@ -116,15 +142,17 @@
 			{
 				throw new IllegalArgumentException("Key is null for composed data " + name);
 			}
-			System.out.println(name + ".value " + format(cds.get(key)));
+			//System.out.println(name + ".value " + format(cds.get(key)));
+			return format(cds.get(key));
 		}
 		else
 		{
-			System.out.println(name + ".value " + format(attr));
+			//System.out.println(name + ".value " + format(attr));
+		  return format(attr);
 		}
 	}

-	private void output(String name, Object attr)
+	public void output(String name, Object attr)
 	{
 		if (attr instanceof CompositeDataSupport)
 		{
@@ -142,7 +170,7 @@
 	}

 	@SuppressWarnings("unchecked")
-	private void listAll() throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException
+	public void listAll() throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException
 	{
 		Set<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><embed type="application/x-shockwave-flash" width="100" height="100"></embed></object></pre>
<p>Once JPype is installed, make sure your Ganglia is configured with the python module.</p>
<pre class="brush:text"># The modules section describes the module
#  that should be loaded.
#   name - module name
#   path - load path of the .so
#   params - path to the directory where mod_python
#             should look for python metric modules
modules {
  module {
    name = "python_module"
    path = "modpython.so"
    params = "/opt/ganglia/python_modules"
  }
}

include ('/opt/ganglia/etc/conf.d/*.pyconf')
</pre>
<p>Then you can use this basic <a href="http://www.shell-tips.com/wp-content/uploads/jmx.py_.txt">jmx python</a> module:</p>
<pre class="brush:python">"""
Ganglia Module to graph JMX values using JPype
Author: Nicolas Brousse
"""
from jpype import *

import os, platform, sys, time

debug = 0

_jmx = None
_jmx_cur_status = {}
_jmx_pre_status = {}
_jmx_pre_time = {}
_eta = 0
_jmx_params = {'User': '',
              'Password': '',
              'Host': '127.0.0.1',
              'Port': '8989',
              'JMXWrapper': '/opt/ganglia/jmxquery.jar'}

descriptors = []

gauge_metrics = {}

def Metric_Handler(name):
    global _jmx

    if _jmx is None:
        _jmx = initJVM()

    pre = None
    cur = 0
    eta = 0

    if debug:
        print "[ DEBUG ] _jmx_cur_status length: %d" % len(_jmx_cur_status)
        print "[ DEBUG ] _jmx_pre_status length: %d" % len(_jmx_pre_status)

    if _jmx is None:
        raise TypeError("No valid JMX Object !")

    if name in _jmx_cur_status:
        _jmx_pre_status[name] = _jmx_cur_status[name]

    for d in descriptors:
        if d['name'] == name:
            break

    try:
        if "jmxKeyName" in d:
            key = d['jmxKeyName']
        else:
            key = None

        if debug:
            print "[ DEBUG ] _jmx.output(%s, %s, %s, %s)" % \
                (d['name'], d['jmxObjectName'], d['jmxAttributeName'], key)

        _jmx.ping()
        result = _jmx.output(d['name'], d['jmxObjectName'], d['jmxAttributeName'], key)
    except:
        print "Error: ", sys.exc_info()[1]
        raise

    if result.isdigit():
        if debug: print "[ DEBUG ] %s: %s" % (name, result)
        _jmx_cur_status[name] = result

        cur_time = time.time()
        if name in _jmx_pre_time:
            eta = cur_time - _jmx_pre_time[name]
            if debug:
                print '[ DEBUG ] ETA: %d, Last time: %d, Cur time: %d' % (eta, _jmx_pre_time[name], cur_time)

        _jmx_pre_time[name] = cur_time

    if name in _jmx_cur_status:
        cur = _jmx_cur_status[name]
    else:
        cur = 0
    if len(_jmx_pre_status) &gt; 0 and name in _jmx_pre_status:
        pre = _jmx_pre_status[name]
    else:
        pre = 0
    eta = int(eta)

    if name in gauge_metrics:
        if pre is not None and eta &gt; 0:
            ret = (long(cur) - long(pre)) / eta
        else:
            ret = 0
    else:
        ret = cur

    if debug:
        print "[ DEBUG ] Metric_Handler(%s): %s (eta: %s, cur: %s, pre: %s)" % (name, ret, eta, cur, pre)

    return long(ret)

def Init_Metric (name, jmxObjectName, jmxAttributeName, jmxKeyName, tmax, type, slope, units, fmt, handler):
    '''Create a metric definition dictionary object.'''
    d = {'name': name.lower(),
        'jmxObjectName': jmxObjectName,
        'jmxAttributeName': jmxAttributeName,
        'jmxKeyName': jmxKeyName,
        'call_back': handler,
        'time_max': tmax,
        'value_type': type,
        'units': units,
        'slope': slope,
        'format': fmt,
        'description': 'JMX '+name.replace("_"," "),
	    'groups': 'jmx'}
    return d

def metric_init(params):
    global _jmx, _jmx_params

    if debug: print "[ DEBUG ] metric_init()"

    if 'User' in params:
        _jmx_params['User'] = params['User']

    if 'Password' in params:
        _jmx_params['Password'] = params['Password']

    if 'Host' in params:
        _jmx_params['Host'] = params['Host']

    if 'Port' in params:
        _jmx_params['Port'] = int(params['Port'])

    if 'JMXWrapper' in params:
        _jmx_params['JMXWrapper'] = params['JMXWrapper']

    return descriptors

def initJVM():
    if debug: print "[ DEBUG ] initJVM()"

    if platform.architecture()[0] == "32bit":
        arch="i386"
    else:
        arch="amd64"

    jvm="/usr/java/jdk/jre/lib/%s/client/libjvm.so" % arch
    if not os.path.isfile(jvm):
        jvm="/usr/java/jdk/jre/lib/%s/server/libjvm.so" % arch
        if not os.path.isfile(jvm):
            raise IOError("Can't find the libjvm.so (%s)" % jvm)

    if not os.path.isfile(_jmx_params['JMXWrapper']):
        raise IOError("Can't find the JMX Wrapper at'%s'" % \
            _jmx_params['JMXWrapper'])

    try:
        startJVM(jvm, "-Djava.class.path=%s" % _jmx_params['JMXWrapper'])

        url = "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi" % \
               (_jmx_params['Host'], int(_jmx_params['Port']))

        JMXQuery = JClass("org.munin.JMXQuery")

        if _jmx_params['Password'] is not '':
            _jmx = JMXQuery(url, username, password)
        else:
            _jmx = JMXQuery(url)

        _jmx.connect()
    except:
        print "Error: ", sys.exc_info()[1]
        raise

    return _jmx

def metric_cleanup():
    '''Clean up the metric module.'''
    #shutdownJVM()

def Build_Conf():
    print "modules {\n module {\n  name = \"jmx\"\n  language = \"python\"\n }\n}\n"
    print "collection_group {\n collect_every = 30\n time_threshold = 60"
    for d in descriptors:
        print " metric {\n  name = \""+d['name']+"\"\n  title = \""+d['description']+"\"\n  value_threshold = 1.0\n }"
    print "}\n"

descriptors.append(
    Init_Metric("java_cpu_time", "java.lang:type=Threading", "CurrentThreadCpuTime", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_cpu_user_time", "java.lang:type=Threading", "CurrentThreadUserTime", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_nonheap_committed", "java.lang:type=Memory", "NonHeapMemoryUsage", "committed",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_nonheap_max", "java.lang:type=Memory", "NonHeapMemoryUsage", "max",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_nonheap_used", "java.lang:type=Memory", "NonHeapMemoryUsage", "used",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_heap_committed", "java.lang:type=Memory", "HeapMemoryUsage", "committed",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_heap_used", "java.lang:type=Memory", "HeapMemoryUsage", "used",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_memory_heap_max", "java.lang:type=Memory", "HeapMemoryUsage", "max",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("os_memory_physical", "java.lang:type=OperatingSystem", "FreePhysicalMemorySize", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("os_memory_vm", "java.lang:type=OperatingSystem", "CommittedVirtualMemorySize", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_thread_count", "java.lang:type=Threading", "ThreadCount", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))
descriptors.append(
    Init_Metric("java_thread_count_peak", "java.lang:type=Threading", "PeakThreadCount", "",
        int(300), 'uint', 'both', '', '%u', Metric_Handler))

#This code is for debugging and unit testing
if __name__ == '__main__':
    try:
        if len(sys.argv) &lt;= 1:
            debug = 1

        metric_init(_jmx_params)

        if len(sys.argv) &lt;= 1:
            while True:
                for d in descriptors:
                    v = d['call_back'](d['name'])
                time.sleep(5)
        elif sys.argv[1] == "config":
            Build_Conf()
            metric_cleanup()

    except KeyboardInterrupt:
        print "Process interrupted."
        if _JMX_WorkerThread.running and not _JMX_WorkerThread.shuttingdown:
            _JMX_WorkerThread.shutdown()
        time.sleep(0.2)
        sys.exit(1)
</pre>
<p>You can simply run &#8220;<em>python jmx.py config</em>&#8221; to generate the jmx.pyconf file. Also, you&#8217;d probably need to edit the plugin to check for your own JMX values. A lot of improvement could be done to this plugin, but all the basics are there and it can give you some awesome graph to monitor your Java application.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F&amp;title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F&amp;title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F&amp;title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F&amp;headline=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;u=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F&amp;title=Graphing+Java+JMX+Object+values+with+Ganglia+and+Python+using+JPype&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.shell-tips.com%2F2010%2F05%2F31%2Fgraphing-java-jmx-object-values-with-ganglia-and-python-using-jpype%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.shell-tips.com/2010/05/31/graphing-java-jmx-object-values-with-ganglia-and-python-using-jpype/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using losetup and dd to secure sensitive data (encrypted block device)</title>
		<link>http://www.shell-tips.com/2008/07/13/using-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device/</link>
		<comments>http://www.shell-tips.com/2008/07/13/using-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device/#comments</comments>
		<pubDate>Sat, 12 Jul 2008 22:26:06 +0000</pubDate>
		<dc:creator>Nicolas Brousse</dc:creator>
				<category><![CDATA[Bash - GNU Shell]]></category>
		<category><![CDATA[Case Study]]></category>
		<category><![CDATA[dd]]></category>
		<category><![CDATA[device]]></category>
		<category><![CDATA[encrypt]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[losetup]]></category>
		<category><![CDATA[secure]]></category>

		<guid isPermaLink="false">http://www.shell-tips.com/?p=41</guid>
		<description><![CDATA[My previous post was made a long time ago, so here is a draft that I finally decide to post. Let&#8217;s see how to secure some of your data with an encrypted block device using losetup and dd. Steps will be : Create an image with dd Build a new device using the image with [...]]]></description>
			<content:encoded><![CDATA[<p>My previous post was made a long time ago, so here is a draft that I finally decide to post. Let&#8217;s see how to secure some of your data with an encrypted block device using losetup and dd.</p>
<p>Steps will be :</p>
<ol>
<li>Create an image with dd</li>
<li>Build a new device using the image with an encrypt algorythm by using losetup</li>
<li>Format the device using mkfs.ext3</li>
<li>Mount the device and start using it !</li>
</ol>
<p>Of course, when you have mounted the device, your data are readable to anyone who have access to the mounted directory.</p>
<p><span id="more-41"></span></p>
<p><strong>Create an image with dd</strong></p>
<pre class="brush:bash">root@vm-ubuntu-lamp:~# dd if=/dev/zero of=encrypted.img bs=4k count=1000 seek=4001
1000+0 records in
1000+0 records out
4096000 bytes (4,1 MB) copied, 0,10063 seconds, 40,7 MB/s
We now have a raw image file using 4MB.
<blockquote>

root@vm-ubuntu-lamp:~# ls -l encrypted.img
-rw-r--r-- 1 root root 20484096 2008-07-12 13:38 encrypted.img
root@vm-ubuntu-lamp:~# du -hs encrypted.img
4,0M    encrypted.img</blockquote>
</pre>
<p><strong>Create the encrypted device</strong></p>
<blockquote><p>root@vm-ubuntu-lamp:~# losetup -e aes /dev/loop0 encrypted.img<br />
Password:<br />
ioctl: LOOP_SET_STATUS: Invalid argument</p></blockquote>
<p>Ooops.. Something wrong. Our losetup bin isn&#8217;t patched to use AES. On ubuntu/debian based OS, it&#8217;s is to deal.</p>
<pre class="brush:bash">apt-get install loop-aes-utils
root@vm-ubuntu-lamp:~# losetup -e aes /dev/loop0 encrypted.img
Password:
ioctl: LOOP_SET_STATUS: Invalid argument, requested cipher or key length (128 bits) not supported by kernel</pre>
<p>Hmm.. Still not good, we need now to patch or change our kernel for support encryption. We have to check if the &#8220;aes&#8221; and &#8220;cryptoloop&#8221; modules are loaded, if not we will load them.</p>
<pre class="brush:bash">root@vm-ubuntu-lamp:~# lsmod | grep aes
root@vm-ubuntu-lamp:~# modprobe aes
root@vm-ubuntu-lamp:~# lsmod | grep aes
aes                    28608  0
root@vm-ubuntu-lamp:~# lsmod | grep cryptoloop
root@vm-ubuntu-lamp:~# modprobe cryptoloop
root@vm-ubuntu-lamp:~# lsmod | grep crypto
cryptoloop              4096  0
loop                   17928  1 cryptoloop</pre>
<p>If you don&#8217;t have the module with your current kernel, you will have to build it by activate the some kernel options.</p>
<pre class="brush:text">CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_AES_586=m</pre>
<p>Now we should be ok to load our encrypted image.<br />
root@vm-ubuntu-lamp:~# losetup -e aes /dev/loop0 encrypted.img<br />
Password:</p>
<p><strong>Format the device with a proper filesystem</strong></p>
<pre class="brush:bash">root@vm-ubuntu-lamp:~# mkfs.ext3 /dev/loop0
mke2fs 1.40-WIP (14-Nov-2006)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
5016 inodes, 20004 blocks
1000 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=20709376
3 block groups
8192 blocks per group, 8192 fragments per group
1672 inodes per group
Superblock backups stored on blocks:
8193

Writing inode tables: done
Creating journal (1400 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 39 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.</pre>
<p><strong>Mount the device</strong></p>
<p>Easiest step, just have to use the mount command.</p>
<pre class="brush:bash">root@vm-ubuntu-lamp:~# mkdir /mnt/encrypted
root@vm-ubuntu-lamp:~# mount /dev/loop0 /mnt/encrypted

root@vm-ubuntu-lamp:~# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1              7850996   1346292   6105892  19% /
varrun                   63052        40     63012   1% /var/run
varlock                  63052         0     63052   0% /var/lock
procbususb               63052        68     62984   1% /proc/bus/usb
udev                     63052        68     62984   1% /dev
devshm                   63052         0     63052   0% /dev/shm
/dev/loop0               19366      1578     16788   9% /mnt/encrypted

root@vm-ubuntu-lamp:~# df -H
Filesystem             Size   Used  Avail Use% Mounted on
/dev/sda1              8,1G   1,4G   6,3G  19% /
varrun                  65M    41k    65M   1% /var/run
varlock                 65M      0    65M   0% /var/lock
procbususb              65M    70k    65M   1% /proc/bus/usb
udev                    65M    70k    65M   1% /dev
devshm                  65M      0    65M   0% /dev/shm
/dev/loop0              20M   1,7M    18M   9% /mnt/encrypted</pre>
<p>If you want to go further on this subject : <a title="Encryption HOWTO" href="http://encryptionhowto.sourceforge.net/Encryption-HOWTO-4.html#losetup">Encryption HOWTO</a></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F&amp;title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F&amp;title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F&amp;title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F&amp;headline=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;u=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F&amp;title=Using+losetup+and+dd+to+secure+sensitive+data+%28encrypted+block+device%29&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.shell-tips.com%2F2008%2F07%2F13%2Fusing-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.shell-tips.com/2008/07/13/using-losetup-and-dd-to-secure-sensitive-data-encrypted-block-device/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cheap SAN and secure backup solution for small-sized platform</title>
		<link>http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/</link>
		<comments>http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/#comments</comments>
		<pubDate>Mon, 26 Nov 2007 03:05:18 +0000</pubDate>
		<dc:creator>Nicolas Brousse</dc:creator>
				<category><![CDATA[Bash - GNU Shell]]></category>
		<category><![CDATA[Case Study]]></category>
		<category><![CDATA[mdadm]]></category>
		<category><![CDATA[nbd]]></category>
		<category><![CDATA[network device]]></category>
		<category><![CDATA[raid software]]></category>
		<category><![CDATA[raid5]]></category>
		<category><![CDATA[raid6]]></category>
		<category><![CDATA[san]]></category>

		<guid isPermaLink="false">http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/</guid>
		<description><![CDATA[Here is a quick post about a cheap SAN and secure backup architecture solution for small-sized platform (5/10 servers). In this study case we will see how to use Network Block Devices (nbd) and soft-raid with mdadm. I design it for my personal web platform which is a small one. Last day, I was missing [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a quick post about a cheap <a title="Wikipedia - SAN" href="http://en.wikipedia.org/wiki/Storage_area_network">SAN</a> and secure backup architecture solution for small-sized platform (5/10 servers). In this study case we will see how to use Network Block Devices (<a title="Network Block Devices" href="http://nbd.sf.net">nbd</a>) and soft-raid with <a title="Linux tools - MDADM" href="http://neil.brown.name/blog/mdadm">mdadm</a>. I design it for my personal web platform which is a small one. Last day, I was missing of free space on my backup server and I was angry by the idea to rent a most expensive server to store my backup while I had lot of unused space on my other servers.</p>
<blockquote><p><a href="http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/#one">1. Initial platform</a><br />
<a href="http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/#two">2. New platform</a><br />
<a href="http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/#three">3. How to do it ?</a></p></blockquote>
<p><span id="more-38"></span></p>
<p><strong><a title="one" name="one"></a>1. Initial platform</strong></p>
<p>The initial platform is made of five production servers (Apache, PHP, MySQL, Postfix), one &#8220;monitoring server&#8221; running with cacti, nagios, POP3, IMAP, Subversion, Trac, Primary DNS, etc. and one &#8220;backup server&#8221; used as Secondary DNS, MySQL Slave and finally <a title="Rsync tools - rsnapshot" href="http://www.rsnapshot.org">rsnapshot</a> server. Of course I manage all this remotely with my old laptop. In this schema the Backup server can deal only 100 Go of backup.</p>
<p><img title="Current Platform" src="/dl/current_pf.png" alt="Current Platform" /></p>
<blockquote><p><em><strong>Cons</strong></em></p>
<ul>
<li>Backup server is a single point of failure (SPOF). If i lost my HD, I lost all my backup data</li>
<li>Don&#8217;t use all my disk space on all my server</li>
<li>When I need more space on my backup server, I have to rent and move to a new and more expensive server</li>
<li>Backup server represent 15% of all my monthly cost (Really hudge for so small platform !)</li>
</ul>
</blockquote>
<p><strong><a title="two" name="two"></a>2. New platform</strong></p>
<p>I look at a quantity of open project for using <a title="Wikipedia - Distributed Filesystem (DFS)" href="http://en.wikipedia.org/wiki/Distributed_file_system">distributed filesystem</a> (Coda, AFS, LegionFS, MogileFS, DRDB, etc.), but I finally conclude that my needs wasn&#8217;t in the ability to distribute data to many clients with hudge load. I need a way to :</p>
<ol>
<li>grow my available backup disk space easily</li>
<li>store my backup data in a redundant maner and most secure way (removing SPOF)</li>
<li>less expensive structure</li>
</ol>
<p>I have lot of space unused on all my production servers. So, I choose to use Network Block Devices (NBD) with Raid 6 implementation. In this schema I currently have 4&#215;100 Go (Raid device) that give me 200 Go of available space for my backups.</p>
<p><em><strong>Why Raid 6 instead of Raid 5 ?</strong></em></p>
<p><em>As I write earlier, my goal isn&#8217;t read/write performance, but security aspect. Due to the risk of lost a network member, I choose to use Raid 6 Implementation that let me the possibility to lost two node at the same time.</em></p>
<p><img title="Cheap secure backup platform (nbd + raid)" src="/dl/new_pf.png" alt="Cheap secure backup platform (nbd + raid)" width="480" height="384" /></p>
<blockquote><p><em><strong>Pros</strong></em></p>
<ul>
<li>Distributed backup data between all the array members</li>
<li>No more SPOF if I crash the backup server (This structure let me the possibility to mount the array on another server or my laptop)</li>
<li>Use all available space on my servers</li>
<li>Less expensive platform and easy to upgrade</li>
</ul>
<p><em><strong>Cons </strong></em></p>
<ul>
<li>If you crash more than two node of your RAID Array you will lost all your data, this mean that you must take care when you choose to reboot a server : RAID reconstruction is not fast !</li>
<li>When writing to the RAID device that will does many network i/o and probably use some CPU on your nbd-server</li>
</ul>
</blockquote>
<p><strong><a title="three" name="three"></a>3. How to do it ?</strong></p>
<p>first of all, I install <strong>nbd-server</strong> on each server with unused disk space. I choose three server from my five production servers. I&#8217;m using Ubuntu Server distrib, so I just have to do an &#8220;<em>apt-get install nbd-server</em>&#8220;. Now I have to build an image disk on each server that will be used for the network block device. I use <strong>dd</strong> for build a 100 Go file image then I start nbd-server on each server (node).</p>
<blockquote><p>dd if=/dev/zero of=/home/nbd/backup.img bs=1024 count=100000000</p>
<p>nbd-server 10130 /home/nbd/backup.img</p></blockquote>
<p>I encourage you to look at the man page of nbd-server for know more about all the available option.</p>
<p>Next, we have to setup the main server for building the RAID Array. I choose RAID 6. We previously setup 3 servers for doing 3 Network Block Devices. I need one more server for implementing my RAID 6 Array. I choose to setup a file image on the local server where I build the RAID Array, I just need to use loop device with <strong>losetup</strong>. Then we &#8220;mount&#8221; the network block devices locally with <strong>nbd-client</strong> (look at the man page too).</p>
<blockquote><p>dd if=/dev/zero of=/home/nbd/backup.img bs=1024 count=100000000</p>
<p>losetup /dev/loop0 /home/nbd/backup.img</p>
<p>modprobe nbd</p>
<p>nbd-client serv1.example.com 10130 /dev/nbd0 -persist</p>
<p>nbd-client serv2.example.com 10130 /dev/nbd1 -persist</p>
<p>nbd-client serv3.example.com 10130 /dev/nbd2 -persist</p></blockquote>
<p>We have all our device up on our main server, we just need to use mdadm to build our array and mount our file system to use it like any other partition.</p>
<blockquote><p>mdadm &#8211;create /dev/md0 &#8211;raid-devices=4 &#8211;level=6 &#8211;spare-devices=0 &#8211;chunk=256 /dev/nbd[012] /dev/loop0</p>
<p>mkfs.ext3 /dev/md0 -b 4096 -E stride=64</p>
<p>mount /dev/md0 /.snapshots</p></blockquote>
<p>That&#8217;s all folks ! I can now run <strong>rsnapshot</strong> using my distributed RAID 6 implementation and stopping to lost my unused spaces. NB : I use a chunk size of 256k because of the RAID 6 implementation and the network constraint, performance looks better. Due to this chunk size, I use a block size of 4k and stride of 64 while building the file system (4k x 64 = 256k).<em><strong></strong></em></p>
<p><em><strong>I need more space, how can I do ?</strong></em></p>
<p>It&#8217;s easy ! You just need to install a new nbd-server on a server having enough space then load a new nbd-client on your server running the RAID Array. When it&#8217;s done, just use mdadm to grow your array.</p>
<blockquote><p>mdadm &#8211;grow /dev/md0 &#8211;raid-disks=5<em><strong></strong></em></p>
<p>mdadm &#8211;add /dev/md0 /dev/nbd4</p></blockquote>
<p><em><strong>The server running the RAID Device crashed. How can I get my backup ??</strong></em></p>
<p>It&#8217;s easy ! You just need to build a new device on another server or on your laptop.</p>
<blockquote><p>mdadm &#8211;create /dev/md0 &#8211;assume-clean &#8211;raid-devices=4 &#8211;chunk=256 &#8211;level=6 /dev/nbd[012] missing</p></blockquote>
<p>&#8220;missing&#8221; mean that our last device of our array (/dev/loop0) is missing, the RAID Array will start in degraded mode.</p>
<p><strong><em>I have a big external HD at home for doing a second site backup. What I have to do for copying and read it ?</em></strong></p>
<p>You will just need to copy all the file image (&#8220;backup.img&#8221;) to your external disk . Take care to stop your RAID Array before (except if you are sure to don&#8217;t have any write on your images while doing your copy). Then You will just have to load each images with <strong>losetup</strong> locally and building a RAID Array with <strong>mdadm</strong>.</p>
<p><strong>To sum up</strong></p>
<p>I think that this platform design is really useful for small sized (5/10 servers) platform because you get a distributed data backup solution at low cost. You don&#8217;t need to have dedicated server to manage your backup. However, you have to take care of the touchy aspect of any raid implementation, a wrong manipulation with mdadm or too many server crash could lead you to the lost of all your data. You have to keep in mind that RAID 6 need lot of time to rebuild large storage. If you plan to reboot lot of your servers, don&#8217;t forget to stop your RAID Array.</p>
<p>If you are interested in this kind of platform for build your SAN, I encourage you to look at the <a title="Wikipedia - iSCSI" href="http://en.wikipedia.org/wiki/iSCSI">iSCSI</a> or <a title="Wikipedia - ATA over Ethernet" href="http://en.wikipedia.org/wiki/ATA_over_Ethernet">AoE</a> Protocols.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F&amp;title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F&amp;title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F&amp;title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F&amp;headline=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;u=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F&amp;title=Cheap+SAN+and+secure+backup+solution+for+small-sized+platform&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F26%2Fcheap-secure-backup-solution-for-small-sized-platform%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.shell-tips.com/2007/11/26/cheap-secure-backup-solution-for-small-sized-platform/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[PHP] Zend Platform &#8211; Performance results</title>
		<link>http://www.shell-tips.com/2007/11/12/php-zend-platform-performance-results/</link>
		<comments>http://www.shell-tips.com/2007/11/12/php-zend-platform-performance-results/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 16:57:14 +0000</pubDate>
		<dc:creator>Nicolas Brousse</dc:creator>
				<category><![CDATA[Benchmarks]]></category>
		<category><![CDATA[Case Study]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zend platform]]></category>

		<guid isPermaLink="false">http://www.shell-tips.com/2007/11/12/php-zend-platform-performance-results/</guid>
		<description><![CDATA[If you are a PHP developer or a LAMP server admin you probably have already heard about the Zend Platform. After some test and configure/tunning step, we deployed this solution on a heavy loaded production server running with Apache 2.x, PHP 4.4.x, MySQL Client 5.x. The server used for deploy and test the Zend Platform [...]]]></description>
			<content:encoded><![CDATA[<p>If you are a PHP developer or a LAMP server admin you probably have already heard about the <a title="Zend Platform" href="http://www.zend.com/fr/products/zend_platform">Zend Platform</a>. After some test and configure/tunning step, we deployed this solution on a heavy loaded production server running with <a title="Apache - HTTPD Server" href="http://httpd.apache.org">Apache 2.x</a>, <a title="PHP" href="http://www.php.net">PHP 4.4.x</a>, <a title="MySQL" href="http://www.mysql.org">MySQL Client 5.x</a>.</p>
<p><span id="more-37"></span></p>
<p>The server used for deploy and test the Zend Platform in real production condition is a Bi-Xeon 1,4Ghz with 2Go RAM and 2&#215;36 Go SCSI. This server is part of a cluster made of 10 servers which deliver PHP scripts only. All statics media (gif, css, js, swf, etc.) are delivered thru other dedicated servers.</p>
<p><strong>Statistics Without  Zend Platform</strong></p>
<blockquote>
<ul>
<li>More than 3.000.000 Hits/Day</li>
<li>30 Hits/sec</li>
<li>60% Average CPU Load</li>
</ul>
</blockquote>
<p><strong>Statistics With  Zend Platform</strong></p>
<blockquote>
<ul>
<li> More than 10.000.000 Hits/Day</li>
<li>100 Hits/sec</li>
<li>20% Average CPU Load</li>
</ul>
</blockquote>
<p><img title="Zend Platform Results" src="/dl/tn_zp_results.png" border="0" alt="Zend Platform Results" width="150" height="194" align="left" /></p>
<p><a title="Zend Platform - Performance result (PDF)" href="/dl/zp_results.pdf">Download the PDF Version</a></p>
<p><a title="Zend Platform - Performance result (PNG)" href="/dl/zp_results.png">Download the PNG Version</a></p>
<p><strong>To sum up<br />
</strong></p>
<blockquote>
<ul>
<li> Manage 3.5 times more traffic</li>
<li> Having 3 times less load</li>
<li> Use same quantity of process</li>
<li> All the advanced futures for debug, profile, analyze your code</li>
<li>Centralize error message easily from multiple front (With stats, alerts, vhost, etc.)</li>
<li>HTML Caching solution</li>
</ul>
</blockquote>
<p>Of course, all this stuff could be done with <a title="xDebug" href="http://www.xdebug.org">xDebug</a>, <a title="xCache" href="http://xcache.lighttpd.net">xCache</a> and many other Open Source solution, this will depend of your free time for deploying it. The Zend Platform is an &#8220;All in One&#8221; package with some advanced features and a good interaction between the Platform and your IDE (<a title="Zend Studio - Zend Neon" href="http://www.zend.com/products/zend_studio">Zend Studio/Neon</a>).</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F&amp;title=%5BPHP%5D+Zend+Platform+-+Performance+results" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F&amp;title=%5BPHP%5D+Zend+Platform+-+Performance+results" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F&amp;title=%5BPHP%5D+Zend+Platform+-+Performance+results" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F&amp;headline=%5BPHP%5D+Zend+Platform+-+Performance+results" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;u=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F&amp;title=%5BPHP%5D+Zend+Platform+-+Performance+results&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.shell-tips.com%2F2007%2F11%2F12%2Fphp-zend-platform-performance-results%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.shell-tips.com/2007/11/12/php-zend-platform-performance-results/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fine tuning a Linux Apache MySQL PHP (LAMP) server</title>
		<link>http://www.shell-tips.com/2006/11/25/fine-tuning-a-linux-apache-mysql-php-lamp-server/</link>
		<comments>http://www.shell-tips.com/2006/11/25/fine-tuning-a-linux-apache-mysql-php-lamp-server/#comments</comments>
		<pubDate>Sat, 25 Nov 2006 02:11:15 +0000</pubDate>
		<dc:creator>Nicolas Brousse</dc:creator>
				<category><![CDATA[Case Study]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sysctl]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.shell-tips.com/2006/11/25/fine-tuning-a-linux-apache-mysql-php-lamp-server/</guid>
		<description><![CDATA[I started to write this post many weeks ago and finally publish it even if it&#8217;s not totally finish. It is just a little feedback about tuning a full LAMP server with some user traffic and services load. Important thing to notice is that all stuff in this post is NOT THE SOLUTION. You will [...]]]></description>
			<content:encoded><![CDATA[<p>I started to write this post many weeks ago and finally publish it even if it&#8217;s not totally finish. It is just a little feedback about tuning a full LAMP server with some user traffic and services load. Important thing to notice is that all stuff in this post is <strong>NOT THE SOLUTION</strong>. You will probably have to tune little more for adapt all this to your personal server usage, server load, development &amp; architecture. So, use those tips as a kind of inspiration instead of an &#8220;how to&#8221;. Don&#8217;t forget that when you do such tuning, take care to keep a backup of your previous configuration files.</p>
<p>We will try to tune the following server :</p>
<ul>
<li>Current OS : Debian GNU Linux Kernel 2.4.32 ipv4 + GRSEC</li>
<li>1Go RAM DDR</li>
<li>Intel(R) Celeron(R) CPU 2.66GHz</li>
<li>SWAP 512Mo</li>
<li>3Go on / and 226Go on /home</li>
<li>Running services are Qmail, Bind9, mrtg, Apache 2.2.2, PHP 5.1.4, MySQL 5.0.21</li>
</ul>
<p><span id="more-18"></span><br />
The best way for tuning a server is to have dedicated services on one server and so, having multiple server especially for MySQL and Apache.</p>
<p>We were runing a heavy website with <a title="DotClear" href="http://www.dotclear.net">DotClear</a> and the heavy <a title="PhpAds New" href="http://www.phpadsnew.com">PhpADS</a> with all its stuff (geoip, all counters, etc.)<br />
The server up to a load of 114 in some peak with a swap totally used ! And so.. a big freeze of services&#8230; 70k mails/day , 110k pv/day, 12k v/day, 47 sql queries/sec</p>
<p>In fact, services weren&#8217;t so loaded but the box was crashing a lot and swapping often without using too much CPU.</p>
<p>First things that I do was to change the Linux Kernel from a 2.4.32 to a 2.6.18. Lot of things were improves in 2.6. I convey you to take a look at those posts :<br />
<a href="http://www-128.ibm.com/developerworks/linux/library/l-web26/">http://www-128.ibm.com/developerworks/linux/library/l-web26/</a><br />
<a href="http://developer.osdl.org/craiger/hackbench/">http://developer.osdl.org/craiger/hackbench/</a><br />
<a href="http://kerneltrap.org/node/903">http://kerneltrap.org/node/903</a></p>
<p>After this update, I take the time to update all version software for using a MySQL 5.0.27, PHP 5.2 etc. Without looking at the changelogs, bugfixes will still help us :-)<br />
After this, we will tune our software configuration that still use default values (this is really bad ! :) then we will tune a little the kernel without recompile a new one.</p>
<ul>
<li><strong>Apache 2.2.2 Prefork</strong></li>
</ul>
<p>Our <strong>HTTPD</strong> is using some modules as url rewriting, server info, php5, GeoIP and other basic modules. We could optimize much more by using an Apache 2.2.3 Worker and only useful modules or even more delivering static pages and using proxy for dynamic pages. All this depend on your developments and your server usage. Here we will only focus on the Apache Prefork.<br />
Nowadays, it&#8217;s important to keep active the <strong>KEEPALIVE</strong> functionality. This will increase the speed of delivring pages for lot of modern browsers (it&#8217;s supported by ie, firefox, safari, opera, etc.). The only thing is to touch a little to the default value. In fact, if your keepalive time out is too big, you will keep an entire apache slot open for a user that is probably gone ! A 4 seconds timeout is enough for delivering a full web page and take care of any network congestion. MaxKeepAliveRequests is used to define the maximum number of request manage by an apache slot during a keepalive session. Except if you have lot of pictures to load on your web pages you don&#8217;t really need to have a big value at this state.</p>
<blockquote><p>KeepAlive On<br />
KeepAliveTimeout 4<br />
MaxKeepAliveRequests 500</p></blockquote>
<p>As I don&#8217;t have lot of memory available on the server I &#8216;m constraint to decrease drastically the number of running servers from 150 to 60. As I have an apache using approximatly 13Mo of memory (withdraw 3Mo of shared memory), I need approximately 600 Mo of available memory when all the apache child process are running. <em><span style="text-decoration: underline;">We have to consider, for our further tuning, that this memory is used.</span></em> It&#8217;s really important in our case to dedicate memory for avoid to swap too much and lost the box in a freeze. you can follow your memory usage by using <strong>TOP</strong> and looking for your apache/httpd process. (Do a quick <em>&#8220;man top&#8221;</em> for know more). If you have little more free memory you can take a look to the <a title="Apache doc - mpm common" href="http://httpd.apache.org/docs/2.2/mod/mpm_common.html">apache documentation</a> for further tuning.</p>
<blockquote><p>ServerLimit         60<br />
MaxClients          60</p></blockquote>
<p>Our server is often overload, with lot of traffic. When I need to restart the apache, or in case of any crashes the apache server start with only 5 Child server process and will add new one 1 second later, 2 new child 2 second later, 4 new at the third second, etc. It&#8217;s really too long when you are in a peak ! So, I configured StartServers for let us start directly with 30 child Server process. That will help us to deliver quickly the clients and minimize the impact of the server restart.</p>
<p>MinSpareServers and MaxSpareServers is used in same way as StartServer. When your apache server isn&#8217;t load, there is idle child waiting for connection. It&#8217;s not usefull to have all your child still open but, In case of a new peak the best way to minimize its impact on your server is to deliver web pages as quick as possible. So keeping some idle Child Process still waiting for client isn&#8217;t so stupid. Furthermore in case of our touchy server we consider to be able to allocate 600Mo of RAM. So, We can use it even if it&#8217;s for idle Child Process as we dedicate this RAM for apache. For avoid any module Memory Leak, and having fully available Child I set the MaxRequestPerChild to 1000, that mean that each 1000  request, the child will be kill and Apache Server will spare a new one. You&#8217;ll probably have to set this value to a higher number. It&#8217;s depend of the structure of your web page. You will have to monitor a little your server after those change for being sure to don&#8217;t have too much child kill/spare instead of delivering web pages.</p>
<blockquote><p>StartServers        30<br />
MinSpareServers     30<br />
MaxSpareServers     30<br />
MaxRequestsPerChild  1000</p></blockquote>
<p>Follow some security issue, we don&#8217;t display too much information about our server. As we don&#8217;t need the reverse lookup on the client ip, we keep the default value of HostnameLookups to Off and by this way we save some network traffic and server load.</p>
<blockquote><p>ServerTokens Prod<br />
ServerSignature Off<br />
HostnameLookups Off</p></blockquote>
<ul>
<li><strong>PHP 5.1.4</strong></li>
</ul>
<p>For perform our page generation and save some cpu we use the php extension <a title="php extension : eaccelerator" href="http://eaccelerator.net/">eaccelerator</a>. Take a look at the documentation for install it.<br />
We dedicate 32Mo of our RAM for eaccelerator (<strong>shm_size</strong>) and will use it with shared memory and file cache (&#8220;<strong>shm_and_disk</strong>&#8221; value for keys, sessions and content variable). (Memory is really useful in our case, because of all the mails, apache log and MySQL disk access that generate too much i/o and slow down considerably all the server). As we don&#8217;t change often the php script on the server we don&#8217;t need to use the <strong>check_mtime</strong> functionality. When set to &#8220;1&#8243;, that will do a stat on the php script for checking of last modification date We don&#8217;t need this because we want to save disk access and we don&#8217;t have so many updates on the running scripts. We just have to clean the cache directory after an update.</p>
<blockquote><p>eaccelerator.shm_size=&#8221;32&#8243;<br />
eaccelerator.cache_dir=&#8221;/www/tmp/eaccelerator&#8221;<br />
eaccelerator.enable=&#8221;1&#8243;<br />
eaccelerator.optimizer=&#8221;1&#8243;<br />
eaccelerator.check_mtime=&#8221;0&#8243;<br />
eaccelerator.debug=&#8221;0&#8243;<br />
eaccelerator.filter=&#8221;"<br />
eaccelerator.shm_max=&#8221;0&#8243;<br />
eaccelerator.shm_ttl=&#8221;3600&#8243;<br />
eaccelerator.shm_prune_period=&#8221;1&#8243;<br />
eaccelerator.shm_only=&#8221;0&#8243;<br />
eaccelerator.compress=&#8221;1&#8243;<br />
eaccelerator.compress_level=&#8221;9&#8243;<br />
eaccelerator.keys     = &#8220;shm_and_disk&#8221;<br />
eaccelerator.sessions = &#8220;shm_and_disk&#8221;<br />
eaccelerator.content  = &#8220;shm_and_disk&#8221;</p></blockquote>
<ul>
<li><strong>MySQL 5.0.24</strong></li>
</ul>
<p>As I don&#8217;t manage how has been coding many of running script, I decrease all the timeout MySQL connection for avoid congestion. Then I increase the number off simultaneous MySQL connection as we had lot of &#8220;Too many connection&#8221; error message.</p>
<blockquote><p>wait_timeout=6<br />
connect_timeout=5<br />
interactive_timeout=120<br />
max_connections         = 500<br />
max_user_connections    = 500</p></blockquote>
<p>Now we change the touchiest part of the MySQL configuration : The RAM usage. It&#8217;s touchy because a bad value can really decrease your server performance and result in a big server swap. After some test I decrease the table cache and the key buffer cache to 256Mo. In fact we don&#8217;t have so many available ram as we had 600Mo for our <strong>HTTPD</strong> and we have lot of other services running. I tried to set it up little higher, hopping that the swap won&#8217;t be to big, but in fact, due to our i/o load the swap were totaly not a good thing for MySQL :-)</p>
<p>If you are using MYISAM tables I suggest you to use the &#8220;<strong>concurrent_insert=2</strong>&#8221; that will really increase your server performance in many case. MYISAM use table lock, with concurrent insert, the engine will sometime bypass the lock and allow INSERT and SELECT to run concurrently. We also disable all engine that is not used (innodb, bdb). Take a look at the <a title="MySQL 5.0 Documentation" href="http://www.mysql.org/doc/refman/5.0/en/server-system-variables.html">MySQL documentation</a> for better tuning.</p>
<blockquote><p>join_buffer_size=1M<br />
sort_buffer_size=1M<br />
read_buffer_size=1M<br />
read_rnd_buffer_size=1M<br />
table_cache=256M<br />
max_allowed_packet=4M</p>
<p>key_buffer=256M<br />
key_buffer_size=256M<br />
thread_cache=256M<br />
thread_concurrency=2<br />
thread_cache_size=40<br />
thread_stack=128K</p>
<p>concurrent_insert=2</p>
<p>query_cache_limit=1M<br />
query_cache_size=256M<br />
query_cache_type=1<br />
skip-bdb<br />
skip-innodb</p></blockquote>
<ul>
<li><strong>Linux Kernel 2.6.18</strong></li>
</ul>
<p>Here is a touchy part of our tuning, we will try to perform the Linux Kernel behavior with our server load for save some memory and avoid too much swap. Furthermore, has we done a great stuff above this part, we have to manage more TCP connection and support correctly the peak. We will use the command &#8220;sysctl&#8221; for doing our update on values.</p>
<blockquote><p># display value of a variable or group of variable<br />
sysctl [-n] [-e] variable &#8230;<br />
# set a new value toe the specified variable<br />
sysctl [-n] [-e] [-q] -w variable=value &#8230;<br />
# display all the variable<br />
sysctl [-n] [-e] -a<br />
# load a sysctl config file<br />
sysctl [-n] [-e] [-q] -p    (default /etc/sysctl.conf)</p></blockquote>
<p>For our test we will create a test config file &#8220;/etc/sysctl.conf.testing&#8221; and we will load it by using the following command line :</p>
<blockquote><p>sysctl -p /etc/sysctl.conf.testing</p></blockquote>
<p>When you will be glad of your change you could rename the file for &#8220;/etc/sysctl.conf&#8221;.  All the sysctl variable are documented with the Kernel Sources. I suggest you to download the <a title="Linux Kernel" href="http://kernel.org">documentation</a> corresponding to your kernel version and read it carefully if you decide to change some values.<br />
A really good article on <a title="Security Focus : Hardening TCP/IP" href="http://www.securityfocus.com/infocus/1729">Security Focus</a> give us some key for minimize the impact of a <strong>SYN ATTACK</strong> / <strong>SYN SPOOFING</strong>. In this goal we activate the syncookies and the route validation</p>
<blockquote><p>net.ipv4.conf.default.rp_filter=1<br />
net.ipv4.tcp_syncookies=1<br />
net.ipv4.tcp_synack_retries=3<br />
net.ipv4.tcp_syn_retries=3</p></blockquote>
<p>As we had some swap troubles, important thing to do is to change the value of <strong>vm.swappiness</strong> where the default value is 60. This variable control how much the kernel should favor swapping out applications, its value can be 0 to 100. I set it to 10 for minimize the swap.</p>
<blockquote><p>vm.swappiness=10</p></blockquote>
<p>We upgrade the max backlog for support more TCP traffic and we change the congestion control algorithm to <a title="Congestion control : BIC-TCP" href="http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/">BIC</a>. The Linux Kernel support lot of congestion algorithm like Reno (default one),  htcp, vegas, westwood, etc.</p>
<blockquote><p>net.core.netdev_max_backlog=2500 # Interface buffering<br />
net.ipv4.tcp_max_syn_backlog=4096<br />
net.core.somaxconn=1024 # Limit of socket listen() backlog. Default is 128.<br />
net.ipv4.tcp_congestion_control=bic</p></blockquote>
<p>For avoid to have a big TCP queue and so memory usage for not really active connection I decrease some TCP timeout and force the kernel to recycle quickly tcp connection. We don&#8217;t cache the value of <strong>ssthresh</strong> (Slow Start Threshold) for avoid to impact a given host to have a reduced  ssthresh for all is next connections.</p>
<blockquote><p>net.ipv4.tcp_keepalive_time=900<br />
net.ipv4.tcp_fin_timeout=30<br />
net.ipv4.tcp_max_orphans=16384<br />
net.ipv4.tcp_tw_reuse=1<br />
net.ipv4.tcp_tw_recycle=1<br />
net.ipv4.tcp_rfc1337=1<br />
net.ipv4.tcp_no_metrics_save=1</p></blockquote>
<p>It&#8217;s critical to use the optimal SEND and RECEIVE socket buffer size for the link you are using. In our case we have a 100Mbits link connection. So for a better TCP connection and congestion control we had to increase the TCP Buffer. You can read more about this <a title="TCP Tuning" href="http://dsd.lbl.gov/TCP-tuning/">here</a>.</p>
<blockquote><p>net.core.rmem_max=16777216<br />
net.core.wmem_max=16777216<br />
net.ipv4.tcp_rmem=4096 87380 16777216<br />
net.ipv4.tcp_wmem=4096 65536 16777216</p></blockquote>
<ul>
<li><strong>That&#8217;s all folks !</strong></li>
</ul>
<p>Now, this server support twice more traffic load. Technical aspect was our traffic growth bottleneck. Lot of other tuning could be done for better performance (on i/o and disk access, other kernel options, compile a new kernel, using apache worker, etc.). This post was just some clues about how to tune your servers. One important thing to don&#8217;t forget is whatever you tune on your server, that will never be enough if you have a bloody developed programs running on it !</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F&amp;title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F&amp;title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F&amp;title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F&amp;headline=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;u=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F&amp;title=Fine+tuning+a+Linux+Apache+MySQL+PHP+%28LAMP%29+server&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.google.com/buzz/post?url=http%3A%2F%2Fwww.shell-tips.com%2F2006%2F11%2F25%2Ffine-tuning-a-linux-apache-mysql-php-lamp-server%2F" ><img class="lightsocial_img" src="http://www.shell-tips.com/wp-content/plugins/light-social/google_buzz.png" alt="Google Buzz (aka. Google Reader)" title="Google Buzz (aka. Google Reader)" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.shell-tips.com/2006/11/25/fine-tuning-a-linux-apache-mysql-php-lamp-server/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
