Yesterday I took 2nd-place in Northwestern University’s Wildhacks hackathon. It was my best finish in a hackathon to date, but the success masked the fact that I was debugging my project, Tweetscan, on-the-fly as I demo’ed it. When one judge came, the whole project was down and I had to show him a cached version,as I debugged the real app. Several times during the last few hours of the 36-hour event, I made a little tweak which ended up taking down the entire service. Debugging was painful, because my project was hundreds of lines of code long, and the exhaustion of a hackathon doesn’t exactly make for readable/well-documented.
Today I did a little mental post-mortem, and came up with a solution I’ll be using for every hackathon in the future: It’s based on this post I read recently on Netflix’s Microservices architecture, using a reverse-proxy. Basically, as follows:
- Every endpoint of the API I write will be contained in its own individual file, and run on its own, though they will all be on the same server. Less code per file means a much more maintainable app.
- All of the endpoints will be accessed through a reverse-http proxy. This will handle errors, so if one microservice goes down, the rest of the app will stay up. This means more reliable demoing, and that I’ll have more time to work during the hackathon, because I don’t have to worry about
The code for the top-layer reverse-proxy (using ‘HTTP-Proxy’ and Express) looks like this
var express = require('express'); var app = express(); var httpProxy = require('http-proxy'); var apiProxy = httpProxy.createProxyServer(); /// Below is the critical section. It catches errors, so the rest of the services stay up. apiProxy.on('error', function (err, req, res) { console.log(err); res.writeHead(500); res.end(); }); /// Each service runs on its own port. var serverOne = 'http://localhost:3001', ServerTwo = 'http://localhost:3002', ServerThree = 'http://localhost:3003'; app.all("/app1/*", function(req, res) { console.log('redirecting to Server1'); apiProxy.web(req, res, {target: serverOne}); }); app.all("/app2/*", function(req, res) { console.log('redirecting to Server2'); apiProxy.web(req, res, {target: ServerTwo}); }); app.all("/app3/*", function(req, res) { console.log('redirecting to Server3'); apiProxy.web(req, res, {target: ServerThree}); }); app.listen(80);