<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Homo-Adminus Blog</title>
	
	<link>http://blog.kovyrin.net</link>
	<description>Yet Another Admin's blog</description>
	<pubDate>Tue, 17 Feb 2009 03:41:30 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Homo-Adminus" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Loops plugin for rails and merb released</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/Zz6DANB1Yko/</link>
		<comments>http://blog.kovyrin.net/2009/02/17/loops-plugin-for-rails-and-merb-released/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 03:41:30 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Links]]></category>

		<category><![CDATA[My Projects]]></category>

		<category><![CDATA[github]]></category>

		<category><![CDATA[plugin]]></category>

		<category><![CDATA[project]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Ruby On Rails]]></category>

		<category><![CDATA[scribd]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=186</guid>
		<description><![CDATA[loops is a small and lightweight framework for Ruby on Rails and Merb created to support simple background loops in your application which are usually used to do some background data processing on your servers (queue workers, batch tasks processors, etc). 
Originally loops plugin was created to make our (Scribd.com) own loops code more organized. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/kovyrin/loops/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">loops</a> is a small and lightweight framework for Ruby on Rails and Merb created to support simple background loops in your application which are usually used to do some background data processing on your servers (queue workers, batch tasks processors, etc). </p>
<p>Originally <a href="http://github.com/kovyrin/loops/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">loops plugin</a> was created to make our (<a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">Scribd.com</a>) own loops code more organized. We used to have tens of different modules with methods that were called with script/runner and then used with nohup and other not so convenient backgrounding techniques. When you have such a number of loops/workers to run in background it becomes a nightmare to manage them on a regular basis (restarts, code upgrades, status/health checking, etc).</p>
<p>After a short time of writing our loops in more organized ways we were able to generalize most of the loops code so now our loops look like a classes with a single mandatory public method called run. Everything else (spawning many workers, managing them, logging, backgrounding, pid-files management, etc) is handled by the plugin itself. </p>
<p>The major idea behind this small project was to create a deadly simple and yet robust framework to be able to run some tasks in background and do not think about spawning many workers, restarting them when they die, etc. So, if you need to be able to run either one or many copies of your worker or you do not want to think about re-spawning dead workers and do not want to spend megabytes of RAM on separate copies of Ruby interpreter (when you run each copy of your loop as a separate process controlled by monit/god/etc), then I’d recommend you to try this framework — you&#8217;ll like it. </p>
<p>For more information, visit the <a href="http://github.com/kovyrin/loops/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">project site</a> and, of course, read the sources <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/HGpSukdLZGJVqnBEbr8aBNfXcZM/0/da"><img src="http://feedads.g.doubleclick.net/~a/HGpSukdLZGJVqnBEbr8aBNfXcZM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/HGpSukdLZGJVqnBEbr8aBNfXcZM/1/da"><img src="http://feedads.g.doubleclick.net/~a/HGpSukdLZGJVqnBEbr8aBNfXcZM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=Pdlxmq2b"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=Pdlxmq2b" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=2rvGM76G"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=S2WoogFl"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=S2WoogFl" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2009/02/17/loops-plugin-for-rails-and-merb-released/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2009/02/17/loops-plugin-for-rails-and-merb-released/</feedburner:origLink></item>
		<item>
		<title>Rails Developer for a Large Startup: My Vision of an Ideal Candidate</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/WgPb8iZXnVo/</link>
		<comments>http://blog.kovyrin.net/2009/02/07/rails-developer-for-a-large-startup-my-vision-of-an-ideal-candidate/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 07:41:22 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[Links]]></category>

		<category><![CDATA[developer]]></category>

		<category><![CDATA[hiring]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[scribd]]></category>

		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=176</guid>
		<description><![CDATA[Few days ago we were chatting in our corporate Campfire room and one of the guys asked me what do I think about Rails developers hiring process, what questions I&#8217;d ask a candidate, etc&#8230; This question started really long and interesting discussion and I&#8217;d like to share my thoughts on this question in this post.

So, [...]]]></description>
			<content:encoded><![CDATA[<p>Few days ago we were chatting in <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">our</a> corporate Campfire room and one of the guys asked me what do I think about Rails developers hiring process, what questions I&#8217;d ask a candidate, etc&#8230; This question started really long and interesting discussion and I&#8217;d like to share my thoughts on this question in this post.</p>
<p><span id="more-176"></span></p>
<p>So, first of all I would like to explain what kind of interviews I really hate <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> Ever since I was thinking of myself as of a developer (many years ago) and was going to &#8220;software developer position&#8221; interviews I really hated questions like &#8220;What is the name and possible values of the third parameter of the function some_freakin_weird_func() from some_weird.h&#8221; or &#8220;How to declare a virtual destructor and when it could be useful?&#8221;&#8230; All my life I had pretty practical thinking and never bothered to learn APIs or some really deep language concepts that are useful in 1% of the development time in really weird edge case situations. I always thought that a Real Engineer should know where to find an answer and should be able to find a way to implement something without knowing all possible ways to do it - engineering mind should be flexible! </p>
<p>So, if I&#8217;d interview a developer for our company, I&#8217;d never ask them this weird kind of theoretical questions because honestly speaking web development is not a rocket science and in most of the cases you don&#8217;t need to have a CS Master degree to be a good developer.</p>
<p>So, let&#8217;s get closer to our discussion in <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">Scribd</a>. During this discussion we were talking about our standard hiring practices, about questions we used to ask our candidates and such. As the result I decided to write a set of questions I&#8217;d really like an ideal candidate to be able to answer. Many of them are not rails specific, but rather high-load and high-scale specific. Let me share some of those questions here.</p>
<ol>
<li>
You have a generic web application (does not matter if it is rails or not) with a set of layers and parties involved in each request:</p>
<ul>
<li>Database</li>
<li>Application</li>
<li>Internet</li>
<li>User</li>
</ul>
<p>What security problems could occur on each level and what action should developer take to prevent those problems from happening? For example take a login action in your application and explain possible problems.
</li>
<li>
You have a table with 100 millions of records, you need to make some changes in each records and it is obvious that you won&#8217;t be able to do that using some SQL queries, so you need to do in some application-level code (one time use script). Your database is MySQL.</p>
<ul>
<li>Where would you put the code in the application: model, module with a bunch of methods, migration, some dedicated script?</li>
<li>How would you process all those records: Model.find(:all).each {}, a loop with different offsets and a limit, a loop walking through primary key values with some step, something else?</li>
<li>What would you choose for this task and why: Model.find or Model.find_by_sql? What is the major difference between those two? When would you definitely use find_by_sql?</li>
<li>What would you use: update_attribute, attribute assignments + saves, Model.connection.execute or something else to update the table? When and why would you use each of those? </li>
</ul>
</li>
<li>
You have a rails action that accepts uploads and then transfers them to a pretty slow storage (S3, some slow nfs, something else). If you have a lots of uploads, pretty soon many of your mongrels (if not all) will be used for uploads and your application would become unusable. What options do you see to solve this problem?
</li>
<li>
You have a huge table in mysql, you need to select a few randomly selected records (and this is not a one-time action, it&#8217;ll be used pretty often, like on the home page), how&#8217;d you do that?
</li>
<li>
You have a document model with the following fields: id, user_id, title, body, created_at, views_count, download_count. There are 10000000 documents. You need to implement a download counters on your site so when one downloads a document, you&#8217;d increase the download_counter field. How would you implement counter management?
</li>
<li>
How&#8217;d you write an SQL query to find all users in a system that have no docs (standard User has_many docs relationship)?
</li>
<li>
Caching:</p>
<ul>
<li>What kinds of caching techniques do you know?</li>
<li>What caching options does Rails provide, when would you use those?</li>
<li>What caching options does HTTP protocol provide?</li>
<li>You have a pretty popular action on your site which uses some heavy SQL query which should be cached. But the problem is that sometimes when the cache expires and too many users hit the action, all those SQL queries will start hammering the database trying to refresh your caches&#8230; That causes huge problems. How&#8217;d you try to solve the problem? </li>
</ul>
</li>
</ol>
<hr/>
<p>As you can see, these questions aren&#8217;t asking you about REST or new cool Rails buzzwords (ActiveResource, named_scope, etc, etc) because IMHO - you can learn those in a week of skimming through any rails-related mailing list. My questions are aimed at the most often happening problems in high-traffic startups where not all common practices could be used and you need to think before writing some code that&#8217;d be executed millions of times per day.</p>
<p>So, if you&#8217;ve read the questions and you think you know (or is able to find in Google/books/etc) answers and you think you know Rails I think you should contact us because we&#8217;re hiring. At this moment we need a few really great Ruby-developers that are not afraid of working on high-load web applications and who isn&#8217;t just a buzzword junkies, but a developers that could use their tools effectively.</p>
<p>For more information and more formal position information, please check out <a href="http://www.scribd.com/jobs/2" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">our jobs page</a> or just <a href="mailto:alexey@scribd.com">email me</a> with any questions related to these positions.</p>
<p>P. S. If you&#8217;re really good, we could work with you remotely w/o relocation to San Francisco (we have some team members in Canada and Ukraine now).</p>

<p><a href="http://feedads.g.doubleclick.net/~a/VJxilVxMnqGstiAyjbfza4qwwsg/0/da"><img src="http://feedads.g.doubleclick.net/~a/VJxilVxMnqGstiAyjbfza4qwwsg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/VJxilVxMnqGstiAyjbfza4qwwsg/1/da"><img src="http://feedads.g.doubleclick.net/~a/VJxilVxMnqGstiAyjbfza4qwwsg/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=gxOA5Qvc"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=gxOA5Qvc" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=2cIHq4gW"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=cEmONMiR"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=cEmONMiR" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2009/02/07/rails-developer-for-a-large-startup-my-vision-of-an-ideal-candidate/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2009/02/07/rails-developer-for-a-large-startup-my-vision-of-an-ideal-candidate/</feedburner:origLink></item>
		<item>
		<title>ActiveMQ Tips: Flow Control and Stalled Producers Problem</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/suGnhpl7WZA/</link>
		<comments>http://blog.kovyrin.net/2009/01/23/activemq-tips-flow-control-and-stalled-producers-problem/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 07:23:09 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Admin-tips]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[activemq]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[queue]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[scribd]]></category>

		<category><![CDATA[server]]></category>

		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=167</guid>
		<description><![CDATA[It&#8217;s been a few months since we&#8216;ve started actively using ActiveMQ queue server in our project. For some time we had pretty weird problems with it and even started thinking about switching to something else or even writing our own queue server which would comply with our requirements. The most annoying problem was the following: [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a few months since <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">we</a>&#8216;ve started actively using <a href="http://activemq.apache.org/" onClick="javascript:urchinTracker ('/outbound/article/activemq.apache.org');">ActiveMQ</a> queue server in our project. For some time we had pretty weird problems with it and even started thinking about switching to something else or even writing our own queue server which would comply with our requirements. The most annoying problem was the following: some time after activemq restart everything worked really well and then activemq started lagging, queue started growing and all producer processes were stalling on push() operations. We rewrote our producers from Ruby to JRuby, then to Java and still - after some time everything was in a bad shape until we restarted the queue server.</p>
<p>So, long story short, after a lots of docs and source code reading we&#8217;ve found really interesting thing. There is a &#8220;feature&#8221; added in the recent ActiveMQ release (5.X) called &#8220;<a href="http://activemq.apache.org/producer-flow-control.html" onClick="javascript:urchinTracker ('/outbound/article/activemq.apache.org');">flow control</a>&#8220;, which is used by ActiveMQ core to <a href="http://activemq.apache.org/what-happens-with-a-fast-producer-and-slow-consumer.html" onClick="javascript:urchinTracker ('/outbound/article/activemq.apache.org');">slow down too fast producers</a> when consumers lag or just aren&#8217;t as fast as ActiveMQ wants them to be. This results in unpredictable producers stalls and all kinds of weird problems. </p>
<p>If you&#8217;re experiencing the same problems, you could try to add the following to your activemq.xml file to make it stop using flow control and let your producers spool data to the queue as fast as it is possible (that&#8217;s exactly what I&#8217;d expect from a queue server):</p>
<div class="codecolorer-container xml " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="xml codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="sc3"><span class="re1">&lt;destinationPolicy<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;policyMap<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;policyEntries<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;policyEntry</span> <span class="re0">queue</span>=<span class="st0">&quot;&gt;</span></span>&quot; producerFlowControl=&quot;false&quot; memoryLimit=&quot;64mb&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/policyEntries<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/policyMap<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/destinationPolicy<span class="re2">&gt;</span></span></span></div></td></table></div>
<p>When this is added, all your queues (if they take more than 64Mb of RAM) will start persisting their messages to the disk and freeing your RAM to consume more messages w/o any slowdowns.</p>
<p>Another useful feature we use in our producer is <a href="http://activemq.apache.org/async-sends.html" onClick="javascript:urchinTracker ('/outbound/article/activemq.apache.org');">Async Sends</a> which basically means that your producers won&#8217;t require any acknowledgments from ActiveMQ after it pushes your messages to a queue. This makes push() operations MUCH faster and your producers&#8217; throughput will become tremendously higher. If you use Java as your producer language, you could use the following code to make your connection async:</p>
<div class="codecolorer-container java " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="java codecolorer" style="font-family:Monaco,Lucida Console,monospace">queueConnectionFactory <span class="sy0">=</span> <span class="kw1">new</span> ActiveMQConnectionFactory<span class="br0">&#40;</span>queue_user, queue_password, queue_url<span class="br0">&#41;</span><span class="sy0">;</span><br />
queueConnectionPool <span class="sy0">=</span> <span class="kw1">new</span> PooledConnectionFactory<span class="br0">&#40;</span>queueConnectionFactory<span class="br0">&#41;</span><span class="sy0">;</span><br />
queueConnectionPool.<span class="me1">setMaxConnections</span><span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// This line is used to make your connection async</span><br />
<span class="br0">&#40;</span><span class="br0">&#40;</span>ActiveMQConnectionFactory<span class="br0">&#41;</span>queueConnectionFactory<span class="br0">&#41;</span>.<span class="me1">setUseAsyncSend</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span></div></td></table></div>
<p>After we&#8217;ve made the changes explained above, our queue server and producers became rock stable and blazing fast so there is no point to look for another solution because looks like <a href="http://blog.kovyrin.net/2008/10/30/activemq-ruby-stomp-client-how-to-process-elements-one-by-one/" >I was right</a> - ActiveMQ is an amazing piece of software - you just need to learn it before using.</p>
<p>This is it for today, if you have any questions, feel free to ask them in the comments and I&#8217;d be glad to answer.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/pBG0qi1-RR5Z_PupxoaRgJgawuQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/pBG0qi1-RR5Z_PupxoaRgJgawuQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/pBG0qi1-RR5Z_PupxoaRgJgawuQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/pBG0qi1-RR5Z_PupxoaRgJgawuQ/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=lWZTp0VX"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=lWZTp0VX" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=TMpwL3Xb"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=VSQTKnb7"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=VSQTKnb7" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2009/01/23/activemq-tips-flow-control-and-stalled-producers-problem/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2009/01/23/activemq-tips-flow-control-and-stalled-producers-problem/</feedburner:origLink></item>
		<item>
		<title>Using SSH tunnel connection as a SOCKS5 proxy</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/7A0eK0KD6Oc/</link>
		<comments>http://blog.kovyrin.net/2008/12/11/using-ssh-tunnel-connection-as-a-socks5-proxy/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 23:13:51 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Admin-tips]]></category>

		<category><![CDATA[Networks]]></category>

		<category><![CDATA[proxy]]></category>

		<category><![CDATA[socks]]></category>

		<category><![CDATA[ssh]]></category>

		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=156</guid>
		<description><![CDATA[Month ago I was on a vacation and as usual even though our hotel provided us with an internet connection on a pretty decent speeds, I wasn&#8217;t able to work there because they&#8217;ve banned all tcp ports but some major ones (like 80, 21, etc) and I needed to be able to use ssh, mysql, [...]]]></description>
			<content:encoded><![CDATA[<p>Month ago I was on a vacation and as usual even though our hotel provided us with an internet connection on a pretty decent speeds, I wasn&#8217;t able to work there because they&#8217;ve banned all tcp ports but some major ones (like 80, 21, etc) and I needed to be able to use ssh, mysql, IMs and other non-web software.</p>
<p>After a short research I&#8217;ve found a pretty simple to set up and easy to use approach to such a connection problems I&#8217;d like to describe here.</p>
<p><span id="more-156"></span></p>
<p>First, you&#8217;ll need someone (or you can do it before leaving home) to start an ssh daemon on port 80 on one of your servers. I use one of my Slicehub slices for this to permanently have an ability to use it. You can do it like this (if it is a temporary solution):</p>
<div class="codecolorer-container bash " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="bash codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co0"># `which sshd` -p 80</span></div></td></table></div>
<p><i>Notice: this <tt>`which sshd`</tt> was used because on some OSes sshd does not want to start w/o an absolute path to its binary.</i></p>
<p>If you&#8217;d like to have it permanent, just add one line to your <tt>/etc/ssh/sshd_config</tt> file and restart your ssh server:</p>
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">Port 80</div></td></table></div>
<p>OK, this step is finished and you have sshd listening on port 80. Now, let&#8217;s imagine you go somewhere and need to use ssh (or ICQ/GTalk/Jabber/MSN/AIM, or torrents) and some weird admin banned all tcp ports but port 80. Here&#8217;s what you&#8217;ll need to do:</p>
<ol>
<li>You open terminal on your machine (most likely it&#8217;ll be your laptop)</li>
<li>You run the following command:
<div class="codecolorer-container text " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="text codecolorer" style="font-family:Monaco,Lucida Console,monospace">$ ssh -D 1080 -p 80 -v user@your-host.com &quot;sleep 1000000&quot;</div></td></table></div>
</li>
<li>Use 127.0.0.1 (port 1080) as your local socks4/5 proxy server (no authorization) in any software you want</li>
</ol>
<p>When you have theses steps are finished, you can go to any place you want and wherever you have an access to web servers, you&#8217;ll have an access to anything you need (tested on: ssh, safari, adium, vuze torrent client, rubygems, macports).</p>
<p><em>P. S.</em> On my macbook to make this thing even more useful I&#8217;ve installed <b>tsocks</b> port (non-mac users, check it out <a href="http://giig.ugr.es/~rgarcia/tsocks/" onClick="javascript:urchinTracker ('/outbound/article/giig.ugr.es');">here</a>).</p>

<p><a href="http://feedads.g.doubleclick.net/~a/8XLJ0wX2k8ZgOuTJ94qUkUxns4s/0/da"><img src="http://feedads.g.doubleclick.net/~a/8XLJ0wX2k8ZgOuTJ94qUkUxns4s/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/8XLJ0wX2k8ZgOuTJ94qUkUxns4s/1/da"><img src="http://feedads.g.doubleclick.net/~a/8XLJ0wX2k8ZgOuTJ94qUkUxns4s/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=hAiLV1lB"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=hAiLV1lB" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=OGgbYSd8"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=GasixQjx"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=GasixQjx" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/12/11/using-ssh-tunnel-connection-as-a-socks5-proxy/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/12/11/using-ssh-tunnel-connection-as-a-socks5-proxy/</feedburner:origLink></item>
		<item>
		<title>Lighttpd Book from Packt - Great Thanksgiving Present</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/w5ByaDGlZw0/</link>
		<comments>http://blog.kovyrin.net/2008/11/27/lighttpd-book-from-packt-great-thanksgiving-present/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 07:15:30 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Admin-tips]]></category>

		<category><![CDATA[Networks]]></category>

		<category><![CDATA[books]]></category>

		<category><![CDATA[Lighttpd]]></category>

		<category><![CDATA[Nginx]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=146</guid>
		<description><![CDATA[Many people know me as a nginx web server evangelist. But as (IMHO) any professional I think that it is really rewarding to know as much as possible about all the tools available on the market so every time you need to make a decision on some technical issue, you&#8217;d consider all pros and cons [...]]]></description>
			<content:encoded><![CDATA[<p>Many people know me as a nginx web server evangelist. But as (IMHO) any professional I think that it is really rewarding to know as much as possible about all the tools available on the market so every time you need to make a decision on some technical issue, you&#8217;d consider all pros and cons based on my own knowledge. </p>
<p>This is why when I received an email from <a href="http://www.packtpub.com/" onClick="javascript:urchinTracker ('/outbound/article/www.packtpub.com');">Packt</a> company asking if I&#8217;d like to read and review <a href="http://www.packtpub.com/lighttpd/book" onClick="javascript:urchinTracker ('/outbound/article/www.packtpub.com');">their book on Lighttpd</a> I decided to give it a shot (I usually do not review any books because I do not always have enough time to read a book thoroughly to be able to write a review). So, here are my impressions from this book.</p>
<p><span id="more-146"></span></p>
<p>First, when I received the book, I was in doubt: how such a small book could cover so flexible and multi-purpose piece of software like <a href="http://www.lighttpd.net/" onClick="javascript:urchinTracker ('/outbound/article/www.lighttpd.net');">Lighttpd</a>? But after reading a few first chapters I understood that the book is written as any <b>professional</b> book should be written - no weird long chapters explaining what is Internet, web server, HTTP or HTML. From the first pages you dive to the world of Lighttpd starting from installation and going through the most popular and useful configuration options to really interesting virtual hosting configurations.</p>
<p>Pretty interesting security-related chapters explain typical process of obtaining and installing SSL certificates. This always was the most painful process for me in almost any web setup I worked on, don&#8217;t know why though, this process seemed kind of messy for me, but I think those chapters could help novice web server administrators understand the process of securing a web server. </p>
<p>For many new lighttpd users the most interesting chapters should be ones that explain typical problems and use cases of using apache with or instead of apache servers and describe how to set up lighttpd to be used with the most popular backend web software (Ruby on Rails, wordpress, phpmyadmin and more). From my consulting experience I should say that this is the most popular lighttpd deployment scheme (lighttpd frontend + some backends) and this is why these chapters should be the most interesting for new users. As a RoR server administrator I wish authors would explain more different deployment options for Rails, but of course I understand that the book is dedicated to lighttpd, not Rails so it is OK to miss some options. </p>
<p>And finally, for experienced users like me who understands all the internals of the web traffic handling and needs to get more control over the traffic there is <b>just awesome</b> chapters on using Lua with lighttpd and writing custom lighttpd modules. I really wish I had such an explanations when I was doing nginx modules development for <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">our</a> projects! If I&#8217;d write some lighttpd module I&#8217;d definitely buy this book just because of those Lua and modules-related chapters - there is not so much info on these topics on the Net and such a solid explanation of the basics of web server extension could help a lot.</p>
<p>So, as the final words on <a href="http://www.packtpub.com/lighttpd/book" onClick="javascript:urchinTracker ('/outbound/article/www.packtpub.com');">this book</a>, I&#8217;d like to recommend it to all web services administrators (even if they do not use lighttpd yet) - this book explains many fundamental things that you&#8217;d really like to know. As for professional developers/admins, this books could be useful if they are going to work on some advanced configurations or modules for lighttpd (yes, I loved those lua and modules sections).</p>

<p><a href="http://feedads.g.doubleclick.net/~a/nerolLkMGm8YqsVbSPj6UMD0OGA/0/da"><img src="http://feedads.g.doubleclick.net/~a/nerolLkMGm8YqsVbSPj6UMD0OGA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/nerolLkMGm8YqsVbSPj6UMD0OGA/1/da"><img src="http://feedads.g.doubleclick.net/~a/nerolLkMGm8YqsVbSPj6UMD0OGA/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=ga5E3aVI"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=ga5E3aVI" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=kK8b2gcJ"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=27L3ZqAb"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=27L3ZqAb" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/11/27/lighttpd-book-from-packt-great-thanksgiving-present/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/11/27/lighttpd-book-from-packt-great-thanksgiving-present/</feedburner:origLink></item>
		<item>
		<title>ActiveMQ + Ruby Stomp Client: How to process elements one by one</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/4LSezsb2MOw/</link>
		<comments>http://blog.kovyrin.net/2008/10/30/activemq-ruby-stomp-client-how-to-process-elements-one-by-one/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 04:42:39 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Admin-tips]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[My Projects]]></category>

		<category><![CDATA[activemq]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[development]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[queue]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[scalability]]></category>

		<category><![CDATA[scribd]]></category>

		<category><![CDATA[stomp]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=135</guid>
		<description><![CDATA[Few months ago I&#8217;ve switched one of our internal projects from doing synchronous database saves of analytics data to an asynchronous processing using starling + a pool of workers. This was the day when I really understood the power of specialized queue servers. I was using database (mostly, MySQL) for this kind of tasks for [...]]]></description>
			<content:encoded><![CDATA[<p>Few months ago I&#8217;ve switched one of <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">our</a> internal projects from doing synchronous database saves of analytics data to an asynchronous processing using <a href="http://github.com/starling/starling/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">starling</a> + a pool of workers. This was the day when I really understood the power of specialized queue servers. I was using database (mostly, MySQL) for this kind of tasks for years and sometimes (especially under a highly concurrent load) it worked not so fast&#8230; Few times I worked with some queue servers, but those were either some small tasks or I didn&#8217;t have a time to really get the idea, that specialized queue servers were created just to do these tasks quickly and efficiently.</p>
<p>All this time (few months now) I was using starling noticed really bad thing in how it works: if workers die (really die, or lock on something for a long time, or just start lagging) and queue start growing, the thing could kill your server and you won&#8217;t be able to do something about it - it just eats all your memory and this is it. Since then I&#8217;ve started looking for a better solution for our queuing, the technology was too cool to give up. I&#8217;ve tried 5 or 6 different popular solutions and all of them sucked&#8230; They ALL had the same problem - if your queue grows, this is your problem and not queue broker&#8217;s :-/ The last solution I&#8217;ve tested was <a href="http://activemq.apache.org/" onClick="javascript:urchinTracker ('/outbound/article/activemq.apache.org');">ActiveMQ</a> and either I wasn&#8217;t able to push it to its limits or it is really so cool, but looks like it does not have this memory problem. So, we&#8217;ve started using it recently.</p>
<p>In this small post I&#8217;d like to describe a few things that took me pretty long to figure out in <a href="http://github.com/grempe/stomp/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">ruby Stomp client</a>: how to make queues persistent (really!) and how to process elements one by one with clients&#8217; acknowledgments.<br />
<span id="more-135"></span><br />
First, we need to connect to the queue server and this code is the same for clients and servers:</p>
<div class="codecolorer-container ruby " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">client = <span class="re2">Stomp::Client</span>.<span class="kw3">open</span> <span class="st0">&quot;stomp://localhost:61613&quot;</span><br />
<span class="kw1">or</span><br />
client = <span class="re2">Stomp::Client</span>.<span class="kw3">open</span><span class="br0">&#40;</span>login, password, host, port, reliable<span class="br0">&#41;</span></div></td></table></div>
<p>Second form looks better for me because it allows you to specify if you want client to be reliable (lock on errors and try to reconnect, etc) or just want client to raise an error in case of any problems.</p>
<p>When you&#8217;ve connected to the server, you can push your data to a queue:</p>
<div class="codecolorer-container ruby " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">client.<span class="me1">send</span><span class="br0">&#40;</span><span class="st0">'/queue/some_queue'</span>, <span class="st0">&quot;hello world&quot;</span>, headers<span class="br0">&#41;</span></div></td></table></div>
<p>And this is where you have an ability to specify if you want your data to be persistent (survive server crashes, etc): <tt>headers</tt> is a hash that could have an element <tt>:persistent => true</tt>, which would do the thing. So, your code would looks like this (for example):</p>
<div class="codecolorer-container ruby " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace">client.<span class="me1">send</span><span class="br0">&#40;</span><span class="st0">'/queue/some_queue'</span>, <span class="st0">&quot;hello world&quot;</span>, <span class="re3">:persistent</span> <span class="sy0">=&gt;</span> <span class="kw2">true</span><span class="br0">&#41;</span><br />
client.<span class="me1">close</span> <span class="co1"># this is needed only in your push code</span></div></td></table></div>
<p>Now, when you have your data submitted to the queue, you need to be able to read it and process with some script. This is as simple as the following code:</p>
<div class="codecolorer-container ruby " style="overflow:auto;white-space:nowrap;width:500px"><table cellspacing="0" cellpadding="0"><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="font-family:Monaco,Lucida Console,monospace"><span class="co1"># Processing loop</span><br />
client.<span class="me1">subscribe</span><span class="br0">&#40;</span><span class="st0">'/queue/some_queue'</span>, headers<span class="br0">&#41;</span> <span class="kw1">do</span> <span class="sy0">|</span>msg<span class="sy0">|</span><br />
&nbsp; <span class="co1"># Process your message here</span><br />
&nbsp; <span class="co1"># Your submitted data is in msg.body</span><br />
<span class="kw1">end</span><br />
client.<span class="me1">join</span> <span class="co1"># Wait until listening thread dies</span></div></td></table></div>
<p>Again, we wanted to receive messages one by one and acknowledge successful processing in our code. This is simple too. You need:</p>
<ul>
<li>Pass <tt>:ack => :client</tt> as an element in your <tt>headers</tt> hash</li>
<li>Call <tt>client.acknowledge(msg)</tt> in the loop if you&#8217;re sure that an element could be removed from the queue</li>
</ul>
<p>This is basically it with the stuff I wanted to explain today. If you&#8217;ve never tried to work with any queue servers, try today and maybe tomorrow you won&#8217;t be able to imagine your systems architecture without such a component <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/_9DVcTyejuR1NDw_Jk0A_VF0lqk/0/da"><img src="http://feedads.g.doubleclick.net/~a/_9DVcTyejuR1NDw_Jk0A_VF0lqk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/_9DVcTyejuR1NDw_Jk0A_VF0lqk/1/da"><img src="http://feedads.g.doubleclick.net/~a/_9DVcTyejuR1NDw_Jk0A_VF0lqk/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=SXYhcBna"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=SXYhcBna" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=gWpf26J8"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=ZrRWa4K4"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=ZrRWa4K4" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/10/30/activemq-ruby-stomp-client-how-to-process-elements-one-by-one/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/10/30/activemq-ruby-stomp-client-how-to-process-elements-one-by-one/</feedburner:origLink></item>
		<item>
		<title>Blog outage</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/FwOkxndfCxo/</link>
		<comments>http://blog.kovyrin.net/2008/10/26/blog-outage/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 07:33:57 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[outage]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/2008/10/25/131-revision/</guid>
		<description><![CDATA[Sorry for a short outage today - we were moving to a new server we had some problems because of software incompatibilities on the new box. Now all sites on this box should behave as usual  
]]></description>
			<content:encoded><![CDATA[<p>Sorry for a short outage today - we were moving to a new server we had some problems because of software incompatibilities on the new box. Now all sites on this box should behave as usual <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<p><a href="http://feedads.g.doubleclick.net/~a/O_x6vBFsGAZOqi8ZJ2XYqBsCoXo/0/da"><img src="http://feedads.g.doubleclick.net/~a/O_x6vBFsGAZOqi8ZJ2XYqBsCoXo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/O_x6vBFsGAZOqi8ZJ2XYqBsCoXo/1/da"><img src="http://feedads.g.doubleclick.net/~a/O_x6vBFsGAZOqi8ZJ2XYqBsCoXo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=ljJxULHb"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=ljJxULHb" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=568CfVnZ"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=5lXny62B"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=5lXny62B" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/10/26/blog-outage/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/10/26/blog-outage/</feedburner:origLink></item>
		<item>
		<title>Advanced Squid Caching for Rails Applications: Preface</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/ZKlb-9lVezk/</link>
		<comments>http://blog.kovyrin.net/2008/10/25/advanced-squid-caching-for-rails-applications-preface/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 21:28:30 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[My Projects]]></category>

		<category><![CDATA[Networks]]></category>

		<category><![CDATA[caching]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[memcache]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[scalability]]></category>

		<category><![CDATA[scribd]]></category>

		<category><![CDATA[squid]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=131</guid>
		<description><![CDATA[Since the day one when I joined Scribd, I was thinking about the fact that 90+% of our traffic is going to the document view pages, which is a single action in our documents controller. I was wondering how could we improve this action responsiveness and make our users happier.
Few times I was creating a [...]]]></description>
			<content:encoded><![CDATA[<p>Since the day one when <a href="http://kovyrin.info/2008/07/23/new-job-scalability-expert-in-scribdcom/" onClick="javascript:urchinTracker ('/outbound/article/kovyrin.info');">I joined Scribd</a>, I was thinking about the fact that 90+% of our traffic is going to the document view pages, which is a single action in our documents controller. I was wondering how could we improve this action responsiveness and make our users happier.</p>
<p>Few times I was creating a git branches and hacking this action trying to implement some sort of page-level caching to make things faster. But all the time results weren&#8217;t as good as I&#8217;d like them to be. So, branches were sitting there and waiting for a better idea.<br />
<span id="more-131"></span><br />
Few months ago <a href="http://kpumuk.info" onClick="javascript:urchinTracker ('/outbound/article/kpumuk.info');">my good friend</a> has joined Scribd and we&#8217;ve started thinking on this problem together. As the result of our brainstorming we&#8217;ve managed to figure out what were the problems preventing us from doing efficient caching:</p>
<ul>
<li>First of all, a lots of code in the action is changing the page view if our visitor is a bot (no, not a cloaking, just some minor adjustments of the view).</li>
<li>Second problem was a set of differences in the view for anonymous and logged in users.</li>
<li>And finally, third problem was the fact that the page has a few blocks that change pretty dynamically: document stats pane and comments lists.</li>
</ul>
<p>All these problems when combined were creating a lots of pain when I was trying to cache a whole page. When we&#8217;ve figured them out, we&#8217;ve started thinking on how could we generalize possible combinations of those factors and possible approaches to caching.</p>
<p>There is a well known idea in web applications development: the fastest web app action is an action that does not require any code to be executed on your application server. So, first idea we&#8217;ve tried to think about was some approach that would definitely reduce the number of hits on our app servers. This idea was based on HTTP protocol features related to <strong>Last-Modified</strong> and <strong>E-Tag</strong> headers. But there was a problem - not so many users go to the same page twice so even if we&#8217;d make the page cacheable, it wouldn&#8217;t help too much. But the idea of full page caching outside of the application was really good and we&#8217;ve started playing with it to figure out how to use it in production.</p>
<p>Long time ago, when Internet was slow and expensive many ISPs and large companies were trying to reduce their traffic w/o hurting users&#8217; experience. Then <a href="http://www.squid-cache.org/" onClick="javascript:urchinTracker ('/outbound/article/www.squid-cache.org');">caching proxy servers</a> were born. The idea of those servers was to handle all web requests going from a network (ISP or a company office) and try to cache as much content as possible so when the same or some other user would request a cached page, proxy server would return it really fast. If we&#8217;d implement support for those Last-Modified headers, all proxy servers would be happy to cache our pages. But there was a problem - no one uses caching proxies in 2008 <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> So, we&#8217;ve got an idea - why can&#8217;t we place such a server in front of our application and make it cache content for all users in the world? (Yes, we knew about a caching reverse proxies before - I&#8217;m just trying to explain the flow of our thoughts and words when we were brainstorming the problem).</p>
<p>The only problem with this approach would be to differentiate logged in users, anonymous users and bots. Considering the fact that our proxy server could be placed between the app and our web servers (nginx), we&#8217;ve decided to create a nginx module that would translate the same document page URLs to a set of URLs, which would be different for all those 3 kinds of users.</p>
<p>When all those problems with different kinds of users were solved, we&#8217;ve decided to solve the last one - non-cacheable dynamic stats pane. The solution was pretty simple - we&#8217;ve added a small ajax call to the page which would update stats on the cached version of our page for all real users while bots will see the same page, but with a bit stale stats pane.</p>
<p>Long story short, the results is really great. Application servers load reduced by 50-70%, database servers  load is reduced by 30-60%, response times dropped down to 150-200 msec from 500-750 msec. As an additional positive effect of the caching we&#8217;ve managed to remove all fragments caches from the application and free more of memcached resources for data caches. Here are a few cacti graphs of our servers load/traffic (the caching was introduced on Oct 9th at night):</p>
<p><strong>Main MySQL command counters:</strong></p>
<div class="thumbnail"><a href="http://skitch.com/kovyrin/2jq2/cacti" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');"><img src="http://img.skitch.com/20081025-kkeqfuqp87w22fgpqwpa99ri4f.preview.jpg" alt="Cacti" /></a><br /><span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080">Uploaded with <a href="http://plasq.com/" onClick="javascript:urchinTracker ('/outbound/article/plasq.com');">plasq</a>&#8217;s <a href="http://skitch.com" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');">Skitch</a>!</span></div>
<p><br/></p>
<p><strong>One of our Application Servers CPU Usage:</strong></p>
<div class="thumbnail"><a href="http://skitch.com/kovyrin/2jqh/cacti" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');"><img src="http://img.skitch.com/20081025-be4571a18h2ijh75idgipsw4u1.preview.jpg" alt="Cacti" /></a><br /><span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080">Uploaded with <a href="http://plasq.com/" onClick="javascript:urchinTracker ('/outbound/article/plasq.com');">plasq</a>&#8217;s <a href="http://skitch.com" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');">Skitch</a>!</span></div>
<p><br/></p>
<p><strong>One of our Application Servers Load Average:</strong></p>
<div class="thumbnail"><a href="http://skitch.com/kovyrin/2jxy/cacti" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');"><img src="http://img.skitch.com/20081025-mdjxgquferw1tdwrqecssbafby.preview.jpg" alt="Cacti" /></a><br /><span style="font-family: Lucida Grande, Trebuchet, sans-serif, Helvetica, Arial; font-size: 10px; color: #808080">Uploaded with <a href="http://plasq.com/" onClick="javascript:urchinTracker ('/outbound/article/plasq.com');">plasq</a>&#8217;s <a href="http://skitch.com" onClick="javascript:urchinTracker ('/outbound/article/skitch.com');">Skitch</a>!</span></div>
<p><br/></p>
<p>Unfortunately there are a lot of things to share related to this caching experience, so I&#8217;ve decided to make a series of posts that would explain all the problems we had and solutions we&#8217;ve found for each of the following parts of the caching system:</p>
<ul>
<li>Nginx module development</li>
<li>Squid Server setup (configs and hardware)</li>
<li>Rails code to support Last-Modified headers and how we purge caches</li>
</ul>
<p>So, if you&#8217;re interested in details, subscribe to this blog&#8217;s <a href="http://feeds.feedburner.com/Homo-Adminus" onClick="javascript:urchinTracker ('/outbound/article/feeds.feedburner.com');">RSS feed</a> and in a few days you&#8217;ll see the first article from this series.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/VMcaSW0OJPo6Qw3KFjVTRm6RG9k/0/da"><img src="http://feedads.g.doubleclick.net/~a/VMcaSW0OJPo6Qw3KFjVTRm6RG9k/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/VMcaSW0OJPo6Qw3KFjVTRm6RG9k/1/da"><img src="http://feedads.g.doubleclick.net/~a/VMcaSW0OJPo6Qw3KFjVTRm6RG9k/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=l0tT5YOr"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=l0tT5YOr" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=fMWt7xbQ"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=jlj4Vrnn"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=jlj4Vrnn" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/10/25/advanced-squid-caching-for-rails-applications-preface/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/10/25/advanced-squid-caching-for-rails-applications-preface/</feedburner:origLink></item>
		<item>
		<title>Bounces-handler Released</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/P_mm_8ZyoVM/</link>
		<comments>http://blog.kovyrin.net/2008/08/03/bounce-handler-released/#comments</comments>
		<pubDate>Sun, 03 Aug 2008 08:46:05 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[My Projects]]></category>

		<category><![CDATA[Networks]]></category>

		<category><![CDATA[email]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[release]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Ruby On Rails]]></category>

		<category><![CDATA[scribd]]></category>

		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=130</guid>
		<description><![CDATA[Today I&#8217;ve managed to finish initial version of our bounces-handler package we use for mailing-related stuff in Scribd. 
Bounces-handler package is a simple set of scripts to automatically process email bounces and ISP‘s feedback loops emails, maintain your mailing blacklists and a Rails plugin to use those blacklists in your RoR applications.
This piece of software [...]]]></description>
			<content:encoded><![CDATA[<p>Today I&#8217;ve managed to finish <a href="http://github.com/kovyrin/bounces-handler/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">initial version of our bounces-handler package</a> we use for mailing-related stuff in <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">Scribd</a>. </p>
<p>Bounces-handler package is a simple set of scripts to automatically process email bounces and ISP‘s feedback loops emails, maintain your mailing blacklists and a Rails plugin to use those blacklists in your RoR applications.</p>
<p>This piece of software has been developed as a part of more global work on mailing quality improvement in Scribd.com, but it was one of the most critical steps after setting up reverse DNS records, DKIM and SPF. </p>
<p>The <a href="http://github.com/kovyrin/bounces-handler/tree/master" onClick="javascript:urchinTracker ('/outbound/article/github.com');">package</a> itself consists of two parts:</p>
<ul>
<li>Perl scripts to process incoming email:
<ul>
<li>bounces processor — could be assigned to process all your bounce emails</li>
<li>feedback loops messages processor — more specific for Scribd, but still - could be modified for your needs (will be released soon).</li>
</ul>
</li>
<li>Rails plugin to work with mailing blacklists</li>
</ul>
<p>For more information, please check our <a href="http://github.com/kovyrin/bounces-handler/tree/master/README.rdoc" onClick="javascript:urchinTracker ('/outbound/article/github.com');">README file</a>. If you have any questions, comments or suggestions, please leave them here as a comments and I&#8217;ll try to reply as soon as possible.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/OFhCcE7JFFki5n1eh_yGJuF1nco/0/da"><img src="http://feedads.g.doubleclick.net/~a/OFhCcE7JFFki5n1eh_yGJuF1nco/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/OFhCcE7JFFki5n1eh_yGJuF1nco/1/da"><img src="http://feedads.g.doubleclick.net/~a/OFhCcE7JFFki5n1eh_yGJuF1nco/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=xA7qW3gZ"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=xA7qW3gZ" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=itARmYqe"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=LeUhQwsF"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=LeUhQwsF" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/08/03/bounce-handler-released/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/08/03/bounce-handler-released/</feedburner:origLink></item>
		<item>
		<title>Found an Ideal I/O Scheduler for my MySQL boxes</title>
		<link>http://feedproxy.google.com/~r/Homo-Adminus/~3/IsaZ-P10PqE/</link>
		<comments>http://blog.kovyrin.net/2008/07/20/found-an-ideal-io-scheduler-for-my-mysql-boxes/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 00:49:56 +0000</pubDate>
		<dc:creator>Scoundrel</dc:creator>
		
		<category><![CDATA[Admin-tips]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[i/O]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[scalability]]></category>

		<category><![CDATA[scheduler]]></category>

		<guid isPermaLink="false">http://blog.kovyrin.net/?p=129</guid>
		<description><![CDATA[Today I was doing some work on one of our database servers (each of them has 4 SAS disks in RAID10 on an Adaptec controller) and it required huge multi-thread I/O-bound read load. Basically it was a set of parallel full-scan reads from a 300Gb compressed innodb table (yes, we use innodb plugin). Looking at [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was doing some work on one of <a href="http://www.scribd.com" onClick="javascript:urchinTracker ('/outbound/article/www.scribd.com');">our</a> database servers (each of them has 4 SAS disks in RAID10 on an Adaptec controller) and it required huge multi-thread I/O-bound read load. Basically it was a set of parallel full-scan reads from a 300Gb compressed innodb table (yes, we use innodb plugin). Looking at the iostat I saw pretty expected results: 90-100% disk utilization and lots of read operations per second. Then I decided to play around with linux I/O schedulers and try to increase disk subsystem throughput. Here are the results:</p>
<p><span id="more-129"></span></p>
<table border="1">
<tr>
<th>Scheduler</th>
<th>Reads per second</th>
</tr>
<tr>
<td>cfq</td>
<td>20000-25000</td>
</tr>
<tr>
<td>noop</td>
<td>35000-60000</td>
</tr>
<tr>
<td>deadline</td>
<td>33000-45000</td>
</tr>
<tr>
<td>anticipatory</td>
<td>22000-29000</td>
</tr>
</table>
<p><em>Notice:</em> The box can&#8217;t be restarted to check with clean caches and stuff, but I was doing full reads from this huge table on a machine with 16Gb RAM so all caches were washed out by this load anyways.</p>
<p>As you can see, less work linux does on its side to optimize disk I/O, slower it works <img src='http://blog.kovyrin.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> Actually it was pretty expected, but still - surprising result. The problem (as guys from Youtube explained on the last year MySQL Conf) is there because Linux knows nothing about RAID&#8217;s internals and specific drives&#8217; queues so when it is trying to re-arrange requests in its own queue it wastes CPU resources and could potentially prevent RAID controller from doing its own queue optimizations. </p>
<p>After this test I&#8217;ve tried it on a few other I/O-bound servers (both read and write bound) and the result was the same - noop (do nothing) I/O scheduler gave me the best results. Long story short, I&#8217;ve decided to try this scheduler on all our boxes for a week and look at the results in cacti graphs to see how it works.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/VreNzb7d49jP7NL1usD82j7e448/0/da"><img src="http://feedads.g.doubleclick.net/~a/VreNzb7d49jP7NL1usD82j7e448/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/VreNzb7d49jP7NL1usD82j7e448/1/da"><img src="http://feedads.g.doubleclick.net/~a/VreNzb7d49jP7NL1usD82j7e448/1/di" border="0" ismap="true"></img></a></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=Wb0g9xSP"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=Wb0g9xSP" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=UiCy9jjU"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?d=50" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/Homo-Adminus?a=aCVjn5yl"><img src="http://feeds.feedburner.com/~f/Homo-Adminus?i=aCVjn5yl" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.kovyrin.net/2008/07/20/found-an-ideal-io-scheduler-for-my-mysql-boxes/feed/</wfw:commentRss>
		<feedburner:origLink>http://blog.kovyrin.net/2008/07/20/found-an-ideal-io-scheduler-for-my-mysql-boxes/</feedburner:origLink></item>
	</channel>
</rss>
