In the first
part of this two-part tutorial series, we saw to set up and control
Supervisor to work with our web applications. In this part, we will see
how we can programmatically control Supervisor processes remotely via
the XML-RPC API.
A question immediately starts ringing in the brain. What if it were possible to control the Supervisor processes programmatically? This would open up a lot of possibilities where processes can be started or stopped conditionally rather than having them run indefinitely or controlling them manually by clicking buttons or running terminal commands. This is very much possible using the XML-RPC API provided by Supervisor.
To check the current state of the Supervisor server, run:
The server daemon can be restarted and stopped by:
Similarly, the list of all available methods can be fetched by:
The API reference
provided in the Supervisor documentation is pretty clean and
self-explanatory. Going ahead in this tutorial, I will cover an example
of how to control the processes based on a condition, and also how we
can extend this API in order to implement our own methods.
Controlling Processes Using the API
Lets say we want a start a new process to send an email every
time an action is performed by some user. (There are many ways of doing
this, and maybe this is not the best one, but I am just using it as an
example to demonstrate this). Let's say the name of this process as
defined in
Similarly, we can also trigger automatic restarting of the
This API can similarly be applied to countless such instances.
Now I will create a small custom interface for the same in a file named
Above, I have created a method which when called will retry the process three times in case of failure to start.
Getting Started
In the previous part, we saw that Supervisor provides a web-based GUI which allows us to remotely control the processes with the help of a few clicks. Below is a screenshot of this GUI for the application we created in the previous part:A question immediately starts ringing in the brain. What if it were possible to control the Supervisor processes programmatically? This would open up a lot of possibilities where processes can be started or stopped conditionally rather than having them run indefinitely or controlling them manually by clicking buttons or running terminal commands. This is very much possible using the XML-RPC API provided by Supervisor.
The XML-RPC API
The API itself is pretty straightforward and easy to use. We saw that the HTTP server for Supervisor runs on port 9001 by default. The same can be used to connect using any XML-RPC library. In the case of Python, we can simply use the built-inxmlrpclib
. Assuming that the Supervisor server runs on http://localhost:9001/:
1
2
| >>> import xmlrpclib |
1
2
| >>> server.supervisor.getState() { 'statename' : 'RUNNING' , 'statecode' : 1 } |
1
2
| >>> server.supervisor.restart() >>> server.supervisor.shutdown() |
1
| >>> server.system.listMethods() |
Controlling Processes Using the API
Lets say we want a start a new process to send an email every
time an action is performed by some user. (There are many ways of doing
this, and maybe this is not the best one, but I am just using it as an
example to demonstrate this). Let's say the name of this process as
defined in supervisord.conf
is send_mail
.
1
2
| if user.action_performed: server.supervisor.startProcess( 'send_email' ) |
supervisord
server daemon in case we have a code change in our application.
1
2
| if app.code_change(): server.supervisor.restart() |
Extending the XML-RPC API
We can not only use the standard API methods provided by Supervisor but also write our own methods, extending the API by using the XML-RPC interface factories. This can simply be done by adding a new[rpcinterface:x]
section in supervisord.conf
.
1
2
| [rpcinterface:custom] supervisor.rpcinterface_factory = my_interface:make_custom_rpcinterface |
my_interface.py
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
| from supervisor.rpcinterface import SupervisorNamespaceRPCInterface class CustomRPCInterface: def __init__( self , supervisord): self .supervisord = supervisord self .retries = 3 def startProcessOrRetry( self , name, wait = True ): interface = SupervisorNamespaceRPCInterface( self .supervisord) retry = 0 while not interface.startProcess(name) or retry < self .retries: retry = retry + 1 # this is not used in code but referenced via an entry point in the conf file def make_custom_rpcinterface(supervisord): return CustomRPCInterface(supervisord) |
محول الاكواد محول الأكواد اضافة الإبتسمات اضافة الإبتسمات تابع المدونة تابع المدونة