Some components of the uWSGI stack require a key-value mapping system.
For example the :doc:`FastRouter<FastRouter>` needs to know which server to contact for a specific request.
In big networks with a lot of nodes manually managing this configuration could be a proper pain in the ass. As uWSGI doesn't want to be a PITA, it implements a subscription system where the node itself announces its presence to Subscription Servers, which will in turn populate their internal dictionaries.
uwsgi --fastrouter :1717 --fastrouter-subscription-server 192.168.0.100:2626
This will run an uWSGI fastrouter on port 1717 and create an empty dictionary where the hostname is the key and the uwsgi address is the value.
To populate this dictionary you can contact 192.168.0.100:2626, the address of the subscription server.
For every key multiple addresses can exist, enabling round robin load balancing.
A node can announce its presence to a Subscription Server using the subscribe-to
option.
uwsgi -s 192.168.0.10:3031 -w myapp -M --subscribe-to 192.168.0.100:2626:uwsgi.it
The FastRouter will map every request for uwsgi.it to 192.168.0.10:3031.
To now add a second node for uwsgi.it simply run it and subscribe:
uwsgi -s 192.168.0.11:3031 -w myapp -M --subscribe-to 192.168.0.100:2626:uwsgi.it
Dead nodes are automatically removed from the pool.
The subscription system is currently available for cluster joining (when multicast/broadcast is not available), the Fastrouter and HTTP.
That said, you can create an evented/fast_as_hell HTTP load balancer in no time.
uwsgi --http :80 --http-subscription-server 192.168.0.100:2626
Now simply subscribe your nodes to the HTTP subscription server.
The subscription system is meant for "trusted" networks. All of the nodes in your network can potentially make one goddamn mess with it.
If you are building an infrastructure for untrusted users or you simply need more control over who can subscribe to a Subscription Server you can use openssl rsa public/private key pairs for "signing" you subscription requests.
# First, create the private key for the subscriber. DO NOT SET A PASSPHRASE FOR THIS KEY.
openssl genrsa -out private.pem
# Generate the public key for the subscription server:
openssl rsa -pubout -out test.uwsgi.it_8000.pem -in private.pem
The keys must be named after the domain/key we are subscribing to serve, plus the .pem extension.
Note
If you're subscribing to a pool for an application listening on a specified port you need to use the domain_port.pem
scheme for your key files. Generally all of the DNS-allowed chars are supported, all of the others are mapped to an underscore.
An example of an RSA protected server looks like this:
[uwsgi]
master = 1
http = :8000
http-subscription-server = 127.0.0.1:2626
subscriptions-sign-check = SHA1:/etc/uwsgi/keys
The last line tells uWSGI that public key files will be stored in /etc/uwsgi/keys.
At each subscription request the server will check for the availability of the public key file and use it, if available, to verify the signature of the packet. Packets that do not correctly verify are rejected.
On the client side you need to pass your private key along with other subscribe-to
options. Here's an example:
[uwsgi]
socket = 127.0.0.1:8080
subscribe-to = 127.0.0.1:2626:test.uwsgi.it:8000,5,SHA1:/home/foobar/private.pem
psgi = test.psgi
Let's analyze the subscribe-to
incantation:
127.0.0.1:2626
is the subscription server we want to subscribe to.test.uwsgi.it:8000
is the subscription key.5
is the modifier1 value for our psgi appSHA1:/home/private/test.uwsgi.it_8000.pem
is the <digest>:<rsa> couple for authenticating to the server (the <rsa> field is the private key path).
Note
Please make sure you're using the same digest method (SHA1 in the examples above) both on the server and on the client.
To avoid replay attacks, each subscription packet has an increasing number (normally the unix time) avoiding the allowance of duplicated packets. Even if an attacker manages to sniff a subscription packet it will be unusable as it is already processed previously. Obviously if someone manages to steal your private key he will be able to build forged packets.