<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Server Density Blog</title>
	
	<link>http://blog.serverdensity.com</link>
	<description>Interesting devops tech stuff</description>
	<lastBuildDate>Sun, 19 May 2013 14:00:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/serverdensity" /><feedburner:info uri="serverdensity" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Sysadmin Sunday 127</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/vsVLY-14zNs/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-127/#comments</comments>
		<pubDate>Sun, 19 May 2013 14:00:33 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3554</guid>
		<description><![CDATA[<p>WordPress Caching with Nginx and Redis How mitmproxy works Facebook June Open Compute hardware hackathon How I &#8216;stole&#8217; $14 million from a bank: A security tester&#8217;s tale Choosing the Right [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-127/">Sysadmin Sunday 127</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/13zgzFa"><span></span>WordPress Caching with Nginx and Redis</a></li>
<li><a href="http://buff.ly/13yqkmV"><span></span>How mitmproxy works</a></li>
<li><a href="http://buff.ly/15NEOTH"><span></span>Facebook June Open Compute hardware hackathon</a></li>
<li><a href="http://buff.ly/12blRnk"><span></span>How I &#8216;stole&#8217; $14 million from a bank: A security tester&#8217;s tale</a></li>
<li><a href="http://buff.ly/129uQVY"><span></span>Choosing the Right EC2 Instance Type for Your Application</a></li>
<li><a href="http://buff.ly/19z0dvS"><span></span>Google introduces a new NoSQL Database</a></li>
<li><a href="http://buff.ly/1287YGA"><span></span>This Is the Most Detailed Picture of the Internet Ever (and Making it Was Very Illegal)</a></li>
<li><a href="http://buff.ly/127RrlO"><span></span>The Secret to 10 Million Concurrent Connections -The Kernel is the Problem, Not the Solution</a></li>
<li><a href="http://buff.ly/16tQydr"><span></span>TDD your DevOps with test-kitchen 1.0</a></li>
<li><a href="http://buff.ly/19hVrmB"><span></span>The Human Side of Postmortems (free O&#8217;Reilly eBook)</a></li>
<li><a href="http://buff.ly/16tOC4H"><span></span>Center for Internet Security Linux Benchmark implementation for PuppetLabs</a></li>
<li><a href="http://buff.ly/16jfcNL"><span></span>Facebook aims to knock Cisco down a peg with open network hardware</a></li>
<li><a href="http://buff.ly/192gOIg"><span></span>How the Syrian Electronic Army Hacked The Onion</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-127/">Sysadmin Sunday 127</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/vsVLY-14zNs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-127/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-127/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-127</feedburner:origLink></item>
		<item>
		<title>Sysadmin Sunday 126</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/EbefMLE3kpo/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-126/#comments</comments>
		<pubDate>Sun, 12 May 2013 14:00:52 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3552</guid>
		<description><![CDATA[<p>Wikipedia Adopts MariaDB The Security Benefits of RPM Packaging Doom Your Chef in 3 Easy Steps What TokuDB might mean for MongoDB CDNs fail, but your scripts don&#8217;t have to [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-126/">Sysadmin Sunday 126</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/10NN1W4"><span></span>Wikipedia Adopts MariaDB</a></li>
<li><a href="http://buff.ly/10NNgQR"><span></span>The Security Benefits of RPM Packaging</a></li>
<li><a href="http://buff.ly/Zf8u3y"><span></span>Doom Your Chef in 3 Easy Steps</a></li>
<li><a href="http://buff.ly/ZPdznV"><span></span>What TokuDB might mean for MongoDB</a></li>
<li><a href="http://buff.ly/ZUMFem"><span></span>CDNs fail, but your scripts don&#8217;t have to &#8211; fallback from CDN to local jQuery </a></li>
<li><a href="http://buff.ly/13P80Ew"><span></span>How to use MongoDB as a pure in-memory DB (Redis style)</a></li>
<li><a href="http://buff.ly/10uNJQx"><span></span>Managing multiple MongoDB clusters with chef</a></li>
<li><a href="http://buff.ly/10uNKE3"><span></span>Redis partial word match, you (auto)complete me</a></li>
<li><a href="http://buff.ly/10uNQeQ"><span></span>Cassandra anti-patterns: Queues and queue-like datasets</a></li>
<li><a href="http://buff.ly/ZuObzs"><span></span>2 advanced techniques to dramatically increase the performance of your responsive website</a></li>
<li><a href="http://buff.ly/140z6c0"><span></span>Google&#8217;s buildings are hackable</a></li>
<li><a href="http://buff.ly/15muFgl"><span></span>DevOps and cloud: A view from outside the Bay Area bubble</a></li>
<li><a href="http://buff.ly/15mQFrD"><span></span>nginx security advisory (CVE-2013-2028)</a></li>
<li><a href="http://buff.ly/15muG3O"><span></span>DevopsDays 2013 &#8211; we are avoiding culture, why?</a></li>
<li><a href="http://buff.ly/15oSMuX"><span></span>SELinux &#038; Return On Time Invested</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-126/">Sysadmin Sunday 126</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/EbefMLE3kpo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-126/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-126/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-126</feedburner:origLink></item>
		<item>
		<title>Many projects with Vagrant and Puppet</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/-HHCfQifljQ/</link>
		<comments>http://blog.serverdensity.com/many-projects-with-vagrant-and-puppet/#comments</comments>
		<pubDate>Tue, 07 May 2013 11:46:30 +0000</pubDate>
		<dc:creator>Tom Wardill</dc:creator>
				<category><![CDATA[Puppet]]></category>
		<category><![CDATA[Vagrant]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3543</guid>
		<description><![CDATA[<p>When we started Server Density v2, one of the main ideas was to build it as a collection of RESTful services, all talking over HTTP. Initially, these were installed locally [...]</p><p>The post <a href="http://blog.serverdensity.com/many-projects-with-vagrant-and-puppet/">Many projects with Vagrant and Puppet</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>When we started <a href="http://www.serverdensity.com/comingsoon/">Server Density v2</a>, one of the main ideas was to build it as a collection of RESTful services, all talking over HTTP.</p>
<p>Initially, these were installed locally on a developer&#8217;s machine and set up via Apache vhosts running each component separately.</p>
<p>This soon became unmaintainable on a daily basis without a lot of work. We were spending too much time discussing whether a certain component was up to date and fighting bugs caused by API incompatibilities between versions. As we added more services to deal with things beyond the core of the product, this just got worse.</p>
<p>The answer was <a href="http://vagrantup.com">Vagrant</a>.</p>
<h2>What is Vagrant?</h2>
<p>Essentially, vagrant is a command line tool for managing virtualbox instances (other backends are now available in the latest version). You use a pre built box (or package your own) to create a fresh virtual machine with all your tools installed, accessible via SSH from the host machine.</p>
<p>Once a vagrant box is configured, it&#8217;s just a case of <code>vagrant up</code>, waiting a while and then a system is up and running.</p>
<h2>Our vagrant box</h2>
<p>We went through some iterations and experimentation to find something suitable for the way we wanted to work, combined with what we could actually achieve in the box. This is the end result for now, and I&#8217;ll list some modifications that we have planned but haven&#8217;t found the time to do.</p>
<p>The box is split in two, a base and an environment box:</p>
<h3>The Base Box</h3>
<p>The first stage in the vagrant build was to build a customised base box. We based it on Ubuntu 12.04, 64-bit build as that&#8217;s what we planned to use in production. Once that was chosen, I collected a set of dependencies and development tools that were required for each service (MongoDB, Apache, Node.js, vim, screen, etc). These were then deployed into the base box using a fairly standard puppet manifest with some available modules. At this stage, it installs just the tooling, dependencies and makes required system level config changes (networking setup, DNS entries).</p>
<p>Once this box is built, it&#8217;s uploaded to a development webserver so all the team have access to it. The Vagrantfile and the puppet manifests live in git, alongside the development box. This means that the base box can be recreated/tweaked/reviewed by anyone at any time if that&#8217;s a necessity.</p>
<p>Using a base box like this loses some flexibility. Every time you want to add something new at the base level, you have to rebuild and re upload the entire box. But it saves deployment time in the next stage, which overall results in a win.</p>
<p>You can temporarily work around this by adding a dependency into the environment box, but if you&#8217;re not strict with how you manage this it becomes a bit of a mess of where everything is, and you lose the advantage of having a pre-built base box.</p>
<h3>The development environment</h3>
<p><img class="alignnone size-full wp-image-3546" style="margin-bottom: 2em" alt="Vagrant and Puppet" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/05/vagrantandpuppet.gif" width="700" height="150" /></p>
<p>This is a little less straightforward than the base box build.</p>
<p>Starting with a Vagrantfile with the base box imported/declared, we added puppet modules to handle installing our agent into the box so it can report to itself, and a module to install apache vhosts.</p>
<p>Once that was done, we created a puppet module that can handle installing all of the services from git. This includes a clone/update, build process (buildout/composer), and finally run any test or development data scripts that we have. This was mostly a mash of already available bits and abuse of the exec puppet command.</p>
<p>The Vagrantfile is just a file of Ruby code, so it was easy to add something that set the box hostname based on the username of the host, and import a separate settings file for overriding the defaults for the vagrant settings (code checkout locations being the main one).</p>
<p>The final stage for this was to add a script that will kill and then start all the code that runs as a service (tornado/celery mainly). This grew out of an ugly hack involving starting lots of things in screen, and hasn&#8217;t really been updated to anything else. It does have a convenient advantage that `screen -list` will tell you exactly what is running, and a total number at the bottom for quick verification that everything started okay.</p>
<p>The code is checked out into a shared directory between the host and the guest, ultimately living on the host. This uses nfs for performance which means we can edit the code using the host editors and tools but the code will still run inside the vagrant box.</p>
<p>Debugging is taken care of by xdebug being configured to point to the host IP for the PHP services, and some work with WingIDE remote debugging for the python services, again with Wing configured to connect into the vagrant box.</p>
<p>Once the box was up and running, we added settings, configs and a custom domain (using vagrant-dns) to enable decent separation and ensure we don&#8217;t accidentally hardcode production/development URLs (or at least, that these are easier to catch if it does happen).</p>
<p>The main feature of this box is that the puppet manifests run with each provision. These update and redeploy the code each time, simplifying the update process to a single command, across every service and repository that we have deployed.</p>
<h2>The Advantages</h2>
<ul>
<li style="margin-bottom: 1em">Reproducible environment for everyone involved.</li>
<li style="margin-bottom: 1em">The puppet manifests mean that just a <code>vagrant provision</code> then waiting is enough to bring everything up to date with the latest master.</li>
<li style="margin-bottom: 1em">Self contained stack, you can see what is running at any point.</li>
<li style="margin-bottom: 1em">Closer to production. We mostly develop on OSX, but deploy to Linux, this gives us both.</li>
<li style="margin-bottom: 1em">Shared URLs for testing. We can pop a URL from our vagrant machines into Hipchat, and other members of the team can use it locally, without having to change it. <a href="https://github.com/BerlinVagrant/vagrant-dns">vagrant-dns</a> is a big win for us there.</li>
<li style="margin-bottom: 1em">Easy to install. Install virtualbox, vagrant, get the Vagrantfiles, run <code>vagrant up</code>.</li>
<li style="margin-bottom: 1em">While there&#8217;s nothing in the vagrant configurations that couldn&#8217;t be as easily done with some scripting for the host machine and remove the need for virtualisation, it&#8217;s handy that when it goes wrong a fresh rebuild is just a <code>destroy</code> and <code>up</code> away. Extremely useful for testing system wide settings.</li>
</ul>
<h2>The Disadvantages</h2>
<ul>
<li style="margin-bottom: 1em">A from-nothing <code>vagrant up</code> takes 25 minutes and downloads about 2Gb (1.2Gb for the base box, the rest for code + dependencies + extras).</li>
<li style="margin-bottom: 1em"><code>vagrant provision</code> to update to latest can take up to 10 minutes depending on speed of the connection and the host machine, so it&#8217;s not that easy to &#8216;just test&#8217; something. You can update the individual services manually, but then you have the problem that we started with, making sure that everyone has the same code.</li>
<li style="margin-bottom: 1em">It&#8217;s hard work for the host machine. The box we have configured has 2 cores and 2Gb of RAM allocated. On a 4Gb Macbook Air, that can start getting a little close to resource starvation, particularly with an IDE and a debugger running.</li>
<li style="margin-bottom: 1em">Debugging isn&#8217;t as easy as I&#8217;d like, setting up the debugger is fairly involved in settings, and you can only really debug one thing at a time. Can be awkward when you&#8217;re trying to trace values across multiple services.</li>
<li style="margin-bottom: 1em">The configuration we have isn&#8217;t as close to production as I&#8217;d like (no nginx, no caching, no centralised logging) but this is just a matter of spending more time.</li>
<li style="margin-bottom: 1em">It doesn&#8217;t entirely solve &#8216;it works for me&#8217;. It just becomes &#8216;it works on my vagrant&#8217;. Fortunately, instances of that seem to be a lot less common.</li>
<li style="margin-bottom: 1em">Random virtualbox/vagrant/host problems. We&#8217;ve had boxes crash, networks go away and all manner of strange things. At least with the code living on the host machine, we&#8217;ve not lost work when that happens.</li>
</ul>
<p>While it seems that there&#8217;s more disadvantages than advantages, overall the reproducibility and simplicity of reducing updating to a single command far outweigh the drawbacks of working in a virtualised environment.</p>
<h2>Future plans</h2>
<p>Most of the future plans for this revolve around gradually bringing it in line with the production environment without losing the flexibility that we have gained.</p>
<ul>
<li style="margin-bottom: 1em">Use the production puppet manifests where possible. Our infrastructure is entirely puppet controlled, so I&#8217;d like to increase the reuse where possible.</li>
<li style="margin-bottom: 1em">Create a version that uses the multi-vm capability of vagrant to simulate a cluster, with each service separately. Could be handy for looking at scaling/communication problems.</li>
<li style="margin-bottom: 1em">See if we can reduce provision time even further, with possible build optimisations. This may then transfer to our deployment system.</li>
<li style="margin-bottom: 1em">Move to vagrant 1.2 and test out some other backends.</li>
<li style="margin-bottom: 1em">Remove the screen based development start script and move to something more production-like. (This is only used in the vagrant box, the live deployments use proper init scripts.)</li>
</ul>
<p>Overall, the use of vagrant has been a big win for us as a company, and has reduced a lot of the problems we were having. There&#8217;s still some work to be done until we&#8217;re completely happy with it, but I&#8217;d recommend that anyone looking at building this type of project take a serious look to see if it suits them.</p>
<p>The post <a href="http://blog.serverdensity.com/many-projects-with-vagrant-and-puppet/">Many projects with Vagrant and Puppet</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/-HHCfQifljQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/many-projects-with-vagrant-and-puppet/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/many-projects-with-vagrant-and-puppet/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=many-projects-with-vagrant-and-puppet</feedburner:origLink></item>
		<item>
		<title>Sysadmin Sunday 125</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/WCSQAB1Cpn0/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-125/#comments</comments>
		<pubDate>Sun, 05 May 2013 14:00:47 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3541</guid>
		<description><![CDATA[<p>etckeeper is a collection of tools to let /etc be stored in a git Why the Rest of Us Need Virtualization Even If Facebook Doesn’t This is what a DDoS [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-125/">Sysadmin Sunday 125</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/10lYa9a"><span></span>etckeeper is a collection of tools to let /etc be stored in a git</a></li>
<li><a href="http://buff.ly/11MYNLS"><span></span>Why the Rest of Us Need Virtualization Even If Facebook Doesn’t</a></li>
<li><a href="http://buff.ly/14VTv6H"><span></span>This is what a DDoS attack looks like</a></li>
<li><a href="http://buff.ly/11JzwlG"><span></span>Asynchronous Loggers for Low-Latency Logging</a></li>
<li><a href="http://buff.ly/15V9dhA"><span></span>10 questions to ask (and answer) when hosting MongoDB on AWS</a></li>
<li><a href="http://buff.ly/15Sk5Nf"><span></span>Speed up your sites with PageSpeed for Nginx</a></li>
<li><a href="http://buff.ly/ZniQC7"><span></span>Under the Covers of DynamoDB</a></li>
<li><a href="http://buff.ly/ZniRG7"><span></span>10 Things Developers Should Know about Couchbase</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-125/">Sysadmin Sunday 125</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/WCSQAB1Cpn0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-125/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-125/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-125</feedburner:origLink></item>
		<item>
		<title>Introducing Sockii: HTTP and WebSocket aggregator</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/a1znOljhlFA/</link>
		<comments>http://blog.serverdensity.com/introducing-sockii-http-and-websocket-aggregator/#comments</comments>
		<pubDate>Tue, 30 Apr 2013 13:30:38 +0000</pubDate>
		<dc:creator>Wes Mason</dc:creator>
				<category><![CDATA[Nodejs]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3513</guid>
		<description><![CDATA[<p>Developing the upcoming Server Density v2 over the past year has forced us to tackle some very interesting and difficult problems. This post introduces Sockii, a Node.js daemon which aggregates [...]</p><p>The post <a href="http://blog.serverdensity.com/introducing-sockii-http-and-websocket-aggregator/">Introducing Sockii: HTTP and WebSocket aggregator</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Developing the <a href="http://www.serverdensity.com/comingsoon/">upcoming Server Density v2</a> over the past year has forced us to tackle some very interesting and difficult problems. This post introduces <a href="https://github.com/serverdensity/sockii">Sockii</a>, a Node.js daemon which aggregates multiple WebSocket connections and proxies them to a single socket to the user&#8217;s browser.</p>
<h2>Shiny SOA</h2>
<p>Server Density v2 was re-designed from the ground up as a distributed set of HTTP services, following much in the same vein as Netflix or Amazon&#8217;s Service Orientated Architecture approach. What that means is that each distinctly different moving part of the project was separated into its own service (when it made sense to do so), e.g. &#8220;users&#8221;, &#8220;devices&#8221;, &#8220;cloud&#8221; etc. That means you gain full separation of concerns, the users service doesn&#8217;t need to care what the sharding policy for devices is as long as the RESTful HTTP API it provides conforms to a known specification.</p>
<p>That&#8217;s all fine and dandy I hear you say, but if the brave new world of SOA were so cut and dry you wouldn&#8217;t be writing this blog post! Well true, the issues that arise are very different from those when you develop everything as &#8220;one app&#8221; and here are some of the harder ones:</p>
<ul>
<li>Authentication and sessions &#8211; do all services talk to the same session store?</li>
<li>If we want to do &#8220;real time&#8221; in the browser, e.g. using WebSockets, does that mean all of our backend services need to be WebSocket aware, or even <a href="http://socket.io/">socket.io</a> aware (if we use that library)?</li>
<li>Will we need to use rewrites to mitigate cross domain request issues in the browser?</li>
<li>Does the UI need to be aware of all the possible hosts/ports/paths to services on the backend?</li>
<li>With multiple backend services possibly providing push updates to the frontend, do we need multiple socket connections from the browser?</li>
</ul>
<p>So how do we go about tackling these? Step this way, I&#8217;ll try not to bore you&#8230;</p>
<h2>Authentication, authorisation and sessions</h2>
<p>As we wanted to avoid duplication of methods across multiple services we decided on building a thin layer service that sits between the two. Any request performed by a user must first go via this thin layer before being routed to the backend. By doing this, we get to perform authentication and authorisation in one central place rather than having every service check if user is currently logged in and if they should be allowed to perform an action.</p>
<p>We created two separate services to handle authentication:</p>
<ol>
<li>The <em>auth</em> app handles performing user account lookups with the backend users service before creating a session in MongoDB and forwarding the user to the main UI. This allows us to both scale auth separately and allows for single sign-on capabilities if we want to go down that road. [1]</li>
<li>Our main thin layer service uses the same MongoDB session store to check if a user is authenticated before appending their account details to the request and then acting as a HTTP router to the requested service. Any request that doesn&#8217;t also have a corresponding authenticated session is immediately stopped, with an appropriate HTTP error status code. [2]</li>
</ol>
<p>[1] In order to access the session storage in the same way, the auth app and UI share a core library with session middleware.<br />
[2] Backend services are not externally routed, <a href="http://blog.serverdensity.com/how-to-configure-nginx-as-a-load-balancer/">our Nginx load balancers</a> only allow access via the thin layer, and most services do not even have externally accessible network addressees.</p>
<p>By accepting account details appended to the request query string, an individual service doesn&#8217;t have to perform any extra user detail lookups and for the most part just has to use the provided user ID and account ID to restrict database queries. This will change slightly as we introduce more fine grained access controls to some areas of some services, but for the most part this covers our needs.</p>
<h2>WebSockets, socket.io and services</h2>
<p>One decision that was made early on was that we didn&#8217;t want to be performing inefficient polling for updates like we do in v1. As reliable as this is in terms of being proven technology (nothing can be simpler than issuing a GET every minute), there are now several alternative solutions for &#8220;[more] real time&#8221; updates, under the umbrella of the HTML5 specifications:</p>
<ul>
<li><a href="http://www.w3.org/TR/eventsource/">Server Sent Events</a> - a stream of events sent as a special part of the HTTP response body during a request that can be listened for using a JavaScript API.</li>
<li><a href="http://www.w3.org/TR/websockets/">WebSockets</a> - a two way persistent socket connection created by issuing an HTTP upgrade header from a regular request that can be opened, listened to and have messages sent over using a JavaScript API.</li>
</ul>
<p>Take note that both have advantages and disadvantages &#8211; while WebSockets provide efficient two way messaging, because they&#8217;re effectively a different protocol that runs on separate ports, some users may have issues connecting through firewalls. There are also other networking issues to consider such as whether your load balancer supports them.</p>
<p>Server Sent Events have the upper hand in that they are just an extension of regular ol&#8217; HTTP and can just be used on a longpoll connection. Any messages you might need to send upstream can be sent as extra regular concurrent HTTP requests (the open request and event API is asynchronous like any regular<code>XMLHTTPRequest</code>).</p>
<p>For our needs, WebSockets seemed like the best fit and most concerns over compatibility (both networking and browser support) can be circumvented by using a library such as <a href="http://socket.io/">socket.io</a> or <a href="http://sockjs.org/">SockJS</a>. They provide a convenient wrapper around various socket or socket-like browser messaging solutions, e.g WebSockets, Flash sockets, HTTP longpolling etc., with any failure in creating a messaging channel failing back to a more reliable method (in most cases longpolling).</p>
<p>We eventually chose socket.io due to it&#8217;s stability and well established support across platforms, but what about backend support for sockets? Or even libraries like socket.io? There is fairly good support in our core platform (Python) and even some support penetrating our secondary platform (PHP) for socket.io but we didn&#8217;t want to have to support our wrapper library across every service. Instead we decided to keep to standard web technology like WebSockets and instead leave compatibility between the frontend abstraction and backend transport up to the thin layer service.</p>
<p>This made our choice of platform for the thin layer quite natural given the following constraints:</p>
<ul>
<li>Very fast with a preferably event based networking API.</li>
<li>First class socket.io <strong>and</strong> WebSocket support.</li>
<li>As an added bonus, a mature HTTP routing/proxying library wouldn&#8217;t go amiss.</li>
</ul>
<p><a href="http://nodejs.org/">Node.js</a> met all these requirements perfectly.</p>
<p><strong>N.B.</strong> We could have also chosen Python to write it in because we already use both <a href="http://www.gevent.org/">Gevent</a> and <a href="http://www.tornadoweb.org/">Tornado</a> which both have thirdparty socket.io compatibility libraries available and provide fast event based networking capabilities.</p>
<p>Despite this, we chose Node.js because it is the defacto target platform for socket.io. This allows us to keep up with the latest version of the library and API. We also chose to write the thin layer in <a href="http://coffescript.org/">CoffeeScript</a> because our frontend is written in CS and we have lots of experience from other parts of the system. Since the thin layer is a long running daemon process, we can deal with a few cycles spent at startup to compile the CS to JS.</p>
<h2>Routing frontend requests to services</h2>
<p>Due to cross domain restrictions (<a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a> alleviates many of these issues), session cookie and SSL certificate requirements, we require the ability to proxy requests to separate services via a single thin layer address, using the URL path to seamlessly route to a backend address.</p>
<p>As we&#8217;re already using Node.js we were able to take advantage of the excellent <a href="https://github.com/nodejitsu/node-http-proxy">node-http-proxy</a> library, which pretty much does exactly this. We add a few extra goodies onto the plain routing in <em>http-proxy</em>, such as configurable HTTP headers for cross domain requests and CSRF protection.</p>
<p>Our two main requirements are authentication handling and address mapping, both for HTTP requests <strong>and</strong> socket connections. To enable this we added a <a href="http://www.senchalabs.org/connect/">Connect</a> style plugin system that allows addresses to be remapped easily for different purposes beyond the mapping built into <em>http-proxy</em> or for data to be injected into requests before forwarding, like adding account details to query strings after querying MongoDB.</p>
<p>How simple is the plugin API? Just add one or several methods like <code>get</code>, <code>post</code>, <code>put</code>, <code>delete</code>, <code>map</code> or <code>socket</code> to your plugin class and the routing handlers will do the rest.</p>
<p>One of <em>http-proxy</em>&#8216;s features is WebSocket routing, however due to using socket.io this doesn&#8217;t get used, instead&#8230;</p>
<h2>Aggregating multiple backend connections over a single frontend socket</h2>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/sockiiflow.png"><img class="aligncenter size-full wp-image-3538" alt="Sockii request flowchart" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/sockiiflow.png" width="574" height="465" /></a></p>
<p>With the socket.io server side handling built into the thin layer we are able to take advantage of having full control over the stack between thin layer and backend service, by terminating the abstracted socket at the Node.js instance and then creating one or more real WebSocket connections to the backend services.</p>
<p>Instead of creating new connections from the frontend to services we just append a different ID to our messages and the thin layer routes the messages to the appropriate service, crating a new WebSocket if it needs to. On receipt of messages from this connection, it appends the same ID to them before sending them back to the frontend.</p>
<p>This socket aggregation also means connections are lazy, only created as needed by the frontend, but once created they remain and will continue to push &#8220;real time&#8221; updates back to the UI.</p>
<p>Another extension of this method is the ability to push other messages over a single connection. Once you have a connection to a service over a WebSocket you can do anything over that socket you might have done with individual requests; this was part of the reason for choosing sockets. However, we are also able to tell the thin layer to send HTTP requests with a socket message and to tag the response with an ID before sending back as a socket message.</p>
<p>This doesn&#8217;t save us much in terms of requests on the backend but this part of our infrastructure is relatively cheap to scale due to various tricks we can employ such as SSL termination. Instead it saves the user&#8217;s browser from sending and receiving lots of expensive HTTP requests.</p>
<h2>Sockii to the rescue!</h2>
<p><em>Sockii</em> is our internal name for the thin layer we created &#8211; it can do everything described above and some more besides, all from a simple JSON config.</p>
<p>We will continuously improve Sockii, and it&#8217;s currently sparse documentation, and as of today we&#8217;ve released it under a BSD license available for <a href="https://github.com/serverdensity/sockii">everyone to fork and deploy</a>!</p>
<p>So when you&#8217;re using Server Density to see real time updates of your cloud instance build status or the response time of your websites, you know a little about what&#8217;s connecting our backend services to your browser client.</p>
<p>The post <a href="http://blog.serverdensity.com/introducing-sockii-http-and-websocket-aggregator/">Introducing Sockii: HTTP and WebSocket aggregator</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/a1znOljhlFA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/introducing-sockii-http-and-websocket-aggregator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/introducing-sockii-http-and-websocket-aggregator/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=introducing-sockii-http-and-websocket-aggregator</feedburner:origLink></item>
		<item>
		<title>Sysadmin Sunday 124</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/5daC9r_VCHs/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-124/#comments</comments>
		<pubDate>Sun, 28 Apr 2013 14:00:07 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3535</guid>
		<description><![CDATA[<p>MongoDB ops best practices Native SSL support made us choose RabbitMQ instead of MongoDB as our Celery task queue backend Propagation Delay and Its Relationship to Maximum Cable Length Pirate [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-124/">Sysadmin Sunday 124</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/ZniLyi"><span></span>MongoDB ops best practices</a></li>
<li><a href="http://buff.ly/15M09vR"><span></span>Native SSL support made us choose RabbitMQ instead of MongoDB as our Celery task queue backend</a></li>
<li><a href="http://buff.ly/ZniFXB"><span></span>Propagation Delay and Its Relationship to Maximum Cable Length</a></li>
<li><a href="http://buff.ly/11ERmY6"><span></span>Pirate Bay Finds Safe Haven in Iceland, Switches to .IS Domain</a></li>
<li><a href="http://buff.ly/15J2PKu"><span></span>Ubuntu 13.04 (Raring Ringtail) released</a></li>
<li><a href="http://buff.ly/11CoaBc"><span></span>Over 25% of Verizon Wireless Traffic Is Now Over IPv6</a></li>
<li><a href="http://buff.ly/11CnFab"><span></span>nginx 1.4 stable: WebSocket connections, OCSP stapling, SPDY module, gunzip filter and more</a></li>
<li><a href="http://buff.ly/11Bl5zT"><span></span>Process Managers: The Good, the Bad, and the Ugly</a></li>
<li><a href="http://buff.ly/ZeH41t"><span></span>A Primer on IPv4, IPv6 and Transition</a></li>
<li><a href="http://buff.ly/15vBJ9y"><span></span>SSL And the Future Of Authenticity</a></li>
<li><a href="http://buff.ly/16QX777"><span></span>Google: &#8220;We&#8217;ll track EVERY task on EVERY data center server&#8221;</a></li>
<li><a href="http://buff.ly/11m2k4J"><span></span>Former Hostgator employee arrested, charged with rooting 2,700 servers</a></li>
<li><a href="http://buff.ly/14CqzQN"><span></span>&#8220;ack is a grep-like search tool that has been optimized for searching large heterogeneous trees of source code.&#8221;</a></li>
<li><a href="http://buff.ly/14zP7dn"><span></span>Two Trillion Objects, 1.1 Million Requests / Second</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-124/">Sysadmin Sunday 124</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/5daC9r_VCHs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-124/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-124/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-124</feedburner:origLink></item>
		<item>
		<title>Using Celery for queuing requests</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/Sb5vv9vK7AI/</link>
		<comments>http://blog.serverdensity.com/using-celery-for-queuing-requests/#comments</comments>
		<pubDate>Thu, 25 Apr 2013 13:00:35 +0000</pubDate>
		<dc:creator>Sebastian Pawluś</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[RabbitMQ]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3517</guid>
		<description><![CDATA[<p>For Server Density v2 we&#8217;ve taken a lot of time to redesign how we handle our website monitoring, particularly in relation to how we avoid false positives. We&#8217;ve also added [...]</p><p>The post <a href="http://blog.serverdensity.com/using-celery-for-queuing-requests/">Using Celery for queuing requests</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>For <a href="http://www.serverdensity.com/comingsoon/">Server Density v2</a> we&#8217;ve taken a lot of time to redesign how we handle our website monitoring, particularly in relation to how we avoid false positives. We&#8217;ve also added much more control and visibility into how our queuing system works because the current one is almost like a black box because ZeroMQ is not great at being transparent with regards to what&#8217;s actually happening.</p>
<p>Every minute our monitoring nodes issue requests to a public URL/IP, usually a website. They question whether whatever you&#8217;re monitoring is running, provide you with response time statistics and gather any other useful information. Oh, and if it&#8217;s down &#8211; we&#8217;ll let you know (even if it is 2am).</p>
<p>Just because your website is up in London, it doesn&#8217;t necessarily mean that it&#8217;ll perform the same to visitors in Australia. So we monitor performance from locations <a title="Server monitoring world map" href="http://www.serverdensity.com/map/">all over the world</a>. This provides you with an overview of how your service is performing &#8211; <em>regardless of visitor location.</em></p>
<h2>The Process</h2>
<p>To deliver you all of this information we decided to create a director-actor (server-client) infrastructure. The &#8216;director&#8217; within our data centre, and the &#8216;actor&#8217; being a machine placed somewhere in a distant location like Sydney (~16,000 km from London). The &#8216;director&#8217; propagates checks for each of the &#8216;actors&#8217; locations, which perform the requested check and return the result to the &#8216;director&#8217;.</p>
<h2>The Tech</h2>
<p>To facilitate the director-actor (server-client) architecture, we chose a message broker software to act as a transport layer between both entities. For this we&#8217;ve used the following tool set: Python, <a href="http://www.celeryproject.org/">Celery</a>, RabbitMQ and Gevent.</p>
<p>We&#8217;ve previously <a href="https://blog.serverdensity.com/queueing-mongodb-using-mongodb/">created our own basic queuing system using MongoDB</a> but given Celery supports MongoDB as a backend, we started using that. We know how to scale Mongo in production and it has excellent replication/failover capabilities, but we hit some problems which forced us to use RabbitMQ instead.</p>
<p>If you consider HTTP checks for the POST method, <em>it may be that some users send sensitive data, or use some sort of authorisation for the targeted URL (or both).</em> The monitoring nodes are hosted with various vendors around the world and communicate with our central directors over the internet rather than our secure, internal network. This means we need to ensure communication is secure, which either means a VPN or SSL. We didn&#8217;t really want to deal with managing a VPN of a large number of nodes around the world so decided to investigate SSL transports instead.</p>
<p>Celery is smart and robust tool which is really easy to extend. But being in the stage of prototyping means that we do things fast and adjust later, this way we decided to go with the RabbitMQ broker with had full support for SSL encryption inside Celery backends, also MongoDB as a backend was still considered an a experimental option. Have a look <a href="http://docs.celeryproject.org/en/latest/getting-started/brokers/" title="Celery docs">inside the Celery docs</a> to decide which broker will work best for you.</p>
<p>We do intend to switch to using MongoDB for the Celery backend eventually, and <a href="https://github.com/celery/celery/issues/1203">have submitted a patch to add SSL support to Celery</a>. RabbitMQ is working well but it&#8217;s another component in our architecture and given our existing experience with MongoDB, we prefer to reduce the number of 3rd party tools where possible. It also has better failover support.</p>
<p>It was better to solve this problem by looking into what we didn&#8217;t want to do as opposed to what we did. We knew we didn&#8217;t want to do raw socket connection, write our own broker or worry too much about scalability at this stage. This is the solution that we chose as a result. Admittedly, the tech used may well change in the future &#8211; but it&#8217;s solving the problem well right now, and we&#8217;re still experimenting with it.</p>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/Service-Monitor-.png"><img class="alignnone size-full wp-image-3520" alt="Server Density Service Monitoring Architecture" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/Service-Monitor-.png" width="100%" height="auto" style="margin-bottom:2em;" /></a></p>
<h3>The Director</h3>
<p>The diagram above presents a simplified structure of the current architecture layout for Celery queues. Checks are described by the location on which we are going to execute them. We allow users to create checks from more than one location, so the same URL will often land on different queues at the same time.</p>
<p>The director assembles a check from the information provided by a user. In a URL check for example, that information could be: target URL, check method (GET, POST, PUT, DELETE), payload, timeout, etc. Information in this form will be serialised and allocated to the right location queue.</p>
<p>Server Density currently supports <a title="Server Density monitoring node locations and IP addresses" href="http://support.serverdensity.com/knowledgebase/articles/75926-monitoring-node-locations-and-ip-addresses">9 locations</a> with more on the horizon. </p>
<h3>The Actor</h3>
<p>At the other end of the process (a couple of thousands kilometres away), our actors are working hard to handle the check location queues. They&#8217;re designed to take traveling checks from the queue, interpret the message received and perform the requested actions. </p>
<p>We were concerned about how to handle things here. Primarily because we don&#8217;t want to evaluate status just by doing one URL check, here&#8217;s why:</p>
<pre style="margin-bottom: 2em!important;">&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.repeat(
... "requests.get('http://example.com')",
... "import requests",
... number=1,
... repeat=5)</pre>
<pre style="margin-bottom: 2em!important;">[0.9308030605316162,
2.1385269165039062,
3.0700418949127197,
6.3459131717681885,
1.9396629333496094]</pre>
<p>Previously Server Density did one check every minute but we found this had its problems. There are hundreds of things that can go wrong when requests are being sent around the world, alerting users that a website was down for example.</p>
<p>As a result v2 now sends 3 checks each time and records the fastest response &#8211; not the average. One check out of the three could timeout for example bringing the entire average down. In this use case people want to see the shortest response time figure. This will be put on the responses queues and send back to the dDirector, which then acts upon the information. We still store the results of all checks and these will be exposed in the UI for the user.</p>
<h2>The Scale</h2>
<p>Since we are using Celery gevent we can benefit from the fact that one queue can be handled by more than one worker (and vice versa). So what are the implications of this? If we see any scale related problems we have few options:</p>
<ol>
<li>Increase the concurrency level. We are using gevent and can therefore benefit from greenlets.</li>
<li>Increase the number of processes. Python has this thing called GIL, right? By deploying another process you can try to bypass this and force your box to do things in parallel.</li>
<li>Increase the number of machines. Install more workers with information on which queue(s) to consume.</li>
</ol>
<h2>Conclusion</h2>
<p>The most important change is the check methodology &#8211; doing 3 checks per location. Further, every location executes the check at the same time so you can see the response time from every location at once, rather than one at a time. Instead of having to do a lot of the queue management functionality ourselves within ZeroMQ, using Celery we can pass that over to the library and dedicate more time to check methodology. It also provides more ways to inspect the queue status and ties into our own monitoring so we know sooner when things are going wrong.</p>
<p>The post <a href="http://blog.serverdensity.com/using-celery-for-queuing-requests/">Using Celery for queuing requests</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/Sb5vv9vK7AI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/using-celery-for-queuing-requests/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/using-celery-for-queuing-requests/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=using-celery-for-queuing-requests</feedburner:origLink></item>
		<item>
		<title>Sysadmin Sunday 123</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/tEpkAszr2dM/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-123/#comments</comments>
		<pubDate>Sun, 21 Apr 2013 14:00:28 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3530</guid>
		<description><![CDATA[<p>Redis as the primary data store? An HTTP reverse proxy for realtime A load test against load balancers / proxies that support WebSockets Ubuntu low-mem install for VMs Git Koans [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-123/">Sysadmin Sunday 123</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/YGtVxL"><span></span>Redis as the primary data store?</a></li>
<li><a href="http://j.mp/16JMbYY"><span></span>An HTTP reverse proxy for realtime</a></li>
<li><a href="http://buff.ly/16KcXQO"><span></span>A load test against load balancers / proxies that support WebSockets</a></li>
<li><a href="http://buff.ly/YfdJnO"><span></span>Ubuntu low-mem install for VMs</a></li>
<li><a href="http://bit.ly/16IfsmO"><span></span>Git Koans</a></li>
<li><a href="http://buff.ly/10W2247"><span></span>New Hash-based Sharding Feature in MongoDB 2.4</a></li>
<li><a href="http://buff.ly/ZhH684"><span></span>Obama for America on AWS &#8211; Infrastructure Architecture</a></li>
<li><a href="http://buff.ly/11cHioN"><span></span>Who is Responsible for PaaS Cloud Application Performance?</a></li>
<li><a href="http://buff.ly/17zf2jW"><span></span>The need for releases</a></li>
<li><a href="http://buff.ly/11cHlkA"><span></span>Programming 101 for Network Engineers – Why Bother?</a></li>
<li><a href="http://buff.ly/11dS7Y4"><span></span>Tachyon &#8211; Fault Tolerant Distributed File System with 300 Times Higher Throughput than HDFS</a></li>
<li><a href="http://buff.ly/xIxUp1"><span></span>Ancient Computers in Use Today</a></li>
<li><a href="http://buff.ly/173LjyB"><span></span>Secure Your REST API&#8230; The Right Way</a></li>
<li><a href="http://buff.ly/12iRVb7"><span></span>Is your MySQL buffer pool warm? Make it sweat!</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-123/">Sysadmin Sunday 123</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/tEpkAszr2dM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-123/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-123/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-123</feedburner:origLink></item>
		<item>
		<title>MongoDB Benchmarks</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/4Ctij6x9n-M/</link>
		<comments>http://blog.serverdensity.com/mongodb-benchmarks/#comments</comments>
		<pubDate>Thu, 18 Apr 2013 13:00:17 +0000</pubDate>
		<dc:creator>David Mytton</dc:creator>
				<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3519</guid>
		<description><![CDATA[<p>There are no official MongoDB benchmarks because the developers don’t believe they accurately represent real world usage. This is true because you can only really get an idea of performance [...]</p><p>The post <a href="http://blog.serverdensity.com/mongodb-benchmarks/">MongoDB Benchmarks</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>There are no official MongoDB benchmarks because the developers don’t believe they accurately represent real world usage. This is true because you can only really get an idea of performance when you’re <a href="http://blog.serverdensity.com/real-world-mongodb-benchmarks-with-benchrun/">testing your own queries on your own hardware</a>. Raw figures can seem impressive but they’re not representative of how your own application is likely to perform. Benchmarks are useful for indicating how different hardware specs might perform but are really only worth it if you use real world queries.
<p>For <a href="http://www.serverdensity.com/comingsoon/">Server Density v2</a> I have been benchmarking MongoDB with <a href="http://blog.serverdensity.com/mongodb-schema-design-pitfalls/">different tweaks</a> so we can get maximum performance for our high throughput clusters, but make cost savings for our less important systems. A lot has been said about various choices of write concern, deploying to SSDs and replication lag but there aren&#8217;t really any numbers to base your decision on.</p>
<p>This set of MongoDB benchmarks is not about the absolute numbers but is designed to give you an idea of how each of the different options affects performance. Your own queries will differ but the idea is to prove general assumptions and principles about the relative differences between each of the write options.</p>
<h2>Test methodology</h2>
<p>These MongoDB benchmarks test various options for configuring and querying MongoDB. I wrote a simple Python script to issue 200 queries and record the execution time for each. It was run with Python 2.7.3 and Pymongo 2.5 against MongoDB 2.4.1 on an Ubuntu Linux 12.04 Intel Xeon-SandyBridge E3-1270-Quadcore 3.4GHz dedicated server with 32GB RAM, Western Digital WD Caviar RE4 500GB spinning disk and Smart XceedIOPS 200GB SSD.</p>
<p>The script was run twice, taking the results from the second execution. This avoids slowdown cause by initially allocating files, collections, etc &#8211; MongoDB only creates databases when they&#8217;re first written which adds a bit of time to the first call but isn&#8217;t really relevant in real world usage.</p>
<pre><code data-language="python">
import time
import pymongo
m = pymongo.MongoClient()

doc = {'a': 1, 'b': 'hat'}

i = 0

while (i < 200):

	start = time.time()
	m.tests.insertTest.insert(doc, manipulate=False, w=1)
	end = time.time()

	executionTime = (end - start) * 1000 # Convert to ms

	print executionTime

	i = i + 1

</code></pre>
<p></p>
<p>This is a dummy document because I'm not trying to simulate a real application here. Document size, number/size of indexes and the type of operation will all play a part in the actual numbers. This is only testing inserts but there are <a href="http://blog.serverdensity.com/mongodb-schema-design-pitfalls/">other optimisations you can make with updates</a>, particularly ensuring documents don't grow. However, this is sufficient for what I'm trying to show in these tests - the relative difference between the write options.</p>
<h2>Write concern</h2>
<p>The <a href="http://docs.mongodb.org/manual/core/write-operations/#write-concern">write concern</a> allows you to trade write performance with knowing the status of the write. If you're doing high throughput logging but aren't concerned about possibly losing some writes (e.g. if the mongod crashes or there is a network error) then you can set the write concern low. Your write calls will return quickly but you won't know if they were successful. The write concern can be dialed up to including error handling (the default) so the write will be acknowledged (not necessarily safe on disk).</p>
<p>It's important to know that an acknowledgement is not the same as a successful write - it simply gives you a receipt that the server accepted the write to process. If you need to know that writes were actually successful one option is to require confirmation the write has hit the journal. This is essentially a safe write to the single node with the option to go further to <a href="http://docs.mongodb.org/manual/core/write-concern/#replica-set-write-concern">request acknowledgement from replica slaves</a>. It's much slower to do this but guarantees your data is replicated.</p>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-w-flag.png"><img class="alignnone size-full wp-image-3523" alt="MongoDB insert() Performance (w flag)" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-w-flag.png" width="751" height="414" /></a></p>
<ul>
<li style="margin-bottom:1em!important;"><code>w=0</code> is the fastest way to issue writes, with an average execution time of 0.07ms, max of 0.11ms and min of 0.06ms. This setting disables basic acknowledgment of write operations, but returns information about socket excepts and networking errors to the application.</li>
<li style="margin-bottom:1em!important;"><code>w=1</code> takes double the time to return, with an average execution time of 0.13ms, max of 0.32ms and min of 0.11ms. This guarantees that the write has been acknowledged but doesn't guarantee that it has reached disk (the journal), so there is still potential for the write to be lost - there's a 100ms window where the journal might not be flushed to disk. Setting <code>j=1</code> protects against this.</li>
<li style="margin-bottom:1em!important;"><code>j=1</code> (spinning disk) is several orders of magnitude slower than even <code>w=1</code>, with an average execution time of 34.19ms, max of 34.28ms and min of 34.10ms. The mongod will confirm the write operation only after it has written the operation to the journal. This confirms that the write operation can survive a mongod shutdown and ensures that the write operation is durable.</li>
<li style="margin-bottom:1em!important;"><code>j=1</code> (SSD) is x3 faster than a spinning disk with an average execution time of 11.18ms, max of 11.24ms and min of 11.11ms.</li>
<li style="margin-bottom:1em!important;">There is an interesting ramp up for the initial few queries every time the script is run. This is likely to do with connection pooling and opening the initial connection to the database, whereas subsequent queries can use the already open connection.</li>
<li style="margin-bottom:1em!important;">Some spikes appear during the script execution. This could be the connection closing and being recreated.</li>
</ul>
<p>This means that you can reasonably use the default <code>w=1</code> as a safe starting point but if you need to be sure data has gone to a single node, <code>j=1</code> is the option you need. And for high throughput you can half query times by going down to <code>w=0</code>.</p>
<h2>SSD vs Spinning Disk</h2>
<p>It's a safe assumption that SSDs will always be faster than spinning disks, but the question is how much - and is that worth paying for them? The more data you store, the more expensive the SSD will be - higher capacity SSDs are available but they are fairly cost prohibitive. However, MongoDB supports storing databases in directories which can be mounted to their own devices, giving you the option of putting certain databases on SSDs.</p>
<p>Putting your journal on an SSD and then using the <code>j=1</code> flag is a good optimisation. You need the <a href="http://docs.mongodb.org/manual/reference/mongod/#cmdoption-mongod--directoryperdb"><code>--directoryperdb</code> config flag</a> and you can then mount the databases on their own disks. The journal is always in its own directory so you can mount it separately without any changes if you wish.</p>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmark-j-flag-ssd.png"><img class="alignnone size-full wp-image-3522" alt="MongoDB insert() Performance (j flag)" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmark-j-flag-ssd.png" width="734" height="432" /></a></p>
<h2>Replication</h2>
<p>If you specify a number greater than 1 for the <code>w</code> flag then this will require <code>n</code> number of replica slaves to acknowledge the write before the query completes. I tested this in a x4 node replica set with the primary and a slave in the same data centre (San Jose, USA) as the execution script and the remaining x2 nodes in a different data centre (Washington DC, USA).</p>
<p>The average round trip time between the nodes in the same data centre is 0.864ms and between different data centres is 71.187ms.</p>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-replication.png"><img class="alignnone size-full wp-image-3524" alt="MongoDB insert() Performance (w &gt; 1 flag)" src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-replication.png" width="736" height="365" /></a></p>
<ul>
<li style="margin-bottom:1em!important;"><code>w=2</code> required acknowledgement from the primary and one of the 3 slaves. Average execution time was 14ms, max of 867ms and min of 1.6ms.</li>
<li style="margin-bottom:1em!important;"><code>w=3</code> required acknowledgement from the primary plus 2 slaves. Average execution time was 310ms, max of 1329ms and min of 96ms. The killer here is the range in response times, which are affected by network latency + congestion, communication overhead between 3 nodes and having to wait for each one.</li>
</ul>
<p>Using an integer for the <code>w</code> flag lets MongoDB decide which nodes must acknowledge. My replica set has 4 nodes and I specified 2 and 3 but I didn't get to choose which ones were part of the acknowledgement. This could be local slaves but could also be remote, which is probably responsible for the range in response times where a remote slave happened to return faster than the local one. More control is possible using <a href="http://docs.mongodb.org/manual/reference/replica-configuration/#replica-set-configuration-tag-sets">tags</a>.</p>
<h2>Conclusion</h2>
<p>It's fairly clear that these MongoDB benchmark results validate the general assumptions that SSDs are faster and there is a fairly variable latency involved with replicating over a network, particularly over long distances. What this experiment shows is the differences between the write concern options so you can make the right tradeoff between durability and performance. It also highlights that you can significantly improve performance if you need the journal based durability by adding SSDs.</p>
<h3>MongoDB benchmarks raw results</h3>
<table>
<tbody>
<tr>
<td valign="top">&nbsp;</td>
<td valign="top"><b><code>w=0</code></b></td>
<td valign="top"><b><code>w=1</code></b></td>
<td valign="top"><b><code>j=1</code></b><br />Spinning</td>
<td valign="top"><b><code>j=1</code></b><br />SSD</td>
<td valign="top"><b><code>w=2</code></b><br />Same DC</td>
<td valign="top"><b><code>w=3</code></b><br />Multi-DC</td>
</tr>
<tr>
<td valign="top"><b>Average</b></td>
<td valign="top">0.07ms</td>
<td valign="top">0.13ms</td>
<td valign="top">34.19ms</td>
<td valign="top">11.18ms</td>
<td valign="top">14.26ms</td>
<td valign="top">311ms</td>
</tr>
<tr>
<td valign="top"><b>Min</b></td>
<td valign="top">0.06ms</td>
<td valign="top">0.11ms</td>
<td valign="top">34.10ms</td>
<td valign="top">11.11ms</td>
<td valign="top">1.65ms</td>
<td valign="top">97ms</td>
</tr>
<tr>
<td valign="top"><b>Max</b></td>
<td valign="top">0.11ms</td>
<td valign="top">0.32ms</td>
<td valign="top">34.28ms</td>
<td valign="top">11.24ms</td>
<td valign="top">867.29ms</td>
<td valign="top">1,329ms</td>
</tr>
</tbody>
</table>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks.png"><img src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks.png" alt="MongoDB Benchmarks" width="731" height="332" class="alignnone size-full wp-image-3526" /></a></p>
<p><a href="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-no-w3.png"><img src="http://serverdensity.wpengine.netdna-cdn.com/wp-content/uploads/2013/04/mongodb-benchmarks-no-w3.png" alt="mongodb-benchmarks-no-w3" width="732" height="362" class="alignnone size-full wp-image-3525" /></a></p>
<p>The post <a href="http://blog.serverdensity.com/mongodb-benchmarks/">MongoDB Benchmarks</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/4Ctij6x9n-M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/mongodb-benchmarks/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/mongodb-benchmarks/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mongodb-benchmarks</feedburner:origLink></item>
		<item>
		<title>Sysadmin Sunday 122</title>
		<link>http://feedproxy.google.com/~r/serverdensity/~3/o69mGqPeh3Y/</link>
		<comments>http://blog.serverdensity.com/sysadmin-sunday-122/#comments</comments>
		<pubDate>Sun, 14 Apr 2013 15:00:45 +0000</pubDate>
		<dc:creator>rufus</dc:creator>
				<category><![CDATA[Sysadmin Sunday]]></category>

		<guid isPermaLink="false">http://blog.serverdensity.com/?p=3515</guid>
		<description><![CDATA[<p>Top 10 Reasons I like Postgres Over SQL Server Why ZFS still needs an equivalent of fsck MongoDB Pub/Sub with Capped Collections Seeking Sucks: Spoiled by SSDs The Monitoring Stack [...]</p><p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-122/">Sysadmin Sunday 122</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p>]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://buff.ly/10M1sFP"><span></span>Top 10 Reasons I like Postgres Over SQL Server</a></li>
<li><a href="http://buff.ly/17mhjPr"><span></span>Why ZFS still needs an equivalent of fsck</a></li>
<li><a href="http://buff.ly/XYvFTJ"><span></span>MongoDB Pub/Sub with Capped Collections</a></li>
<li><a href="http://buff.ly/YaJxu1"><span></span>Seeking Sucks: Spoiled by SSDs</a></li>
<li><a href="http://buff.ly/Y9b0wh"><span></span>The Monitoring Stack (the state of the art)</a></li>
<li><a href="http://buff.ly/YRmFhS"><span></span>Building Technical Literacy in Business Teams</a></li>
<li><a href="http://buff.ly/16Gkb8w"><span></span>DevOps Consulting &#8211; Why I Don’t</a></li>
<li><a href="http://buff.ly/16GtRA2"><span></span>Don&#8217;t Copy-Paste from Website to Terminal</a></li>
<li><a href="http://buff.ly/17hMMSR"><span></span>Don’t Use Linksys Routers</a></li>
<li><a href="http://buff.ly/Y4VVeY"><span></span>Detecting TOR Communication in Network Traffic</a></li>
<li><a href="http://buff.ly/16t3lrL"><span></span>put a burger in your shell</a></li>
<li><a href="http://buff.ly/Y2w5E3"><span></span>URLs are for People, not Computers</a></li>
<li><a href="http://buff.ly/YXbbtf"><span></span>Python 3.3 with Ubuntu #linux 13.04</a></li>
</ul>
<p>The post <a href="http://blog.serverdensity.com/sysadmin-sunday-122/">Sysadmin Sunday 122</a> appeared first on <a href="http://blog.serverdensity.com">Server Density Blog</a>.</p><img src="http://feeds.feedburner.com/~r/serverdensity/~4/o69mGqPeh3Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.serverdensity.com/sysadmin-sunday-122/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.serverdensity.com/sysadmin-sunday-122/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sysadmin-sunday-122</feedburner:origLink></item>
	</channel>
</rss>
