Imperial monitors ================= ``dir://`` -- scan a directory for uWSGI config files ----------------------------------------------------- Simply put all of your config files in a directory, then point the uWSGI emperor to it. The Emperor will start scanning this directory. When it finds a valid config file it will spawn a new uWSGI instance. For our example, we're deploying a Werkzeug_ test app, a Trac_ instance, a Ruby on Rails app and a Django_ app. werkzeug.xml .. code-block:: xml werkzeug.testapp:test_app 4 127.0.0.1:3031 trac.ini .. code-block:: ini [uwsgi] master = true processes = 2 module = trac.web.main:dispatch_request env = TRAC_ENV=/opt/project001 socket = 127.0.0.1:3032 rails.yml .. code-block:: yaml uwsgi: plugins: rack rack: config.ru master: 1 processes: 8 socket: 127.0.0.1:3033 post-buffering: 4096 chdir: /opt/railsapp001 django.ini .. code-block:: ini [uwsgi] socket = 127.0.0.1:3034 threads = 40 master = 1 env = DJANGO_SETTINGS_MODULE=myapp.settings module = django.core.handlers.wsgi:WSGIHandler() chdir = /opt/djangoapp001 Put these 4 files in a directory, for instance :file:`/etc/uwsgi/vassals` in our example, then spawn the Emperor: .. code-block:: sh uwsgi --emperor /etc/uwsgi/vassals The emperor will find the uWSGI instance configuration files in that directory (the ``dir://`` plugin declaration is implicit) and start the daemons needed to run them. .. _Werkzeug: http://werkzeug.pocoo.org/ .. _Trac: http://trac.edgewall.org/ .. _Django: http://djangoproject.com/ ``glob://`` -- monitor a shell pattern -------------------------------------- ``glob://`` is similar to ``dir://``, but a glob expression must be specified: .. code-block:: sh uwsgi --emperor "/etc/vassals/domains/*/conf/uwsgi.xml" uwsgi --emperor "/etc/vassals/*.ini" .. note:: Remember to quote the pattern, otherwise your shell will most likely interpret it and expand it at invocation time, which is not what you want. As the Emperor can search for configuration files in subdirectory hierarchies, you could have a structure like this: .. code-block:: sh /opt/apps/app1/app1.xml /opt/apps/app1/...all the app files... /opt/apps/app2/app2.ini /opt/apps/app2/...all the app files... and run uWSGI with: .. code-block:: sh uwsgi --emperor /opt/apps/app*/app*.* ``pg://`` -- scan a PostgreSQL table for configuration ------------------------------------------------------ You can specify a query to run against a PostgreSQL database. Its result must be a list of 3 to 6 fields defining a vassal: 1. The instance name, including a valid uWSGI config file extension. (Such as ``django-001.ini``) 2. A ``TEXT`` blob containing the vassal configuration, in the format based on the extension in field 1 3. A number representing the modification time of this row in UNIX format (seconds since the epoch). 4. The UID of the vassal instance. Required in :ref:`Tyrant` mode only. 5. The GID of the vassal instance. Required in :ref:`Tyrant` mode only. 6. Socket for on demand vassal activation. If specified, vassal will be run in on demand mode. If omitted or empty, vassal will be run normally. Go to :doc:`OnDemandVassals` for more information. .. code-block:: sh uwsgi --plugin emperor_pg --emperor "pg://host=127.0.0.1 user=foobar dbname=emperor;SELECT name,config,ts FROM vassals" * Whenever a new tuple is added a new instance is created and spawned with the config specified in the second field. * Whenever the modification time field changes, the instance is reloaded. * If a tuple is removed, the corresponding vassal will be destroyed. ``mongodb://`` -- Scan MongoDB collections for configuration ------------------------------------------------------------ .. code-block:: sh uwsgi --plugin emperor_mongodb --emperor "mongodb://127.0.0.1:27107,emperor.vassals,{enabled:1}" This will scan all of the documents in the ``emperor.vassals`` collection having the field ``enabled`` set to 1. An Emperor-compliant document must define three fields: ``name``, ``config`` and ``ts``. In :ref:`Tyrant` mode, 2 more fields are required. There is also optional ``socket`` field for on demand vassal mode. * ``name`` (string) is the name of the vassal (remember to give it a valid extension, like .ini) * ``config`` (multiline string) is the vassal config in the format described by the ``name``'s extension. * ``ts`` (date) is the timestamp of the config (Note: MongoDB internally stores the timestamp in milliseconds.) * ``uid`` (number) is the UID to run the vassal as. Required in :ref:`Tyrant` mode only. * ``gid`` (number) is the GID to run the vassal as. Required in :ref:`Tyrant` mode only. * ``socket`` (string) Socket for on demand vassal activation. If specified, vassal will be run in on demand mode. If omitted or empty, vassal will be run normally. Go to :doc:`OnDemandVassals` for more information. ``amqp://`` -- Use an AMQP compliant message queue to announce events --------------------------------------------------------------------- Set your AMQP (RabbitMQ, for instance) server address as the --emperor argument: .. code-block:: sh uwsgi --plugin emperor_amqp --emperor amqp://192.168.0.1:5672 Now the Emperor will wait for messages in the ``uwsgi.emperor`` exchange. This should be a `fanout` type exchange, but you can use other systems for your specific needs. Messages are simple strings containing the absolute path of a valid uWSGI config file. .. code-block:: python # The pika module is used in this example, but you're free to use whatever adapter you like. import pika # connect to RabbitMQ server connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.0.1')) # get the channel channel = connection.channel() # create the exchange (if not already available) channel.exchange_declare(exchange='uwsgi.emperor', type='fanout') # publish a new config file channel.basic_publish(exchange='uwsgi.emperor', routing_key='', body='/etc/vassals/mydjangoapp.xml') The first time you launch the script, the emperor will add the new instance (if the config file is available). From now on every time you re-publish the message the app will be reloaded. When you remove the config file the app is removed too. .. tip:: You can subscribe all of your emperors in the various servers to this exchange to allow cluster-synchronized reloading/deploy. AMQP with HTTP ^^^^^^^^^^^^^^ uWSGI :ref:`is capable of loading configuration files over HTTP`. This is a very handy way to dynamically generate configuration files for massive hosting. Simply declare the HTTP URL of the config file in the AMQP message. Remember that it must end with one of the valid config extensions, but under the hood it can be generated by a script. If the HTTP URL returns a non-200 status code, the instance will be removed. .. code-block:: python channel.basic_publish(exchange='uwsgi.emperor', routing_key='', body='http://example.com/confs/trac.ini') Direct AMQP configuration ^^^^^^^^^^^^^^^^^^^^^^^^^ Configuration files may also be served directly over AMQP. The ``routing_key`` will be the (virtual) config filename, and the message will be the content of the config file. .. code-block:: python channel.basic_publish( exchange='uwsgi.emperor', routing_key='mydomain_trac_config.ini', body=""" [uwsgi] socket=:3031 env = TRAC_ENV=/accounts/unbit/trac/uwsgi module = trac.web.main:dispatch_request processes = 4""") The same reloading rules of previous modes are valid. When you want to remove an instance simply set an empty body as the "configuration". .. code-block:: python channel.basic_publish(exchange='uwsgi.emperor', routing_key='mydomain_trac_config.ini', body='') ``zmq://`` -- ZeroMQ -------------------- The Emperor binds itself to a ZeroMQ PULL socket, ready to receive commands. .. code-block:: sh uwsgi --plugin emperor_zeromq --emperor zmq://tcp://127.0.0.1:5252 Each command is a multipart message sent over a PUSH zmq socket. A command is composed by at least 2 parts: ``command`` and ``name``. ``command`` is the action to execute, while ``name`` is the name of the vassal. 4 optional parts can be specified. * ``config`` (a string containing the vassal config) * ``uid`` (the user id to drop priviliges to in case of tyrant mode) * ``gid`` (the group id to drop priviliges to in case of tyrant mode) * ``socket`` (socket for on demand vassal activation. If specified, vassal will be run in on demand mode. If omitted or empty, vassal will be run normally. Go to :doc:`OnDemandVassals` for more information) There are 2 kind of commands (for now): * ``touch`` * ``destroy`` The first one is used for creating and reloading instances while the second is for destroying. If you do not specify a config string, the Emperor will assume you are referring to a static file available in the Emperor current directory. .. code-block:: python import zmq c = zmq.Context() s = zmq.Socket(c, zmq.PUSH) s.connect('tcp://127.0.0.1:5252') s.send_multipart(['touch','foo.ini',"[uwsgi]\nsocket=:4142"]) ``zoo://`` -- Zookeeper ----------------------- Currently in development. ``ldap://`` -- LDAP ------------------- Currently in development.