HTTP Load Balancer Example [Mongoose]

DZone 's Guide to

HTTP Load Balancer Example [Mongoose]

This article looks at an HTTP load balancer in Mongoose. This is a fairly advanced example that will showcase Mongoose usage as both a server and a client.

· Integration Zone ·
Free Resource

Welcome back to our Mongoose Embedded Web Server examples blog post series! In this edition, we will look at an HTTP load balancer. This is a fairly advanced example that will showcase Mongoose usage as both a server and a client.

As always, you can download Mongoose Embedded Web Server and work through the example yourself.

An HTTP load balancer is a piece of serving infrastructure; an additional stage between a user’s browser and a server that is introduced when there are multiple servers to choose from. Which one should be used to handle client’s request? Load balancer takes the user’s request, makes the decision and forwards it to one of the servers. These are commonly called backends. More advanced load balancers will keep track of the load of the backends and pick the least loaded, but our example load balancer is very basic: it will just alternate between the configured backends. We have two backends configured, the first request will go to backend 1, the second will go to backend 2, the third will go to backend 1 again and so forth.

Example Run-Through

So let’s test it first and then look take a look under the hood. For our example we will need the balancer itself and backends. We will use a restful_server as the backend. We’ll need at least two to see balancing going on, so let’s compile and start two on different ports:

mongoose/examples/restful_server$ make
cc restful_server.c ../../mongoose.c -o restful_server -g -W -Wall -I../.. -Wno-unused-function  -DMG_ENABLE_THREADS -DMG_DISABLE_HTTP_WEBSOCKET -lpthread
mongoose/examples/restful_server$ ./restful_server -p 8910
Starting RESTful server on port 8910, serving .

In another terminal window - ran simultaneously:

mongoose/examples/restful_server$ ./restful_server -p 8911
Starting RESTful server on port 8910, serving .

Use your browser to verify that both backends are working: and should display the “RESTful API demo” index page.

Now compile and run the load_balancer example:

mongoose/examples/load_balancer master$ make
cc load_balancer.c ../../mongoose.c -o load_balancer -W -Wall -pthread
rojer@nbt:~/go/src/cesanta.com/mongoose/examples/load_balancer master$ ./load_balancer -p 8000 -l - -b / -b /
Adding backend for / : [redirect=0,prefix_replacement=/]
Adding backend for / : [redirect=0,prefix_replacement=/]
Starting LB on port 8000

Arguments are documented in the README file, but briefly: -p 8000 tells it to listen for incoming connection on port 8000, -l - sets the log file to “-”, which is a special value for stdout and the two -b options add our backends.

With that done, you should see the same index page when you point your browser to But, each time you reload, the page will be served by a different instance of the backend, and you will see records in the balancer log:

1465822060 GET / backend=
1465822061 GET / backend=
1465822062 GET / backend=

Under the Hood

Now, let’s check out how it works internally. There are a few hundred lines of code in the main file, but as usual, most of the action happens in the event handler (ev_handler). When the client’s request arrives (ev == MG_EV_HTTP_REQUEST), it picks a backend to use, connects to it and forwards the client’s request. When the server responds (ev == MG_EV_HTTP_REPLY), the response is forwarded to the client’s connection. The rest of the code is error handling, dealing with HTTP keep-alive and idle backends.

That’s it for now, we hope this helps you get an idea of how to combine serving and making HTTP requests in the same program.

Test the example for yourself: Download Mongoose

http, load balancer, mongoose

Published at DZone with permission of Deomid Ryabkov , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}