Writing a reverse proxy/loadbalancer from the ground up in C, part 4: Dealing with slow writes to the network
This is the fourth step along my road to building a simple C-based reverse proxy/loadbalancer, rsp, so that I can understand how nginx/OpenResty works -- more background here. Here are links to the first part, where I showed the basic networking code required to write a proxy that could handle one incoming connection at a time and connect it with a single backend, to the second part, where I added the code to handle multiple connections by using epoll, and to the third part, where I started using Lua to configure the proxy.
This post was was unplanned; it shows how I fixed a bug that I discovered when I first tried to use rsp to act as a reverse proxy in front of this blog. The bug is fixed, and you're now reading this via rsp. The problem was that when the connection from a browser to the proxy was slower than the connection from the proxy to the backend (that is, most of the time), then when new data was received from the backend and we tried to send it to the client, we sometimes got an error to tell us that the client was not ready. This error was being ignored, so a block of data would be skipped, so the pages you got back would be missing chunks. There's more about the bug here.
While I was at it, I figured that this blog was looking ridiculously dated. So I've fixed that with the Iconic One Wordpress theme, with a few tweaks that I think make it look a bit cleaner.
In order to use this blog as a decent real-world test of rsp, I figured that I should make it as fast as possible. The quickest way to do that was to install Varnish, which is essentially a reverse proxy that caches stuff. You configure it to say what is cachable, and then it runs in place of the web server and proxies anything it can't cache back to it.
I basically used the instructions from Ewan Leith's excellent "10 Million hits a day with Wordpress using a $15 server" post.
So now, this server has:
- rsp running on port 80, proxying everything to port 83.
- varnish running on port 83, caching what it can and proxying the rest to port 81.
- nginx running on port 81, serving static pages and sending PHP stuff to php5-fpm on port 9000.
I've also got haproxy running on port 82, doing the same as rsp -- proxying everything to varnish -- so that I can do some comparative speed tests once rsp does enough for such tests to give interesting results. Right now, all of the speed differences seem to be in the noise, with a run of ab pointed at varnish actually coming out slower than the two proxies.