A basic random-per-request load balancer
Let's go through the pieces necessary to create our random-per-request load balancer.
A quick note about the code in this chapter: Because we won't be using any packages outside of the standard library, programs listed here won't include the
package main line nor the imports.
goimports tool will allow you to automatically add those sections to your code.
The first thing we will need is someplace to store our state. We have two servers we will be pointing at, and these servers' structs will both be storing their reverse proxy information.
We'll also need the ratio of how many requests we want to go to one versus the other. And because we are choosing randomly, we can include our random seed in all of this state.
So create a new directory for our canary deployment server, and then we can start our
load_balancer.go file like this.
NewServer is a helper method that'll make it easier for us to set up backends in the future.
This code notably uses
httputil, which is in the
"net/http/httputil" standard library package. We're using this so we don't have to write our own reverse proxy. Even though that might be fun, there are a number of RFCs (RFC 7230 and RFC 2616) that determine what headers need to be stripped from the request, among other things that we probably want to let someone else handle for us. If you want to see what you're missing, check out the
httputil.ServeHTTP method from the Go standard library.
Now that we have our state handled, we need to determine how to choose the right server to send each request to. Since we'll assume we always have two servers available, we only have to choose a random number, see if it is greater than our ratio, and use that to determine what server to send it to. It ends up looking like this.
With that out of the way, actually handling the request becomes easy. We choose a server, and then we reverse proxy the request to it.
Now that we have all the pieces, we can glue them together with a
main function. It has flags for the URLs of our servers which are used as parameters to the
NewServer function to create our reverse proxies. Then we can create our load balancer with the servers and start it up.
That gives us this:
And that's it!
Making sure it works#
Now that we have the code written, we should make sure it works. To do that, we need to have two servers to test with, and we'll need to start our load balancer, and then send the requests.
Let's create a new file in a different directory for this test, since it will need its own
main function to run it all. Call the directory
test, and the file
Start by creating the server functions we need to test with in our
These servers are very simple. They accept any request to any path and return whatever message we set them up with.
For convenience, this method will also run the server. However, that means we will need to run this method in a Go routine, by prepending
go to it, otherwise we would never get past the server starting up.
Now that the servers are made, we will need to run our load balancer. We can do that with the handy
exec package, which will allow us to use shell commands, including
go build. So we can build our load balancer binary, wait for that to finish, and then run it.
We will also need to run our load balancer asynchronously, because we still need to send requests to it. It will take some time for the load balancer to start up, so we'll throw a sleep in there too.
Setting up our servers and load balancer looks like this.