<?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>Alexey Kovyrin's Blog</title>
	
	<link>http://kovyrin.net</link>
	<description>Yet Another Admin's blog</description>
	<lastBuildDate>Tue, 17 Aug 2010 15:55:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Homo-Adminus" /><feedburner:info uri="homo-adminus" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Scribd is Hiring (I’m Looking for an Operations Engineer to Join My Team)</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/PqbAzRHL-mg/</link>
		<comments>http://kovyrin.net/2010/08/17/scribd-is-hiring/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 15:51:06 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Networks]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[operations]]></category>
		<category><![CDATA[scribd]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=502</guid>
		<description><![CDATA[Scribd is a top 100 site on the web and one of the largest sites built using Ruby on Rails. As one of the first rails sites to reach scale, we&#8217;ve built a lot of infrastructure and solved a lot of challenges to get Scribd to where it is today. We actively try to push [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.scribd.com/">Scribd</a> is a <a href="http://rails100.pbworks.com/Alexa+Rankings">top 100 site</a> on the web and one of the largest sites built using Ruby on Rails. As one of the first rails sites to reach scale, we&#8217;ve built a lot of infrastructure and solved a lot of challenges to get Scribd to where it is today. We actively try to push the envelope and have contributed substantial work back to the open source community.</p>
<p>Scribd has an agile, startup culture and an unusually close working relationship between engineering and ops. You&#8217;ll regularly find cross-over work at Scribd, with ops people writing application-layer code and engineers figuring out operations-level problems. We think we&#8217;re able to make that work because of the uniquely talented people we have on the team.</p>
<p>To allow us to keep scaling, we&#8217;re now looking to add a strong, experienced operations guru to the team. As a member of Scribd operations, you&#8217;ll have tremendous ownership and responsibility for one of the web&#8217;s most popular applications. Because Scribd is a startup, you will wear many hats and have broader responsibility than you would at a larger company.</p>
<p>If you read this blog, you should already have a good sense of the kind of work you&#8217;ll be doing on this position. </p>
<p><strong>The Ideal Profile</strong></p>
<p>You are an experienced operations professional and have run ops at at least one large-scale website. You have comprehensive knowledge of a broad variety of system tools, from MySQL and Nginx to Squid and Memcached. You should also have strong software development skills and be well-versed in major programming languages. You should be strongly motivated, a creative solution finder, and ready to jump into the thorniest technical problems whenever necessary.</p>
<p><strong> Responsibilities</strong></p>
<ul>
<li>Develop and maintain all aspects of Scribd&#8217;s operations infrastructure, including system monitoring, backups, server configuration, databases, and caching systems</li>
<li>Collaborate with engineering to create next generation infrastructure to support changing requirements</li>
<li>Predict scaling problems before they occur and work with engineering to prevent them</li>
<li>Write and debug application level ruby code</li>
<li>Participate in an on-call rotation</li>
<li>Quickly diagnose server problems and employ preventive measures to maintain high availability servers</li>
</ul>
<p><strong>Qualifications</strong></p>
<ul>
<li>Bachelors degree in CS or equivalent experience</li>
<li>3-5 years of professional experience in site operations</li>
<li>Strong software engineering skills, including knowledge of major programming languages</li>
<li>Strong database skills, preferably with MySQL, and overall linux knowledge</li>
<li>Experience with most of the following technologies: MySQL, Nginx, Ruby, Memcached, Squid, git, Solr, HBase, Postfix</li>
<li>Proven ability to quickly learn and implement unfamiliar technologies</li>
<li>Strong desire to work hard at a rapidly growing company</li>
</ul>
<p>Location: <strong>You are preferably located near San Francisco, CA</strong>. Relocation assistance is designed on a per-case basis. In short, we&#8217;ll be creative to get you here.</p>
<p>Contact: Please send your email cover letter and resume with the subject &#8220;Your name – Senior Site Operations Engineer – via Kovyrin.net&#8221; to jobs@scribd.com or contact me directly using <a href="http://kovyrin.net/contact/">any of my contacts</a>. All communication and correspondence is held in the strictest confidence to ensure that you can connect and learn more without exposure.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/RWGCGmnRKReW6byQK16_MflmLOE/0/da"><img src="http://feedads.g.doubleclick.net/~a/RWGCGmnRKReW6byQK16_MflmLOE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/RWGCGmnRKReW6byQK16_MflmLOE/1/da"><img src="http://feedads.g.doubleclick.net/~a/RWGCGmnRKReW6byQK16_MflmLOE/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=PqbAzRHL-mg:y4-nncz8nKI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=PqbAzRHL-mg:y4-nncz8nKI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=PqbAzRHL-mg:y4-nncz8nKI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=PqbAzRHL-mg:y4-nncz8nKI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=PqbAzRHL-mg:y4-nncz8nKI:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/08/17/scribd-is-hiring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/08/17/scribd-is-hiring/</feedburner:origLink></item>
		<item>
		<title>Nginx-Fu: X-Accel-Redirect From Remote Servers</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/1gvnDfslGWY/</link>
		<comments>http://kovyrin.net/2010/07/24/nginx-fu-x-accel-redirect-remote/#comments</comments>
		<pubDate>Sat, 24 Jul 2010 03:45:52 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Admin-tips]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Networks]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[nginx-fu]]></category>
		<category><![CDATA[redirect]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[x-accel-redirect]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=462</guid>
		<description><![CDATA[We use nginx and its features a lot in Scribd. Many times in the last year we needed some pretty interesting, but not supported feature &#8211; we wanted nginx X-Accel-Redirect functionality to work with remote URLs. Out of the box nginx supports this functionality for local URIs only. In this short post I want to [...]]]></description>
			<content:encoded><![CDATA[<p>We use <a href="http://nginx.org/">nginx</a> and its features a lot in <a href="http://www.scribd.com/">Scribd</a>. Many times in the last year we needed some pretty interesting, but not supported feature &#8211; we wanted nginx <a href="http://wiki.nginx.org/NginxXSendfile"><tt>X-Accel-Redirect</tt></a> functionality to work with remote URLs. Out of the box nginx supports this functionality for local URIs only. In this short post I want to explain how did we make nginx serve remote content via <nobr><tt>X-Accel-Redirect</tt></nobr>.</p>
<p><span id="more-462"></span></p>
<p>First of all, here is why you may need this feature. Let&#8217;s imagine you have a file storage on <a href="http://aws.amazon.com/s3/">Amazon S3</a> where you store tons of content. And you have an application where you have some content downloading functionality that you want to be available for logged-in/paying/premium users and/or you want to keep track of downloads your users perform on your site. If your content was on your web server, you could have used simple <a href="http://kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/">controlled downloads</a> functionality built-in to nginx out of the box. But the problem is that your content is remote.</p>
<p>Here is what we do to solve this problem.</p>
<p>First, we create a special location on our nginx server. This location will be used as a proxy for all our accelerated file downloads:</p>
<div class="codecolorer-container nginx twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="nginx codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #adadad; font-style: italic;"># Proxy download </span><br />
<span style="color: #00007f;">location</span> ~* ^/internal_redirect/<span style="color: #66cc66;">&#40;</span>.*?<span style="color: #66cc66;">&#41;</span>/<span style="color: #66cc66;">&#40;</span>.*<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Do not allow people to mess with this location directly</span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Only internal redirects are allowed</span><br />
&nbsp; <span style="color: #0000ff;">internal</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Location-specific logging</span><br />
&nbsp; <span style="color: #0000ff;">access_log</span> logs/internal_redirect.access.log main;<br />
&nbsp; <span style="color: #0000ff;">error_log</span> logs/internal_redirect.error.log warn;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Extract download url from the request</span><br />
&nbsp; set <span style="">$download_uri</span> <span style="">$2</span>;<br />
&nbsp; set <span style="">$download_host</span> <span style="">$1</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Compose download url</span><br />
&nbsp; set <span style="">$download_url</span> <span style="color: #00007f;">http</span>://<span style="">$download_host</span>/<span style="">$download_uri</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Set download request headers</span><br />
&nbsp; <span style="color: #0000ff;">proxy_set_header</span> <span style="">Host</span> <span style="">$download_host</span>;<br />
&nbsp; <span style="color: #0000ff;">proxy_set_header</span> Authorization <span style="color: #7f007f;">''</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># The next two lines could be used if your storage </span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># backend does not support Content-Disposition </span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># headers used to specify file name browsers use </span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># when save content to the disk</span><br />
&nbsp; proxy_hide_header Content-Disposition;<br />
&nbsp; add_header Content-Disposition <span style="color: #7f007f;">'attachment; filename=&quot;$args&quot;'</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Do not touch local disks when proxying </span><br />
&nbsp; <span style="color: #adadad; font-style: italic;"># content to clients</span><br />
&nbsp; proxy_max_temp_file_size <span style="color: #ff0000;">0</span>;<br />
<br />
&nbsp; <span style="color: #adadad; font-style: italic;"># Download the file and send it to client</span><br />
&nbsp; <span style="color: #0000ff;">proxy_pass</span> <span style="">$download_url</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>After adding this location to our nginx config we could start sending responses with headers like the following:</p>
<div class="codecolorer-container nginx twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="nginx codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #adadad; font-style: italic;"># This header will ask nginx to download a file </span><br />
<span style="color: #adadad; font-style: italic;"># from http://some.site.com/secret/url.ext and send it to user</span><br />
X-Accel-Redirect: /internal_redirect/some.site.com/secret/url.ext<br />
<br />
<span style="color: #adadad; font-style: italic;"># This header will ask nginx to download a file </span><br />
<span style="color: #adadad; font-style: italic;"># from http://blah.com/secret/url and send it to user as cool.pdf</span><br />
X-Accel-Redirect: /internal_redirect/blah.com/secret/url?cool.pdf</div></td></tr></tbody></table></div>
<p>Here is an example code you could use in a Rails application to use our internal redirect location:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> x_accel_url<span style="color:#006600; font-weight:bold;">&#40;</span>url, file_name = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; uri = <span style="color:#996600;">&quot;/internal_redirect/#{url.gsub('http://', '')}&quot;</span><br />
&nbsp; uri <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;?#{file_name}&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> file_name<br />
&nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> uri<br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">def</span> download<br />
&nbsp; headers<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'X-Accel-Redirect'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = x_accel_url<span style="color:#006600; font-weight:bold;">&#40;</span>some_secret_url, pretty_name<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; render <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>As you can see, nginx is really powerful tool and when you turn your creativity on you can make it even more powerful. Stay tuned for more <a href="http://kovyrin.net/tag/nginx-fu/">Nginx-Fu</a> posts.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/YMdbFfuKS6VH52An0qRhwXQyJz8/0/da"><img src="http://feedads.g.doubleclick.net/~a/YMdbFfuKS6VH52An0qRhwXQyJz8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/YMdbFfuKS6VH52An0qRhwXQyJz8/1/da"><img src="http://feedads.g.doubleclick.net/~a/YMdbFfuKS6VH52An0qRhwXQyJz8/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=1gvnDfslGWY:LUrpmTqfO4k:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=1gvnDfslGWY:LUrpmTqfO4k:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=1gvnDfslGWY:LUrpmTqfO4k:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=1gvnDfslGWY:LUrpmTqfO4k:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=1gvnDfslGWY:LUrpmTqfO4k:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/07/24/nginx-fu-x-accel-redirect-remote/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/07/24/nginx-fu-x-accel-redirect-remote/</feedburner:origLink></item>
		<item>
		<title>Cool Web Designer is Looking for Work</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/irCkqZTuNPo/</link>
		<comments>http://kovyrin.net/2010/07/18/web-designer/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 17:13:01 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[toronto]]></category>
		<category><![CDATA[web-designer]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=454</guid>
		<description><![CDATA[My wife &#8211; a good web designer with 6 years of experience with web design, HTML and CSS is looking for a job. Here is some information about her: Her web site (of course she is the one who designed it) Her portfolio Her resume Her LinkedIn profile We&#8217;re physically located in Toronto, Canada, but [...]]]></description>
			<content:encoded><![CDATA[<p>My wife &#8211; a <strong>good web designer</strong> with 6 years of experience with web design, HTML and CSS is <strong>looking for a job</strong>.  Here is some information about her:</p>
<ul>
<li><a href="http://kovyrina.info/">Her web site</a> (of course she is the one who designed it)</li>
<li><a href="http://kovyrina.info/portfolio">Her portfolio</a></li>
<li><a href="http://kovyrina.info/resume">Her resume</a></li>
<li><a href="http://ca.linkedin.com/in/kovyrina">Her LinkedIn profile</a>
</ul>
<p>We&#8217;re physically located in Toronto, Canada, but she has a great experience of working remotely too.  So, if you need a web designer or a junior web designer, feel free to <a href="http://kovyrina.info/contacts/">contact Tanya</a>.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/-Y0kA0j__RtlZMzx2ruAwNawL4k/0/da"><img src="http://feedads.g.doubleclick.net/~a/-Y0kA0j__RtlZMzx2ruAwNawL4k/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/-Y0kA0j__RtlZMzx2ruAwNawL4k/1/da"><img src="http://feedads.g.doubleclick.net/~a/-Y0kA0j__RtlZMzx2ruAwNawL4k/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=irCkqZTuNPo:7I7uKKKuk8E:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=irCkqZTuNPo:7I7uKKKuk8E:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=irCkqZTuNPo:7I7uKKKuk8E:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=irCkqZTuNPo:7I7uKKKuk8E:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=irCkqZTuNPo:7I7uKKKuk8E:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/07/18/web-designer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/07/18/web-designer/</feedburner:origLink></item>
		<item>
		<title>Fwd: Scalexis Inc is Hiring</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/bv0NYG9DY8o/</link>
		<comments>http://kovyrin.net/2010/07/05/scalexis/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 05:48:53 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[My Projects]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=488</guid>
		<description><![CDATA[Scalexis Inc, web performance/scalability consulting firm in Toronto, is looking for a full-time consultant. Being a consulting company on the high-demand market of web application scalability consulting and high-performance web applications development, we need an employee that could perform both web application development and web application performance consulting work. The main duty of the employee [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://scalexis.com">Scalexis Inc</a>, web performance/scalability consulting firm in Toronto, is looking for a full-time consultant. Being a consulting company on the high-demand market of web application scalability consulting and high-performance web applications development, we need an employee that could perform both web application development and web application performance consulting work.<br />
<span id="more-488"></span></p>
<p>The main duty of the employee would be to work directly with the customers&#8217; operations teams to detect, analyze and fix performance problems and plan application scalability in accordance with customers&#8217; needs/requests.</p>
<p>The employee would work in a small team of highly professional consultants helping the company to handle growing demand for web applications performance consulting services. </p>
<p>Position is in Toronto. Telecommuting is not possible.</p>
<p>Being a consulting-related position, it requires an extensive experience with highly-loaded web-applications scalability and, based on our customers&#8217; needs, an expert knowledge of the following technologies: </p>
<ul>
<li>Programming Languages: Ruby, PHP, C/C++, C#, Google Go </li>
<li>Databases: MySQL, Microsoft SQL Server </li>
<li>Operating Systems: MacOS X, Linux, Windows</li>
</ul>
<p>This position requires a Bachelor or Master&#8217;s degree in computer sciences. Fluent oral and written Russian language and an intermediate written English language skills are required.</p>
<p>For more details please contact hr (аt) scalexis.com.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/zInEWlw2OvOKI8PtettRXtLgXqY/0/da"><img src="http://feedads.g.doubleclick.net/~a/zInEWlw2OvOKI8PtettRXtLgXqY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/zInEWlw2OvOKI8PtettRXtLgXqY/1/da"><img src="http://feedads.g.doubleclick.net/~a/zInEWlw2OvOKI8PtettRXtLgXqY/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=bv0NYG9DY8o:Tafq-ygEGPo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=bv0NYG9DY8o:Tafq-ygEGPo:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=bv0NYG9DY8o:Tafq-ygEGPo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=bv0NYG9DY8o:Tafq-ygEGPo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=bv0NYG9DY8o:Tafq-ygEGPo:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/07/05/scalexis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/07/05/scalexis/</feedburner:origLink></item>
		<item>
		<title>Advanced Squid Caching in Scribd: Cache Invalidation Techniques</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/4ywVA01ppFY/</link>
		<comments>http://kovyrin.net/2010/05/29/squid-in-scribd-cache-invalidation/#comments</comments>
		<pubDate>Sat, 29 May 2010 17:02:17 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Admin-tips]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[Networks]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[HTCP]]></category>
		<category><![CDATA[invalidation]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[squid]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=322</guid>
		<description><![CDATA[Having a reverse-proxy web cache as one of the major infrastructure elements brings many benefits for large web applications: it reduces your application servers load, reduces average response times on your site, etc. But there is one problem every developer experiences when works with such a cache &#8211; cached content invalidation. It is a complex [...]]]></description>
			<content:encoded><![CDATA[<p>Having a <a href="http://kovyrin.net/2008/10/25/advanced-squid-caching-for-rails-applications-preface/">reverse-proxy</a> web cache as one of the major infrastructure elements brings many benefits for large web applications: it reduces your application servers load, reduces average response times on your site, etc. But there is one problem every developer experiences when works with such a cache &#8211; <em>cached content invalidation</em>.</p>
<p>It is a complex problem that usually consists of two smaller ones: i<em>ndividual cache elements invalidation</em> (you need to keep an eye on your data changes and invalidate cached pages when related data changes) and <em>full cache purges</em> (sometimes your site layout or page templates change and you need to purge all the cached pages to make sure users will get new visual elements of layout changes). In this post I&#8217;d like to look at a few techniques we use at <a href="http://www.scribd.com/">Scribd</a> to solve cache invalidation problems.</p>
<p><span id="more-322"></span></p>
<hr />So, the <strong>first problem &#8211; ongoing cache invalidation when content changes</strong>. This is actually a pretty simple task in squid: you just use <a href="http://www.htcp.org/">HTCP protocol</a> and send CLR requests to your caching farm (we didn&#8217;t find any HTCP protocol implementations so we&#8217;ve implemented <a href="http://github.com/kovyrin/htcp-ruby">our own simple client</a> that supports just one command).</p>
<p>Since we use <a href="http://haproxy.1wt.eu/">haproxy</a> to balance our traffic in the cluster it is hard to predict where should we send a purge request. So we fan those out to all cache servers.</p>
<p>To make sure cache purging won&#8217;t slow the site down, especially considering we need to do more that just a simple cache purge (submit documents to search indexes, etc, etc), we just spool a &#8220;document changed&#8221; request to a queue and then have a set of <a href="http://github.com/kovyrin/loops">asynchronous processes</a> that do all the work in background.</p>
<p>Next, <strong>The Hard Problem &#8211; handling full cache purges w/o killing our backend servers</strong> with 5x-10x traffic (our normal hit ratio is ~90-95%).</p>
<p>We&#8217;ve spent a lot of time thinking about this problem and the first idea we came up with was to have a loop process somewhere that would iterate all documents we have cached and purge them one by one&#8230; but that does not seem to be a practical solution when you have tens of millions documents (and few page versions per document) and obviously the solution would not scale with constantly growing documents corpus.</p>
<p>So we kept brainstorming and finally got one idea that works just perfectly for us: what if we&#8217;d be able to take our traffic and define a function <em>f(t)</em> that would return a percentage of the traffic that should be purged at any moment in time. So we did it &#8211; we&#8217;ve implemented a nginx module that would version our cache by assigning every cached page a revision (<a href="http://kovyrin.net/2009/07/21/advanced-squid-caching-scribd-logged-in-users-complex-urls/">using a custom HTTP-headers + Vary-caching</a>) and would be able to slowly migrate the cache from one revision to another over a pre-defined period of time.</p>
<p>Here is an overview of the requests/responses flow in our web/cache/application cluster:</p>
<p><center><img src="http://img.skitch.com/20100605-dyqee8s35ukg4cxefu3ua5jiit.png" alt="Document Page Caching" /></center></p>
<p>X-Cache-Revision value selection algorithm is the following:</p>
<p><center><img src="http://img.skitch.com/20100605-kpahhhdc92uig9qmtih4rqa6tu.png" alt="Cache Revision Selection" /></center></p>
<p>Having this kind of logic in place allows us to do so called &#8220;slow&#8221; cache purges that could take any time from a few minutes (that still helps to reduce the load spike generated by the hottest content) up to many hours (this is what we normally use) or days (never used this option, but it is definitely possible).</p>
<p>Here is an example 100% cache purge over an 8 hour interval:</p>
<ol>
<li> Daily hit ratio graph:<br />
<a href="http://img.skitch.com/20100529-pkx64g6the9winqcnk6sigiyns.png" rel="shadowbox[post-322];player=img;"><img rel="shadowbox" src="http://img.skitch.com/20100529-pkx64g6the9winqcnk6sigiyns.jpg" width="470" alt="day" /></a>
</li>
<li> Weekly hit ratio graph:<br />
<a  href="http://img.skitch.com/20100529-nk2hyafgtbw1pc1nrkgbec8st3.png" rel="shadowbox[post-322];player=img;"><img rel="shadowbox" src="http://img.skitch.com/20100529-nk2hyafgtbw1pc1nrkgbec8st3.jpg" width="470" alt="week" /></a>
</li>
</ol>
<p>As you can see, during those slow purges our cached pages would be slowly updated without putting too much pressure on the backend. Cache hit ratio would slowly degrade and then slowly get back to its normal levels, but with our normal (6-8 hours) purges hit ratio never gets lower that 65-70% which makes it possible for us to save huge amounts of money on not having 90% spare capacity just for the cache purge load surges (we used to have lots of spare application cluster capacity before introducing this approach).</p>
<p><strong>Update (June 5th, 2010):</strong> Request/response flow and cache revision selection algorithm added.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/tj3OjvA3iQ65CvNbkPSsrn5aErk/0/da"><img src="http://feedads.g.doubleclick.net/~a/tj3OjvA3iQ65CvNbkPSsrn5aErk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/tj3OjvA3iQ65CvNbkPSsrn5aErk/1/da"><img src="http://feedads.g.doubleclick.net/~a/tj3OjvA3iQ65CvNbkPSsrn5aErk/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=4ywVA01ppFY:b2ode2vaNL0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=4ywVA01ppFY:b2ode2vaNL0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=4ywVA01ppFY:b2ode2vaNL0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=4ywVA01ppFY:b2ode2vaNL0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=4ywVA01ppFY:b2ode2vaNL0:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/05/29/squid-in-scribd-cache-invalidation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/05/29/squid-in-scribd-cache-invalidation/</feedburner:origLink></item>
		<item>
		<title>DbCharmer – Rails Can Scale!</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/pRvMOlkGJ0A/</link>
		<comments>http://kovyrin.net/2010/04/16/dbcharmer-rails-can-scale/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 21:33:18 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[sharding]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=397</guid>
		<description><![CDATA[Back in November 2009 I was working on a project to port Scribd.com code base to Rails 2.2 and noticed that some old plugins we were using in 2.1 were abandoned by their authors. Some of them were just removed from the code base, but one needed a replacement &#8211; that was an old plugin [...]]]></description>
			<content:encoded><![CDATA[<p>Back in November 2009 I was working on a project to port <a href="http://www.scribd.com">Scribd.com</a> code base to Rails 2.2 and noticed that some old plugins we were using in 2.1 were abandoned by their authors. Some of them were just removed from the code base, but one needed a replacement &#8211; that was an old plugin called acts_as_readonlyable that helped us to distribute our queries among a cluster of MySQL slaves. There were some alternatives but we didn&#8217;t like them for one or another reasons so we&#8217;ve decided to go with creating our own ActiveRecord plugin, that would help us scale our databases out. That&#8217;s the story behind the <a href="http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/">first release of DbCharmer</a>.</p>
<p>Today, six months after the first release of <a href="http://rubygems.org/gems/db-charmer">the gem</a> and we&#8217;ve moved it to gemcutter (which is now the official gems hosting) and we&#8217;re already at <a href="http://rubygems.org/gems/db-charmer/versions">version 1.6.11</a>. The gem was downloaded more than 2000 times. There are (at least) 10+ large users that rely on this gem to scale their products out. And (this is the most exciting) we&#8217;ve added tons of new features to the product. </p>
<p>Here are the main features added since the first release:</p>
<ul>
<li>Much better <strong>multi-database migrations</strong> support including default migrations connection changing.</li>
<li>We&#8217;ve added <strong>ActiveRecord associations preload</strong> support that makes it possible to move eager loading queries to the same connection where your finder queries go to.</li>
<li>We&#8217;ve improved <strong>ActiveRecord&#8217;s query logging</strong> feature and now you can see what connections your queries executed on (and yes, all those improvements are colorized <img src='http://kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ).</li>
<li>We&#8217;ve added an ability to temporary<strong> remap any ActiveRecord connections</strong> to any other connections for a block of code (really useful when you need to make sure all your queries would go to some non-default slave and you do not want to mess with all your models).</li>
<li>The most interesting change: we&#8217;ve implemented some basic <strong>sharding functionality in ActiveRecord</strong> which currently is being used in production in our application.</li>
</ul>
<p>As you can see now DbCharmer helps you to do three major scalability tasks in your Rails projects:</p>
<ol>
<li><strong>Master-Slave clusters</strong> to scale out your Rails models reads.</li>
<li><strong>Vertical sharding</strong> by moving some of your models to a separate (maybe even dedicated) servers and still keep using AR associations</li>
<li><strong>Horizontal sharding</strong> by slicing your models data to pieces and placing those pieces into different databases and/or servers.</li>
</ol>
<p> So, If you didn&#8217;t check DbCharmer out yet and you&#8217;re working on some large rails project that is (or going to be) facing scalability problems, go <a href="http://github.com/kovyrin/db-charmer/blob/master/README.rdoc">read the docs</a>, download/install the <a href="http://rubygems.org/gems/db-charmer">gem</a> and prove them that <strong>Rails CAN scale</strong>!</p>

<p><a href="http://feedads.g.doubleclick.net/~a/C50kaw-zPALIf9S7psJCrd2YGWE/0/da"><img src="http://feedads.g.doubleclick.net/~a/C50kaw-zPALIf9S7psJCrd2YGWE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/C50kaw-zPALIf9S7psJCrd2YGWE/1/da"><img src="http://feedads.g.doubleclick.net/~a/C50kaw-zPALIf9S7psJCrd2YGWE/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=pRvMOlkGJ0A:KhLs4uvpOsE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=pRvMOlkGJ0A:KhLs4uvpOsE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=pRvMOlkGJ0A:KhLs4uvpOsE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=pRvMOlkGJ0A:KhLs4uvpOsE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=pRvMOlkGJ0A:KhLs4uvpOsE:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/04/16/dbcharmer-rails-can-scale/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/04/16/dbcharmer-rails-can-scale/</feedburner:origLink></item>
		<item>
		<title>Installing Midnight Commander 4.7 on Mac OS X</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/n_CrAVJAsNM/</link>
		<comments>http://kovyrin.net/2010/02/02/install-mc-4-7-on-osx/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 22:34:00 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Admin-tips]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[macos]]></category>
		<category><![CDATA[mc]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=390</guid>
		<description><![CDATA[Another short post just to remember the procedure for the next time I&#8217;ll be setting up a new mac. For those of my readers who do not know what Midnight Commander (aka mc) is, GNU Midnight Commander is a visual file manager, created under a heavy influence of Norton Commander file manager from dark DOS [...]]]></description>
			<content:encoded><![CDATA[<p>Another short post just to remember the procedure for the next time I&#8217;ll be setting up a new mac. For those of my readers who do not know what Midnight Commander (aka mc) is, <a href="http://www.midnight-commander.org">GNU Midnight Commander</a> is a visual file manager, created under a heavy influence of Norton Commander file manager from dark DOS ages <img src='http://kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  For more information, you can visit <a href="http://www.midnight-commander.org">their web site</a>. Now, get to the installation topic itself.</p>
<p>To install mc on a Mac OS X machine, you need <a href="http://www.macports.org/">macports</a> installed and then first thing you&#8217;ll need to do is to install some prerequisite libraries:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo port install libiconv slang2</div></td></tr></tbody></table></div>
<p>Next thing, download the sources <a href=" http://www.midnight-commander.org/downloads">from their web site</a> and unpack them. When the sources are ready, you can configure the build:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./configure \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --prefix=/opt/mc \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --with-screen=slang \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --enable-extcharset \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --enable-charset \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --with-libiconv-prefix=/opt/local \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --with-slang-includes=/opt/local/include \<br />
&nbsp; &nbsp; &nbsp; &nbsp; --with-slang-libs=/opt/local/lib</div></td></tr></tbody></table></div>
<p>Then, normal GNU-style build and install procedure:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ make <br />
........<br />
$ sudo make install</div></td></tr></tbody></table></div>
<p>And the last thing would be to add <code class="codecolorer text dawn"><span class="text">/opt/mc/bin</span></code> to your PATH environment variable.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/XrjjWX8YwK8oNMTkwJo---s_rYI/0/da"><img src="http://feedads.g.doubleclick.net/~a/XrjjWX8YwK8oNMTkwJo---s_rYI/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/XrjjWX8YwK8oNMTkwJo---s_rYI/1/da"><img src="http://feedads.g.doubleclick.net/~a/XrjjWX8YwK8oNMTkwJo---s_rYI/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=n_CrAVJAsNM:wPhsQocSzm8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=n_CrAVJAsNM:wPhsQocSzm8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=n_CrAVJAsNM:wPhsQocSzm8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=n_CrAVJAsNM:wPhsQocSzm8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=n_CrAVJAsNM:wPhsQocSzm8:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/02/02/install-mc-4-7-on-osx/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/02/02/install-mc-4-7-on-osx/</feedburner:origLink></item>
		<item>
		<title>Enabling IPv6 Support in nginx</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/TpJuKctpPjk/</link>
		<comments>http://kovyrin.net/2010/01/16/enabling-ipv6-support-in-nginx/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 09:39:44 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Admin-tips]]></category>
		<category><![CDATA[Networks]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[ipv6]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=362</guid>
		<description><![CDATA[This is going to be a really short post, but for someone it could save an hour of life. So, you&#8217;ve nothing to do and you&#8217;ve decided to play around with IPv6 or maybe you&#8217;re happened to be an administrator of a web service that needs to support IPv6 connectivity and you need to make [...]]]></description>
			<content:encoded><![CDATA[<p>This is going to be a really short post, but for someone it could save an hour of life.</p>
<p>So, you&#8217;ve nothing to do and you&#8217;ve decided to play around with <a href="http://en.wikipedia.org/wiki/IPv6">IPv6</a> or maybe you&#8217;re happened to be an administrator of a web service that needs to support IPv6 connectivity and you need to make your <a href="http://nginx.org/">nginx</a> server work nicely with this protocol. </p>
<p>First thing you need to do is to enable IPv6 in nginx by recompiling it with <code class="codecolorer text dawn"><span class="text">--with-ipv6</span></code> configure option and reinstalling it. If you use some pre-built package, check if your nginx already has this key enabled by running <code class="codecolorer text dawn"><span class="text">nginx -V</span></code>. </p>
<p><span id="more-362"></span></p>
<p>The results should have <code class="codecolorer text dawn"><span class="text">--with-ipv6</span></code> option in configure arguments:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[root@node ~]# nginx -V<br />
nginx version: nginx/0.7.64<br />
built by gcc 4.1.2 20080704 (Red Hat 4.1.2-46)<br />
TLS SNI support disabled<br />
configure arguments: --with-ipv6 ... --prefix=/opt/nginx</div></td></tr></tbody></table></div>
<p>After you&#8217;ve got your nginx binary with IPv6 support, you need to enable it by changing <code class="codecolorer text dawn"><span class="text">listen</span></code> directives in your configuration file. </p>
<p>If your server binds to all interfaces/IPs, you already have <code class="codecolorer text dawn"><span class="text">listen 80</span></code> or something like that in your file. Those lines should be changed to make sure you tell your nginx to bind on both IPv4 and IPv6 addresses:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">listen [::]:80;</div></td></tr></tbody></table></div>
<p>For situations when you do not want to listen on IPv4 interfaces, there is <code class="codecolorer text dawn"><span class="text">ipv6only=on</span></code> parameter:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">listen [::]:443 default ipv6only=on;</div></td></tr></tbody></table></div>
<p>For configurations that need to bind to specific ip addresses you could use similar notation:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">listen [2607:f0d0:1004:2::2]:80;</div></td></tr></tbody></table></div>
<p>After changing your configs and testing them you need to restart (not reload) your nginx process and then check your system port bindings to make sure it works as expected:</p>
<div class="codecolorer-container text twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[root@node ~]# netstat -nlp | grep nginx<br />
tcp &nbsp; 0 &nbsp; &nbsp;0 :::80 &nbsp; &nbsp; &nbsp; &nbsp;:::* &nbsp; &nbsp; &nbsp; &nbsp; LISTEN &nbsp; &nbsp;23817/nginx<br />
tcp &nbsp; 0 &nbsp; &nbsp;0 :::443 &nbsp; &nbsp; &nbsp; :::* &nbsp; &nbsp; &nbsp; &nbsp; LISTEN &nbsp; &nbsp;23817/nginx</div></td></tr></tbody></table></div>
<p>This is it, now you can add <a href="http://en.wikipedia.org/wiki/IPv6_Addresses#IPv6_addresses_in_the_Domain_Name_System">AAAA</a> records to your main domain name or just create a dedicated <a href="http://ipv6.scribd.com">ipv6</a>.<a href="http://ipv6.google.com">yourcompany</a>.<a href="http://ipv6.netflix.com">com</a> sub-domain and show it to your friends <img src='http://kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/gys7FFomJnrqeeBmRPpOqPsFIyM/0/da"><img src="http://feedads.g.doubleclick.net/~a/gys7FFomJnrqeeBmRPpOqPsFIyM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/gys7FFomJnrqeeBmRPpOqPsFIyM/1/da"><img src="http://feedads.g.doubleclick.net/~a/gys7FFomJnrqeeBmRPpOqPsFIyM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=TpJuKctpPjk:Yc3Q-fyY3Vw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=TpJuKctpPjk:Yc3Q-fyY3Vw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=TpJuKctpPjk:Yc3Q-fyY3Vw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=TpJuKctpPjk:Yc3Q-fyY3Vw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=TpJuKctpPjk:Yc3Q-fyY3Vw:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2010/01/16/enabling-ipv6-support-in-nginx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2010/01/16/enabling-ipv6-support-in-nginx/</feedburner:origLink></item>
		<item>
		<title>DB Charmer – ActiveRecord Connection Magic Plugin</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/_bkc3hWZQr0/</link>
		<comments>http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 15:36:26 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[scribd]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=324</guid>
		<description><![CDATA[Today I&#8217;m proud to announce the first public release of our ActiveRecord database connection magic plugin: DbCharmer. DB Charmer &#8211; ActiveRecord Connection Magic Plugin DbCharmer is a simple yet powerful plugin for ActiveRecord that does a few things: Allows you to easily manage AR models&#8217; connections (switch_connection_to method) Allows you to switch AR models&#8217; default [...]]]></description>
			<content:encoded><![CDATA[<p>Today I&#8217;m proud to announce the first public release of <a href="http://www.scribd.com">our</a> ActiveRecord database connection magic plugin: <a href="http://github.com/kovyrin/db-charmer">DbCharmer</a>. </p>
<hr/>
<h2>DB Charmer &#8211; ActiveRecord Connection Magic Plugin</h2>
<p><tt>DbCharmer</tt> is a simple yet powerful plugin for ActiveRecord that does a few things:</p>
<ol>
<li>Allows you to easily manage AR models&#8217; connections (<code class="codecolorer ruby dawn"><span class="ruby">switch_connection_to</span></code> method)
<li>Allows you to switch AR models&#8217; default connections to a separate servers/databases
<li>Allows you to easily choose where your query should go (<code class="codecolorer ruby dawn"><span class="ruby">on_<span style="color:#006600; font-weight:bold;">*</span></span></code> methods family)
<li>Allows you to automatically send read queries to your slaves while masters would handle all the updates.
<li>Adds multiple databases migrations to ActiveRecord
</ol>
<p><span id="more-324"></span></p>
<h2>Installation</h2>
<p>There are two options when approaching db-charmer installation:</p>
<ul>
<li>using the <a href="http://gemcutter.org/gems/db-charmer">gem</a> (recommended)
<li>install as a Rails plugin
</ul>
<p>To install as a <a href="http://gemcutter.org/gems/db-charmer">gem</a>, add this to your environment.rb:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">'db-charmer'</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'db_charmer'</span>, <br />
&nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://gemcutter.org'</span></div></td></tr></tbody></table></div>
<p>And then run the command:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">sudo</span> rake gems:<span style="color: #c20cb9; font-weight: bold;">install</span></div></td></tr></tbody></table></div>
<p>To install db-charmer as a Rails plugin use this:</p>
<div class="codecolorer-container bash twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">script<span style="color: #000000; font-weight: bold;">/</span>plugin <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>kovyrin<span style="color: #000000; font-weight: bold;">/</span>db-charmer.git</div></td></tr></tbody></table></div>
<h2>Easy ActiveRecord Connection Management</h2>
<p>As a part of this plugin we&#8217;ve added <code class="codecolorer ruby dawn"><span class="ruby">switch_connection_to</span></code> method that accepts many different kinds of db connections specifications and uses them on a model. We support:</p>
<ol>
<li>Strings and symbols as the names of connection configuration blocks in database.yml.
<li>ActiveRecord models (we&#8217;d use connection currently set up on a model).
<li>Database connections (<code class="codecolorer ruby dawn"><span class="ruby">Model.<span style="color:#9900CC;">connection</span></span></code>)
<li>Nil values to reset model to default connection.
</ol>
<p>Sample code:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Foo <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Model</span>; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
Foo.<span style="color:#9900CC;">switch_connection_to</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:blah</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
Foo.<span style="color:#9900CC;">switch_connection_to</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'foo'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
Foo.<span style="color:#9900CC;">switch_connection_to</span><span style="color:#006600; font-weight:bold;">&#40;</span>Bar<span style="color:#006600; font-weight:bold;">&#41;</span><br />
Foo.<span style="color:#9900CC;">switch_connection_to</span><span style="color:#006600; font-weight:bold;">&#40;</span>Baz.<span style="color:#9900CC;">connection</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
Foo.<span style="color:#9900CC;">switch_connection_to</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>The <code class="codecolorer ruby dawn"><span class="ruby">switch_connection_to</span></code> method has an optional second parameter <code class="codecolorer ruby dawn"><span class="ruby">should_exist</span></code> which is true by default. This parameter is used when the method is called with a string or a symbol connection name and there is no such connection configuration in the database.yml file. If this parameter is <code class="codecolorer ruby dawn"><span class="ruby"><span style="color:#0000FF; font-weight:bold;">true</span></span></code>, an exception would be raised, otherwise, the error would be ignored and no connection change would happen.</p>
<p>This is really useful when in development mode or in a tests you do not want to create many different databases on your local machine and just want to put all your tables in a single database.</p>
<p><b>Warning:</b> All the connection switching calls would switch connection <b>only</b> for those classes the method called on. You can&#8217;t call the <code class="codecolorer ruby dawn"><span class="ruby">switch_connection_to</span></code> method and switch connection for a base class in some hierarchy (for example, you can&#8217;t switch AR::Base connection and see all your models switched to the new connection, use the classic <code class="codecolorer ruby dawn"><span class="ruby">establish_connection</span></code> instead).</p>
<h2>Multiple DB Migrations</h2>
<p>In every application that works with many databases, there is need in a convenient schema migrations mechanism.</p>
<p>All Rails users already have this mechanism &#8211; rails migrations. So in <tt>DbCharmer</tt>, we&#8217;ve made it possible to seamlessly use multiple databases in Rails migrations.</p>
<p>There are two methods available in migrations to operate on more than one database:</p>
<p>1. Global connection change method &#8211; used to switch whole migration to a non-default database.<br />
2. Block-level connection change method &#8211; could be used to do only a part of a migration on a non-default db.</p>
<p>Migration class example (global connection rewrite):</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> MultiDbTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span><br />
&nbsp; &nbsp;db_magic <span style="color:#ff3333; font-weight:bold;">:connection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:second_db</span><br />
<br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span><br />
&nbsp; &nbsp; &nbsp;create_table <span style="color:#ff3333; font-weight:bold;">:test_table</span>, <span style="color:#ff3333; font-weight:bold;">:force</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:test_string</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;t.<span style="color:#9900CC;">timestamps</span><br />
&nbsp; &nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span><br />
&nbsp; &nbsp; &nbsp;drop_table <span style="color:#ff3333; font-weight:bold;">:test_table</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp;<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Migration class example (block-level connection rewrite):</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> MultiDbTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span><br />
&nbsp; &nbsp; on_db <span style="color:#ff3333; font-weight:bold;">:second_db</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; create_table <span style="color:#ff3333; font-weight:bold;">:test_table</span>, <span style="color:#ff3333; font-weight:bold;">:force</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; t.<span style="color:#CC0066; font-weight:bold;">string</span> <span style="color:#ff3333; font-weight:bold;">:test_string</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; t.<span style="color:#9900CC;">timestamps</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span><br />
&nbsp; &nbsp; on_db <span style="color:#ff3333; font-weight:bold;">:second_db</span> <span style="color:#006600; font-weight:bold;">&#123;</span> drop_table <span style="color:#ff3333; font-weight:bold;">:test_table</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>By default in development and test environments you could skip this <code class="codecolorer ruby dawn"><span class="ruby"><span style="color:#ff3333; font-weight:bold;">:second_db</span></span></code> connection from your database.yml files and rails would create the tables in your single database, but in production you&#8217;d specify it and get the table created on a separate server and/or in a separate database.</p>
<p>This behaviour is controlled by the <code class="codecolorer ruby dawn"><span class="ruby">DbCharmer.<span style="color:#9900CC;">migration_connections_should_exist</span></span></code> configuration attribute which could be set from a rails initializer.</p>
<h2>Using Models in Master-Slave Environments</h2>
<p>Master-slave replication is the most popular scale-out technique in a medium-sized and large database-centric applications today. There are some rails plugins out there that help developers to use slave servers in their models but none of them were flexible enough for us to start using them in a huge application we work on.</p>
<p>So, we&#8217;ve been using ActsAsReadonlyable plugin for a long time and have made tons of changes in its code over the time. But since that plugin has been abandoned by its authors, we&#8217;ve decided to collect all of our master-slave code in one plugin and release it for rails 2.2+. <tt>DbCharmer</tt> adds the following features to Rails models:</p>
<h3>Auto-Switching all Reads to the Slave(s)</h3>
<p>When you create a model, you could use <code class="codecolorer ruby dawn"><span class="ruby">db_magic <span style="color:#ff3333; font-weight:bold;">:slave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:blah</span></span></code> or <code class="codecolorer ruby dawn"><span class="ruby">db_magic <span style="color:#ff3333; font-weight:bold;">:slaves</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:foo</span>, <span style="color:#ff3333; font-weight:bold;">:bar</span> <span style="color:#006600; font-weight:bold;">&#93;</span></span></code> commands in your model to set up reads redirection mode when all your find/count/exist/etc methods will be reading data from your slave (or a bunch of slaves in a round-robin manner). Here is an example:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Foo <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; db_magic <span style="color:#ff3333; font-weight:bold;">:slave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:slave01</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Bar <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; db_magic <span style="color:#ff3333; font-weight:bold;">:slaves</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:slave01</span>, <span style="color:#ff3333; font-weight:bold;">:slave02</span> <span style="color:#006600; font-weight:bold;">&#93;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<h3>Default Connection Switching</h3>
<p>If you have more than one master-slave cluster (or simply more than one database) in your database environment, then you might want to change the default database connection of some of your models. You could do that by using <code class="codecolorer ruby dawn"><span class="ruby">db_magic <span style="color:#ff3333; font-weight:bold;">:connection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:foo</span></span></code> call from your models. Example:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Foo <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; db_magic <span style="color:#ff3333; font-weight:bold;">:connection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:foo</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Sample model on a separate master-slave cluster (so, separate main connection + a slave connection):</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Bar <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; db_magic <span style="color:#ff3333; font-weight:bold;">:connection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:bar</span>, <span style="color:#ff3333; font-weight:bold;">:slave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:bar_slave</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<h3>Per-Query Connection Management</h3>
<p>Sometimes you have select queries that you know you want to run on the master. This could happen for example when you have just added some data and need to read it back and not sure if it made it all the way to the slave yet or no. For this situation and a few others there is a set of methods we&#8217;ve added to ActiveRecord models:</p>
<p>1) +on_master+ &#8211; this method could be used in two forms: block form and proxy form. In the block form you could force connection switch for a block of code:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">User.<span style="color:#9900CC;">on_master</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; user = User.<span style="color:#9900CC;">find_by_login</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'foo'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; user.<span style="color:#9900CC;">update_attributes</span>!<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:activated</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>In the proxy form this method could be used to force one query to be performed on the master database server:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Comment.<span style="color:#9900CC;">on_master</span>.<span style="color:#9900CC;">last</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
User.<span style="color:#9900CC;">on_master</span>.<span style="color:#9900CC;">find_by_activation_code</span><span style="color:#006600; font-weight:bold;">&#40;</span>code<span style="color:#006600; font-weight:bold;">&#41;</span><br />
User.<span style="color:#9900CC;">on_master</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:login</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> login, <span style="color:#ff3333; font-weight:bold;">:password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> password<span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>2) <code class="codecolorer ruby dawn"><span class="ruby">on_slave</span></code> &#8211; this method is used to force a query to be run on a slave even in situations when it&#8217;s been previously forced to use the master. If there is more than one slave, one would be selected randomly. This method has two forms as well: block and proxy.</p>
<p>3) <code class="codecolorer ruby dawn"><span class="ruby">on_db<span style="color:#006600; font-weight:bold;">&#40;</span>connection<span style="color:#006600; font-weight:bold;">&#41;</span></span></code> &#8211; this method is what makes two previous methods possible. It is used to switch a model&#8217;s connection to some db for a short block of code or even for one statement (two forms). It accepts the same range of values as the <code class="codecolorer ruby dawn"><span class="ruby">switch_connection_to</span></code> method does. Example:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Comment.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:olap</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">count</span><br />
Post.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<h3>Associations Connection Management</h3>
<p>ActiveRecord models can have an associations with each other and since every model has its own database connections, it becomes pretty hard to manage connections in a chained calls like <code class="codecolorer ruby dawn"><span class="ruby">User.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">count</span></span></code>. With a class-only connection switching methods this call would look like the following if we&#8217;d want to count posts on a separate database:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Post.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:olap</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> User.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">count</span> <span style="color:#006600; font-weight:bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>Apparently this is not the best way to write the code and we&#8217;ve implemented an <code class="codecolorer ruby dawn"><span class="ruby">on_<span style="color:#006600; font-weight:bold;">*</span></span></code> methods on associations as well so you could do things like this:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:olap</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">count</span><br />
<span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">on_slave</span>.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Hello, world!'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>Notice: Since ActiveRecord associations implemented as proxies for resulting objects/collections, it is possible to use our connection switching methods even without chained methods:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@post</span>.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">on_slave</span> <span style="color:#008000; font-style:italic;"># would return post's author</span><br />
<span style="color:#0066ff; font-weight:bold;">@photo</span>.<span style="color:#9900CC;">owner</span>.<span style="color:#9900CC;">on_slave</span> <span style="color:#008000; font-style:italic;"># would return photo's owner</span></div></td></tr></tbody></table></div>
<p>Starting with <tt>DbCharmer</tt> release 1.4 it is possible to use prefix notation for has_many and HABTM associations connection switching:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">posts</span><br />
<span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">on_slave</span>.<span style="color:#9900CC;">posts</span></div></td></tr></tbody></table></div>
<h3>Named Scopes Support</h3>
<p>To make it easier for <tt>DbCharmer</tt> users to use connections switching methods with named scopes, we&#8217;ve added <code class="codecolorer ruby dawn"><span class="ruby">on_<span style="color:#006600; font-weight:bold;">*</span></span></code> methods support on the scopes as well. All the following scope chains would do exactly the same way (the query would be executed on the <code class="codecolorer ruby dawn"><span class="ruby"><span style="color:#ff3333; font-weight:bold;">:foo</span></span></code> database connection):</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Post.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">with_comments</span>.<span style="color:#9900CC;">spam_marked</span>.<span style="color:#9900CC;">count</span><br />
Post.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with_comments</span>.<span style="color:#9900CC;">spam_marked</span>.<span style="color:#9900CC;">count</span><br />
Post.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">with_comments</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">spam_marked</span>.<span style="color:#9900CC;">count</span><br />
Post.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">with_comments</span>.<span style="color:#9900CC;">spam_marked</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">count</span></div></td></tr></tbody></table></div>
<p>And now, add this feature to our associations support and here is what we could do:</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:archive</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">all</span><br />
<span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:olap</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">count</span><br />
<span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">posts</span>.<span style="color:#9900CC;">published</span>.<span style="color:#9900CC;">on_db</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:foo</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span></div></td></tr></tbody></table></div>
<h2>Documentation</h2>
<p>For more information on the plugin internals, please check out the source code. All the plugin&#8217;s code is ~100% covered with a tests that were placed in a separate staging rails project located at <a href="http://github.com/kovyrin/db-charmer-sandbox">github</a>. The project has unit tests for all or at least the most of the parts of plugin&#8217;s code.</p>
<h2>What Ruby and Rails implementations does it work for?</h2>
<p>We have a continuous integration setups for this plugin on MRI 1.8.6 with Rails 2.2 and 2.3. We use the plugin in production on <a href="http://www.scribd.com">Scribd.com</a> with MRI (rubyee) 1.8.6 and Rails 2.2.</p>
<h2>Who are the authors?</h2>
<p>This plugin has been created in Scribd.com for our internal use and then the sources were opened for other people to use. All the code in this package has been developed by <a href="http://kovyrin.net">Alexey Kovyrin</a> for Scribd.com and is released under the MIT license. For more details, see the LICENSE file.</p>
<hr/>
<p>If you have any comments on this project, feel free to contact me here in comments or by email. And, of course, patches are welcome (only when covered with tests).</p>

<p><a href="http://feedads.g.doubleclick.net/~a/hx_zWaMXIT4I2NZGzRG5hINlpBY/0/da"><img src="http://feedads.g.doubleclick.net/~a/hx_zWaMXIT4I2NZGzRG5hINlpBY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/hx_zWaMXIT4I2NZGzRG5hINlpBY/1/da"><img src="http://feedads.g.doubleclick.net/~a/hx_zWaMXIT4I2NZGzRG5hINlpBY/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=_bkc3hWZQr0:tDjUt-_xpVg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=_bkc3hWZQr0:tDjUt-_xpVg:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=_bkc3hWZQr0:tDjUt-_xpVg:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=_bkc3hWZQr0:tDjUt-_xpVg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=_bkc3hWZQr0:tDjUt-_xpVg:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2009/11/03/db-charmer-activerecord-connection-magic-plugin/</feedburner:origLink></item>
		<item>
		<title>Advanced Squid Caching in Scribd: Hardware + Software Used</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/s8GVmmmES8s/</link>
		<comments>http://kovyrin.net/2009/08/04/advanced-squid-caching-in-scribd-hardware-software-used/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 05:23:18 +0000</pubDate>
		<dc:creator>Alexey Kovyrin</dc:creator>
				<category><![CDATA[Admin-tips]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Networks]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[scribd]]></category>
		<category><![CDATA[squid]]></category>

		<guid isPermaLink="false">http://kovyrin.net/?p=298</guid>
		<description><![CDATA[After the previous post in this caching related series I&#8217;ve received many questions on hardware and software configuration of our servers so in this post I&#8217;ll describe our server&#8217;s configs and the motivation behind those configs. Hardware Configuration Since in our setup Squid server uses one-process model (with an asynchronous requests processing) there was no [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://kovyrin.net/2009/07/21/advanced-squid-caching-scribd-logged-in-users-complex-urls/">the previous post in this caching related series</a> I&#8217;ve received many questions on hardware and software configuration of our servers so in this post I&#8217;ll describe our server&#8217;s configs and the motivation behind those configs.</p>
<p><span id="more-298"></span></p>
<h3>Hardware Configuration</h3>
<p>Since in our setup Squid server uses one-process model (with an asynchronous requests processing) there was no point in ordering multi-core CPUs for our boxes and since we have a lots of pages on the site and the cache is pretty huge all the servers ended up being highly I/O bound. Considering these facts we&#8217;ve decided to use the following hardware specs for the servers:</p>
<p><b>CPU:</b> One pretty cheap dual-core Intel Xeon 5148 (no need in multiple cores or really high frequencies &#8211; even these CPUs have ~1% avg load)<br />
<b>RAM:</b> 8Gb (basically to reduce I/O pressure by caching hot content in RAM)<br />
<b>Disks: </b> 4 x small SAS 15k drives in JBOD mode (no RAIDS &#8211; we&#8217;ve tried all kinds of RAID configs and it did not help with the I/O performance)</p>
<p>So, once again: <i>nothing is as important in a squid box as I/O throughput</i>. </p>
<p>Here is a sample CPU load graph from one of the boxes:</p>
<p><a href="http://kovyrin.net/wp-content/uploads/2009/08/squid-cpu-graph.png" rel="shadowbox[post-298];player=img;"><img src="http://kovyrin.net/wp-content/uploads/2009/08/squid-cpu-graph-300x139.png" alt="squid-cpu-graph" title="squid-cpu-graph" width="300" height="139" class="aligncenter size-medium wp-image-305" /></a></p>
<h3>Software Configuration</h3>
<p>This could be a long story, but in a few words our experience with different squid versions was the following.</p>
<p>First, when I&#8217;ve started working on this caching project I&#8217;ve just installed squid using Debian&#8217;s apt-get install squid command. As the result we&#8217;ve got some ancient squid 2.6 release that for some reason (still unclear to me) was painfully slow in I/O operations and it had some leaking file descriptors problem so after a few hours under production load the box would simply stop processing requests.</p>
<p>When the first approach failed, I&#8217;ve decided to go to the <a href="http://www.squid-cache.org/">squid web site</a>, download the latest production release and install it from sources (yes, we do it all the time when OS vendor ships too old or buggy releases). Result &#8211; freaking fast and stable squid 3.0 which worked flawlessly for about 5 months. </p>
<p>Few months ago we&#8217;ve found out about the <a href="http://www.mnot.net/blog/2007/12/12/stale">stale-* extensions</a> available in squid 2.7 and I&#8217;ve started wondering if we should change our perfectly stable 3.0 setup to 2.7. And some time later I&#8217;ve decided to use Vary HTTP header in our caching architecture and then I found out that vary-caching correctly implemented only in 2.7 and since 3.0 is a complete rewrite of the 2.X branch, vary-caching is not yet implemented there (or not in a way we&#8217;d want it to be implemented).</p>
<p>So, the  final result: at this moment in time we&#8217;re using custom-built Squid 2.7STABLE6 and really happy with it, it is stable, fast and feature-rich caching proxy server.</p>
<h3>Caching Cluster Configuration</h3>
<p>Apparently we have more than one squid server in scribd and this makes it a bit harder to use those servers (comparing to one box when you&#8217;d send all requests to one IP:port pair). We&#8217;ve tried to use round-robin balancing for the squid boxes + ICP-based neighbor checks but it was adding more latency to our responses and we&#8217;ve decided to put haproxy load balancer between nginx and squid farm and set up URL hash based balancing to distribute requests evenly amongst squid backends. </p>
<p>This scheme worked pretty nice, but we had one serious problem with this setup: if one squid box would go down, haproxy would quickly detect the problem and would remove it from the pool&#8230; And here comes the problem &#8211; removing a server from the pool completely changes hashing keys space and all cached requests become invalid. To solve this problem we&#8217;ve developed a nginx balancer module that performs consistent hashing of URLs and we&#8217;re testing this module now in production. What is really good about this module is that it removes one hop from the chain if http proxies between the site and a user.</p>
<p>So, this was a short description of what hardware we use for our caching cluster and why do we use it. In the next posts of this series we&#8217;ll talk about cache control and objects invalidation.</p>
<p><b>UPDATE:</b> squid-3.0 was not a rewrite of Squid-2. It’s a continuation of Squid-2.5, with a conversion to compile under C++.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/dXdI1T1MhxC9l48j08Zg97Go0gM/0/da"><img src="http://feedads.g.doubleclick.net/~a/dXdI1T1MhxC9l48j08Zg97Go0gM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/dXdI1T1MhxC9l48j08Zg97Go0gM/1/da"><img src="http://feedads.g.doubleclick.net/~a/dXdI1T1MhxC9l48j08Zg97Go0gM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=s8GVmmmES8s:rOiXzkyoXvI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=s8GVmmmES8s:rOiXzkyoXvI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=s8GVmmmES8s:rOiXzkyoXvI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Homo-Adminus?a=s8GVmmmES8s:rOiXzkyoXvI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Homo-Adminus?i=s8GVmmmES8s:rOiXzkyoXvI:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://kovyrin.net/2009/08/04/advanced-squid-caching-in-scribd-hardware-software-used/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://kovyrin.net/2009/08/04/advanced-squid-caching-in-scribd-hardware-software-used/</feedburner:origLink></item>
	</channel>
</rss>
