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

<channel>
	<title>kill the radio &#187; caching</title>
	<atom:link href="http://blog.killtheradio.net/tag/caching/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.killtheradio.net</link>
	<description>or die trying</description>
	<lastBuildDate>Thu, 15 Dec 2011 20:21:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Using gzip_static in nginx to cache gzip files</title>
		<link>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/</link>
		<comments>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/#comments</comments>
		<pubDate>Tue, 04 May 2010 03:54:12 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=542</guid>
		<description><![CDATA[Recently I&#8217;ve been working on speeding up the homepage of beeets.com. Most speed tests say it takes between 4-6 seconds. Obviously, all of them are somehow fatally flawed. I digress, though. Everyone (who&#8217;s anyone) knows that gzipping your content is a great way to reduce download time for your users. It can cut the size [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been working on speeding up the homepage of <a href="http://beeets.com/local-events/Santa+Cruz+CA">beeets.com</a>. Most speed tests say it takes between 4-6 seconds. Obviously, all of them are somehow fatally flawed. I digress, though.</p>
<p>Everyone (who&#8217;s anyone) knows that gzipping your content is a great way to reduce download time for your users. It can cut the size of html, css, and javascript by about 60-90%. Everyone also knows that gzipping can be very cpu intensive. <span style="text-decoration: underline;">Not anymore</span>.</p>
<p>I just installed <a href="http://wiki.nginx.org/NginxHttpGzipStaticModule">nginx&#8217;s Gzip Static Module</a> (compile nginx with &#8211;with-http_gzip_static_module) on beeets.com. It allows you to pre-cache your gzip files. What?</p>
<p>Let&#8217;s say you have the file /css/beeets.css. When a request for beeets.css comes through. the static gzip module will look for /css/beeets.css.gz. If it finds it, it will serve that file as gzipped content. This allows you to gzip your static files using the highest compression ratio (gzip -9) when deploying your site. Nginx then has absolutely no work to do besides serving the static gzip file (it&#8217;s very good at serving static content).</p>
<p>Wherever you have a gzip section in your nginx config, you can do:</p>
<pre>gzip_static on;</pre>
<p>That&#8217;s it. Note that you will have to create the .gz versions of the files yourself, and it&#8217;s mentioned in the docs that it&#8217;s better if the original and the .gz files have the same timestamp; so it may be a good idea to &#8220;touch&#8221; the files after both are created. It&#8217;s also a good idea to turn the gzip compression down (<a href="http://wiki.nginx.org/NginxHttpGzipModule#gzip_comp_level">gzip_comp_level 1..3</a>). This will minimally compress dynamic content without putting too much strain on the server.</p>
<p>This is a great way to get the best of both worlds: gzipping (faster downloads) <em>without</em> the extra load on the server. Once again, nginx pulls through as the best thing since multi-cellular life. Keep in mind that this only works on static content (css, javascript, etc etc). Dynamic pages can and should be gzipped, but with a lower compression ratio to keep load off the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/using-gzip_static-in-nginx-to-cache-gzip-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NginX as a caching reverse proxy for PHP</title>
		<link>http://blog.killtheradio.net/technology/nginx-as-a-caching-reverse-proxy-for-php/</link>
		<comments>http://blog.killtheradio.net/technology/nginx-as-a-caching-reverse-proxy-for-php/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 08:15:19 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[web services]]></category>

		<guid isPermaLink="false">http://blog.killtheradio.net/?p=394</guid>
		<description><![CDATA[So I got to thinking. There are some good caching reverse proxies out there, maybe it&#8217;s time to check one out for beeets. Not that we get a ton of traffic or we really need one, but hey what if we get digged or something? Anyway, the setup now is not really what I call [...]]]></description>
			<content:encoded><![CDATA[<p>So I got to thinking. There are some good caching reverse proxies out there, maybe it&#8217;s time to check one out for beeets. Not that we get a ton of traffic or we really need one, but hey what if we get digged or something? Anyway, the setup now is not really what I call simple. <a href="http://haproxy.1wt.eu/" target="_blank">HAproxy</a> sits in front of <a href="http://nginx.org/" target="_blank">NginX</a>, which serves static content and sends PHP requests back to <a href="http://php-fpm.org/" target="_blank">PHP-FPM</a>. That&#8217;s three steps to load a fucking page. Most sites use apache + mod_php (one step)! But I like to tinker, and I like to see requests/second double when I&#8217;m running ab on beeets.</p>
<p>So, I&#8217;d like to try something like <a href="http://varnish-cache.org/" target="_blank">Varnish</a> (sorry, <a href="http://www.squid-cache.org/" target="_blank">Squid</a>) but that&#8217;s adding one more step in between my requests and my content. Sure it would add a great speed boost, but it&#8217;s another layer of complexity. Plus it&#8217;s a whole nother service to ramp up on, which is fun but these days my time is limited. I did some research and found what I was looking for.</p>
<p>NginX has made me cream my pants every time I log onto the server since the day I installed it. It&#8217;s fast, stable, fast, and amazing. Wow, I love it. Now I read that NginX can cache FastCGI requests based on response caching headers. So I set it up, modified the beeets api to send back some <a href="http://www.mnot.net/cache_docs/" target="_blank">Cache-Control</a> junk, and voilà&#8230;a %2800 speed boost on some of the more complicated functions in the API.</p>
<p>Here&#8217;s the config I used:</p>
<pre># in http {}
fastcgi_cache_path /srv/tmp/cache/fastcgi_cache levels=1:2
                           keys_zone=php:16m
                           inactive=5m max_size=500m;</pre>
<pre># after our normal fastcgi_* stuff in server {}
fastcgi_cache php;
fastcgi_cache_key $request_uri$request_body;
fastcgi_cache_valid any 1s;
fastcgi_pass_header Set-Cookie;
fastcgi_buffers 64 4k;</pre>
<p>So we&#8217;re giving it a 500mb cache. It says that any valid cache is saved for 1 second, but this gets overriden with the Cache-Control headers sent by PHP. I&#8217;m using $request_body in the cache key because in our API, the actual request is sent through like:</p>
<pre>GET /events/tags/1 HTTP/1.1
Host: ...

{"page":1,"per_page":10}</pre>
<p>The params are sent through the HTTP body even in a GET. Why? I spent a good amount of time trying to get the API to accept the params through the query string, but decided that adding $request_body to one line in an NginX config was easier that re-working the structure of the API. So far so good.</p>
<p>That&#8217;s FastCGI acting as a reverse proxy cache. Ideally in our setup, HAproxy would be replaced by a reverse proxy cache like Varnish, and NginX would just stupidly forward requests to PHP like it was earlier today&#8230;but I like HAproxy. Having a health-checking load-balancer on every web server affords some interesting failover opportunities.</p>
<p>Anyway, hope this helps someone. NginX <span style="text-decoration: underline;">can</span> be a caching reverse proxy. Maybe not the best, but sometimes, just sometimes,  simple &gt; faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/nginx-as-a-caching-reverse-proxy-for-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Is a good Windows-based S3 tool too much to ask?</title>
		<link>http://blog.killtheradio.net/technology/is-a-good-windows-based-s3-tool-too-much-to-ask/</link>
		<comments>http://blog.killtheradio.net/technology/is-a-good-windows-based-s3-tool-too-much-to-ask/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 19:20:08 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://www.killtheradio.net/?p=77</guid>
		<description><![CDATA[With Amazon S3 being as good and cheap as it is, it&#8217;s almost essential for what I need it for&#8230;storing images and large static files. The problem is there is no interface besides SOAP, and if you don&#8217;t know how I feel about SOAP, let me tell you: it makes my head want to fucking [...]]]></description>
			<content:encoded><![CDATA[<p>With Amazon S3 being as good and cheap as it is, it&#8217;s almost essential for what I need it for&#8230;storing images and large static files. The problem is there is no interface besides SOAP, and if you don&#8217;t know how I feel about SOAP, let me tell you: it makes my head want to fucking explode. It&#8217;s insanely complicated for what it does. It tries to standardize so many things that it&#8217;s completely bloated&#8230;sending the message &#8220;hello&#8221; from one computer to another in SOAP takes oh about 10 years&#8230;5 years for a team of 50 supercomputers working in tandem to build the header and message body (which will total about 400 mb when finally complete), .02ms to send, and 5 years in decoding. Use JSON, you crackheads. Sure you&#8217;ll actually have to document it, but nothing is worse than SOAP, not even documenting.</p>
<p>That&#8217;s besides the point though. S3 chose to use SOAP, so I refuse to write my own client for it. This means that, as of late, the world is without a <span style="text-decoration: underline;">good</span> free S3 uploading client. S3Fox, the firefox extension, is ok&#8230;it can&#8217;t handle SSL connections though, so expect to lose your private key to a sniffer about 10 seconds after your first request. JungleDisk is now a completely paid service (I already pay for S3, I&#8217;m not paying those guys to fucking USE it). Linux has some great <em>command line</em> tools for S3 (yay&#8230;), but that leaves windows with either S3fox, JD ($$$), or a handful of shitty S3 clients.</p>
<p>Right now, I have to use a PHP script I built around the <a href="http://undesigned.org.za/2007/10/22/amazon-s3-php-class" target="_blank">S3 PHP Class</a> to do any uploading that doesn&#8217;t make me vomit. The S3 class works REALLY well&#8230;it lets you assign ACL while uploading, change headers for images (for browser-side caching, mmm) and best of all, doesn&#8217;t completely suck. Let&#8217;s all thank Donovan Schönknecht for writing something that actually works well and communicates with S3.</p>
<p>Here&#8217;s a piece of code I wrote that wraps around the S3 uploader. It uploads images, sets Cache-Control headers, and removes the images. What you want to do is copy your images into a folder, run this file one directory up (change $start_folder to == the name of the folder your images are in), and sit back. It will upload all your images, directory structure preserved, publicly viewable and with cache-control headers.</p>
<pre>&lt; ?
	// quick config
	$bucket			=	'your.bucket.com';
	$start_folder	=	'images';

	// settings
	error_reporting(E_ALL);
	ini_set('display_errors', 1);
	ini_set('max_execution_time', 3600);

	// include S3 class
	include 'S3.php';
	$s3	=	new S3('[your key]', '[your secret]', false);

	// get list of files. if you don't want a subdirectory, just change this line to not need one. hopefully you know PHP...
	$files	=	recurse(array(), $start_folder);

	// loop over files and upload
	for($i = 0, $n = count($files); $i &lt; $n; $i++)
	{
		$ext	=	preg_replace('/.*\./', '', $files[$i]);
		$type	=	'image/jpeg';
		if($ext == 'jpg')
		{
			$type	=	'image/jpeg';
		}
		else if($ext == 'gif')
		{
			$type	=	'image/gif';
		}
		else if($ext == 'png')
		{
			$type	=	'image/png';
		}

		if(
			!$s3-&gt;putObject(
				$s3-&gt;inputFile($files[$i]),
				$bucket,
				$files[$i],
				S3::ACL_PUBLIC_READ,
				array(),
				array('Cache-Control' =&gt; 'max-age=31536000', 'Content-Type' =&gt; $type)
			)
		)
		{
			echo '&lt;span style="color:green;"&gt;Failed: upload of '. $files[$i] . '';
		}
		else
		{
			echo '&lt;span style="color:green;"&gt;Succeeded: upload of '. $files[$i] .'';
			unlink($files[$i]);
		}
	}

	function recurse($files, $dir)
	{
		$d	=	scandir($dir);

		for($i = 0, $n = count($d); $i &lt; $n; $i++)
		{
			if(!preg_match('/^\./', $d[$i]))
			{
				if(is_dir($dir . '/' . $d[$i]))
				{
					$files	=	recurse($files, $dir . '/' . $d[$i]);
				}
				else
				{
					$files[]	=	$dir . '/' . $d[$i];
				}
			}
		}

		return $files;
	}
?&gt;</pre>
<p>Feel free to modify, copy, blah blah&#8230;but give credit where it&#8217;s due. Let it be a light to you when all other lights go out. Hopefully it helps someone, because it sure helps me out.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/is-a-good-windows-based-s3-tool-too-much-to-ask/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon S3</title>
		<link>http://blog.killtheradio.net/technology/amazon-s3/</link>
		<comments>http://blog.killtheradio.net/technology/amazon-s3/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 20:22:59 +0000</pubDate>
		<dc:creator>Andrew Lyon</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[beeets]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://killtheradio.dev/?p=24</guid>
		<description><![CDATA[Very cool service. I updated beeets to pull all images from images.beeets.com, an S3 bucket. Also, all css files now go through /css/css.php/file.css &#8230;which rewrites url(/images/&#8230;) to url(http://images.beeets.com/images/&#8230;) And guess what, it all works. I had some bad experiences with the S3Fox firefox plugin in the past, but it&#8217;s since been updated and I&#8217;ve been [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://aws.amazon.com/" target="_blank">Very cool service</a>. I updated <a href="http://www.beeets.com" target="_blank">beeets</a> to pull all images from images.beeets.com, an S3 bucket. Also, all css files now go through</p>
<p>/css/css.php/file.css &#8230;which rewrites</p>
<p>url(/images/&#8230;) to</p>
<p>url(http://images.beeets.com/images/&#8230;)</p>
<p>And guess what, it all works. I had some bad experiences with the <a href="https://addons.mozilla.org/en-US/firefox/addon/3247" target="_blank">S3Fox</a> firefox plugin in the past, but it&#8217;s since been updated and I&#8217;ve been using it regularly.</p>
<p>Also, using <a href="http://undesigned.org.za/2007/10/22/amazon-s3-php-class" target="_blank">S3.php</a>, all profile images now go directly onto images.beeets.com. Wicked.</p>
<p>So what does this mean? A few things:</p>
<p>1. Less bandwidth &amp; work &#8211; beeets will spend more time serving HTML, CSS, and JS than images.</p>
<p>2. Safer &#8211; We were backing up profile images to S3 indirectly before, but the chances of S3 going down VS our hosting are slim.</p>
<p>3. Worse image caching &#8211; Before, I had .htaccess controlling all the caching for static files. I liked it that way. S3 doesn&#8217;t do this very well at all. Apparently it&#8217;s configurable, but I don&#8217;t know how&#8230;any ideas?</p>
<p>All in all, it should be better for beeets. Maybe we&#8217;ll actually let users have images bigger than 10&#215;10 now ;)</p>
<p>Thumbs up to S3 (and probably all other Amazon web services).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.killtheradio.net/technology/amazon-s3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

