programming:python:py-prefork-server
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
programming:python:py-prefork-server [2011/01/14 16:46] – jay | programming:python:py-prefork-server [2015/01/04 20:44] – [Downloading] jay | ||
---|---|---|---|
Line 13: | Line 13: | ||
===== Downloading ===== | ===== Downloading ===== | ||
- | You can download this package here: {{: | + | You can download this, or even clone the repository, over at [[https:// |
- | You can also track this project on [[https:// | + | You can also install |
+ | <code bash> | ||
+ | pip install py-prefork-server | ||
+ | </ | ||
+ | **NOTE:** The RPMs are **not** guaranteed to be the latest versions. | ||
+ | |||
+ | {{: | ||
+ | {{: | ||
+ | ===== Donations ===== | ||
+ | By no means should anyone feel they //have// to donate. | ||
+ | |||
+ | < | ||
+ | <form action=" | ||
+ | <input type=" | ||
+ | <input type=" | ||
+ | <input type=" | ||
+ | <img alt="" | ||
+ | </ | ||
+ | </ | ||
+ | ===== Issues and Feature Requests ===== | ||
+ | Please use the bug tracker built in to [[https://github.com/ | ||
+ | |||
+ | ===== Code Contributions ===== | ||
+ | I'm always open to code contributions. | ||
===== Installing ===== | ===== Installing ===== | ||
+ | To manually install the package: | ||
< | < | ||
# tar -xvzf py-prefork-server-X.X.X.tar.gz | # tar -xvzf py-prefork-server-X.X.X.tar.gz | ||
Line 22: | Line 46: | ||
# python setup.py install | # python setup.py install | ||
</ | </ | ||
+ | |||
+ | Or install from PyPI: | ||
+ | < | ||
+ | pip install py-prefork-server | ||
+ | </ | ||
+ | ===== Usage ===== | ||
+ | For the most up to date information: | ||
+ | |||
+ | <code bash> | ||
+ | pydoc preforkserver | ||
+ | pydoc preforkserver.BaseChild | ||
+ | pydoc preforkserver.Manager | ||
+ | </ | ||
+ | |||
+ | For a complete example, see the '' | ||
+ | |||
+ | ==== BaseChild ==== | ||
+ | This is the class you will inherit from when you create your implementation. | ||
+ | <code python> | ||
+ | import preforkserver | ||
+ | |||
+ | class MyChild(preforkserver.BaseChild): | ||
+ | def process_request(self): | ||
+ | # handle the connection here | ||
+ | </ | ||
+ | One important thing to remember is that any instance variables that are set here will have to be done so with the idea that each instance will handle a number of connections (by default, as you can set by the max_requests argument when creating a Manager instance). | ||
+ | |||
+ | === Instance Variables === | ||
+ | There are some class instance variables that are set for your use. You can access these in any of the hooks. | ||
+ | |||
+ | ^ Name ^ Type ^ Description ^ | ||
+ | | self.protocol | str | This will be either " | ||
+ | | self.requests_handled | int | This is the number of requests this child has handled | | ||
+ | | self.conn | socket object or str | The socket object if this is a tcp server, otherwise this will be the actual payload of the udp packet | | ||
+ | | self.address | tuple(str , int) | An address tuple containing (ip , port) | | ||
+ | | self.closed | boolean | A boolean, mainly for internal use, which says whether this child has been set to be closed | | ||
+ | | self.error | str | A string error message, if set | | ||
+ | |||
+ | === Hooks === | ||
+ | == initialize(self) == | ||
+ | Rather than reimplementing __init__, which you can do instead, you can just override this and setup variables and such that you need to set up. This is the recommended approach. | ||
+ | |||
+ | == pre_bind(self) == | ||
+ | This hook is called before the main socket is created and bound to the ip: | ||
+ | |||
+ | == post_bind(self) == | ||
+ | As you might have guessed, this is called right after the '' | ||
+ | |||
+ | == post_accept(self) == | ||
+ | '' | ||
+ | |||
+ | == allow_deny(self) == | ||
+ | You can use this hook to refuse the connection based on the '' | ||
+ | |||
+ | == request_denied(self) == | ||
+ | If you deny the connection in allow_deny(), | ||
+ | |||
+ | == process_request(self) == | ||
+ | This is where you are processing the actual request. | ||
+ | |||
+ | Remember, if this is a udp server, self.conn will be a string with the actual packet payload. | ||
+ | |||
+ | <source python> | ||
+ | def process_request(self): | ||
+ | data = self.conn | ||
+ | self.resp_to(' | ||
+ | </ | ||
+ | |||
+ | == post_process_request(self) == | ||
+ | This is called after the connection is closed. | ||
+ | |||
+ | == shutdown(self) == | ||
+ | This is called when the child is exiting. | ||
+ | |||
+ | Use this to do an pre-close cleanup, like possibly closing open files or a database connection. | ||
+ | |||
+ | ==== Manager ==== | ||
+ | The '' | ||
+ | |||
+ | First, let's take a look at the '' | ||
+ | |||
+ | === The __init__ Signature === | ||
+ | <code python> | ||
+ | def __init__(self , child_class , max_servers=20 , min_servers=5 , | ||
+ | min_spare_servers=2 , max_spare_servers=10 , max_requests=0 , | ||
+ | bind_ip=' | ||
+ | reuse_port=False): | ||
+ | </ | ||
+ | Here is short description of each of those variables. | ||
+ | ^ Name ^ Type ^ Description ^ | ||
+ | | child_class | BaseChild | An implentation of BaseChild to define the child processes | | ||
+ | | max_cervers | int | Maximum number of children that can exist at any time | | ||
+ | | min_servers | int | Minimum number of children to have | | ||
+ | | min_spare_servers | int | Minimum number of spare children to have | | ||
+ | | max_spare_servers | int | Maximum number of spare children to have | | ||
+ | | max_requests | int | Maximum number of requests each child should handle. | ||
+ | | bind_ip | str | The IP address to bind to | | ||
+ | | port | int | The port number to bind to | | ||
+ | | protocol | str | The protocol to use (tcp or udp) | | ||
+ | | listen | int | TCP listen queue backlog | | ||
+ | | reuse_port | bool | If set, and available, SO_REUSEPORT will be used to bind the socket in the child | | ||
+ | For anyone who has set up an Apache prefork server (or used Perl's '' | ||
+ | |||
+ | === Hooks === | ||
+ | Of the following hooks, most, with the exception of the signal hooks, are not going to be very useful to you. The signal hooks can be overridden to perform special actions on a '' | ||
+ | |||
+ | Here they are with a brief description. | ||
+ | |||
+ | == pre_bind(self) == | ||
+ | This hook is called before the main socket is created and bound to the ip: | ||
+ | |||
+ | == post_bind(self) == | ||
+ | As you might have guessed, this is called right after the '' | ||
+ | |||
+ | == pre_signal_setup(self) == | ||
+ | This is called before the signal handlers are set up | ||
+ | |||
+ | == post_signal_setup(self) == | ||
+ | This is called after the signal handlers have been set. You can override the default signal handlers if you like. More on that below. | ||
+ | |||
+ | == pre_init_children(self) == | ||
+ | This is called before the child processes are initialized. | ||
+ | |||
+ | == post_init_children(self) == | ||
+ | This is called after the child processes are initialized. | ||
+ | |||
+ | == pre_loop(self) == | ||
+ | This is the last hook before the main server loop takes over. Any last minute setup items you wish to do should be done here. | ||
+ | |||
+ | == pre_server_close(self) == | ||
+ | This is called before the server shuts down. Any cleanup you wish to take care of before termination should be done here. | ||
+ | |||
+ | == hup_handler(self , frame , num) == | ||
+ | This handles a SIGHUP. | ||
+ | |||
+ | == int_handler(self , frame , num) == | ||
+ | This handles a SIGINT. | ||
+ | |||
+ | == term_handler(self , frame , num) == | ||
+ | By default, this does exactly the same thing as '' | ||
+ | |||
+ | ===== Example ===== | ||
+ | There is a full, working example in the distributions '' |
programming/python/py-prefork-server.txt · Last modified: 2023/11/10 20:06 by jay