(Ken Struys' Blog)

web-developer, serious schemer

Just Let Me In: Hacking with the Twilio API

My apartment has a fairly standard phone system. You dial an extension, my cell is called and I can allow the caller to enter the building by dialing nine.

To let myself in I have a dongle that it's hooked into the system and to let you in. Unfortunately, when my girlfriend and I moved into the apartment, we were only given one dongle and were told we we're not able to get a second one.

For three months I've been using the system to call my own cellphone and letting myself in. The biggest problem with this solution is my android phone dies all the time and I've been left a couple times stuck outside.

I decided I needed a better system to just let me in my own building. Twilio provides the perfect service to solve the problem. Twilio is a web service API for building Voice and SMS based applications. When you signup, you get a San Francisco phone number for development and you can code simple XML documents to automate Dialing other numbers, Messaging, Playing audio, etc for basically pennies. Once you've coded you application you can pay around $1/month for a local number.

When I dial into my front door, audio is played asking whether you want to speak to myself (press one) or my girlfriend (press two). When you press either key, one of our two numbers are dialled and the system works as normal. Since I don't want to dial myself anymore, I also added a pin (some other combination of keys) that just opens the door by fooling the system into thinking I've dialed nine.

The Twilio code was really simple (it was about 20 lines of PHP). The only difficultly I had was getting the dialling 9 to work. Twilio does support dialling keys, but only after Dialing out to another number. I emailed the Twilio team and they said the easiest way to get it working was to use a program called audacity to record a 9 key tone. Playing this tone tricked the door system into thinking I had actually pressed the key. I was a little surprised to find out such a hacky solution would actually work, but then again a lot software solutions are hacks :P.

In the future I think I'll try to port my PHP solution over to a more Rackety approach. You could very easily use send/suspend provided by the web server to make the script even shorter/more clear.

Overall my experience with the Twilio API was fantastic, it's probably the easiest API I've ever had the pleasure of using and it's really impressive in it's simplicity.

Building a Scalable Web Architecture

A lot of people talk about building a scalable web architecture but don't actually explain what they mean. "Oh well you know use memcache and stuff", "No, that doesn't explain anything, how do you actually do it?". I'm sick of hearing it, so I'm going to explain how I do it. The best part about it is, other then server cycles/memory all the software I use are free. Here's a diagram of everything in the stack and that I will cover:

Let's start from the first entry point. First we have some kind of Load Balancer. In terms of software there are two great products out there, SQUID and Varnish. SQUID is the one I'm familiar with so I'm going to go over that one, but Varnish is being used by companies like Facebook, Twitter and Flickr it's really awesome and hopefully I will soon get the chance to try it out.

There are two main services SQUID provides. The first service is reverse proxying. SQUID receives a request from the web and send it's own request to one of the application servers (usually following round robin). That satisfies the load balancing of application servers. The other service SQUID provides is caching, when SQUID receives the response from the application server it caches the result by URL. You save a lot with SQUID's cache because application servers running things like PHP can be crazy CPU heavy. Caching generated results for even minutes we can handle a lot more load.

SQUID is policies are controlled by the squid.conf file. I like the configuration file because it allows you to control the caching policies. You can do things like disallow cache access of logged in users (acl aclname req_header Cookie [-i] user_cookie) and we can create rewrite programs to do url rewriting (url_rewrite_program /etc/squid/rewrite.py). I won't go through everything related policy by here's a starting configuration that I think makes sense. When you get the conf from SQUID it comes with an entire manual inline and it's hard to actually see what your configuration is doing either use mine, or remove the manual, it's available online.

Next we have our actual webservers, I usually just go with vanilla apache running whatever MVC framework I fancy. You might also want a webserver that better handles loading of assets (like images), for that I suggest nginx.

The final step that pretty much everyone takes these days is using some form in memory data cache. Usually I use memcached (distributed memcache). memcache isn't magic it's actually the simplest thing in the world: key value storage (max 1 MB values). You only really need two functions it provides, get(key) and set(key, value). The distributed aspect is that each webserver gets it's own memcache. When you add another webserver you add another memcache to the pool and all webservers can see the entire pool of memcaches. Why do the webservers need access to the entire pool? Let's say two requests come for the same page and we have a architecture decribed above. First request comes in and SQUID makes the request to the first webserver. The webserver tries to get data from memcache and misses so it pulls data from the database and stores it in it's memcache. Second request comes in, SQUID makes the request to the second webserver, this webserver checks and it hits because the first webserver stored it in the cache, no database call. If the second webserver wasn't able to see the entire distributed cache, it would have required a call to the database.

That's about all you really need to know to have pretty reasonable performance. Don't get me wrong, companies like Twitter and Facebook do far more then what I've described, but until your product requires fail whales stay lean, you can hire a scalability expert later. To give you idea of what companies actually use, I compiled the following table:

CompanyLoad BalancerWeb ServerApp ServerMemcacheDatabaseOther Cool Stuff
TwitterVarnishMongrelRuby on Rails/ScalaMemcachedCassandraMurder
WikipediaOver 40 SQUIDs and physical load balancersApacheMediaWiki/PHPMemcached (over 80 memcache servers, >3gb storage)MySQL
FlickrServerIron/SQUIDApachePHPMemcachedMySQLGanglia
DiggPhysical Load BalancerApachePHP/PythonMemcachedLazyboy/CassandraRabbitMQ
RedditElastic Load BalancingTornadoPython/DjangoMemcachedb, tons of stuff precomputedPostgreSQL (mostly denormalized)All on EC2
facebookVarnishHipHop embeded , over 10,000 serversPHP/C++ via Hip-HopMemcached over 800 instancesCassandraHipHop, BigPipe, Haystack, Hadoop/Hive
YoutubeNetScaler/VarnishApache, lighttpd for videoPython with psycoMemcached a lot of pre-rendered pagesMySQLCDN for most popular videos per locale