Yes, that’s Zerg as in the “quantity-over-quality” Starcraft race. If you haven’t played Starcraft, be prepared for some nonsense.
Also note that this nonsense is mostly limited to the nomenclature. Zerg Mode is serious business.
When your site load is variable, it would be nice to be able to add workers dynamically.
You can obviously edit your configuration to hike up workers and reload your uWSGI instance, but for very loaded apps this is undesirable, and frankly – who wants to do manual work like that to scale an app?
Enabling Zerg mode you can allow “uwsgi-zerg” instances to attach to your already running server and help it in the work.
If you want an uWSGI instance to be rushed by zerg, you have to enable the Zerg server. It will be bound to an UNIX socket and will pass uwsgi socket file descriptors to the Zerg workers connecting to it.
The socket must be an UNIX socket because it must be capable of passing through file descriptors. A TCP socket simply will not work.
For security reasons the UNIX socket does not inherit the chmod-socket option, but will always use the current umask.
If you have filesystem permission issues, on Linux you can use the UNIX sockets in abstract namespace, by prepending an @ to the socket name.
A normal UNIX socket:
./uwsgi -M -p 8 --module welcome --zerg-server /var/run/mutalisk
A socket in a Linux abstract namespace:
./uwsgi -M -p 8 --module welcome --zerg-server @nydus
To add a new instance to your zerg pool, simply use the –zerg option
./uwsgi --zerg /var/run/mutalisk --master --processes 4 --module welcome # (or --zerg @nydus, following the example above)
In this way 4 new workers will start serving requests.
When your load returns to normal values, you can simply shutdown all of the uwsgi-zerg instances without problems.
You can attach an unlimited number of uwsgi-zerg instances.
By default a Zerg client will not run if the Zerg server is not available. Thus, if your zerg server dies, and you reload the zerg client, it will simply shutdown.
If you want to avoid that behaviour, add a --socket directive mapping to the required socket (the one that should be managed by the zerg server) and add the --zerg-fallback option.
With this setup, if a Zerg server is not available, the Zerg client will continue binding normally to the specified socket(s).
A good trick you can use, is suspending the main instance with the SIGTSTP signal and loading a new version of your app in a Zerg. If the code is not ok you can simply shutdown the Zerg and resume the main instance.
Zergpools are special Zerg servers that only serve Zerg clients, nothing more.
You can use them to build high-availability systems that reduce downtime during tests/reloads.
You can run an unlimited number of zerg pools (on several UNIX sockets) and map an unlimited number of sockets to them.
[uwsgi] master = true zergpool = /tmp/zergpool_1:127.0.0.1:3031,127.0.0.1:3032 zergpool = /tmp/zergpool_2:192.168.173.22:3031,192.168.173.22:3032
With a config like this, you will have two zergpools, each serving two sockets.
You can now attach instances to them.
uwsgi --zerg /tmp/zergpool_1 --wsgi-file myapp.wsgi --master --processes 8 uwsgi --zerg /tmp/zergpool_2 --rails /var/www/myapp --master --processes 4
or you can attach a single instance to multiple Zerg servers.
uwsgi --zerg /tmp/zergpool_1 --zerg /tmp/zergpool_2 --wsgi-file myapp.wsgi --master --processes 8