[Web-SIG] Starting Web Servers using socket FDs
Hey I am doing this experimentation where the WGSI server is not started with an host/port or a unix socket, but rather a FD value, corresponding to a socket already bound by the parent process. The server would then just accept new connection on the FD, using socket.fromfd() to get a socket object back, and forget about all the binding work. Here's a prototype based on wsgiref : https://github.com/tarekziade/chaussette The goal I have is to be able to just spawn web workers using subprocess and take care myself of the process management part. I wrote a blog post on my motivations here : http://blog.ziade.org/2012/06/12/shared-sockets-in-circus if you want more background. Anyways, the idea I wanted to bring here was the following: most web servers out there support regular host/port or Unix Socket, which are usually the unix: prefix followed by a path on the system. What if web servers had these two standards *and* a new one which would be a fd: prefix. For instance, we would start server foo with: $ foo --fd:12:localhost:8080 Where 12 is the fd number the foo server would use for getting the socket, and localhost:8080 would just be there as an information to be able to fill some WGSI headers that requires it. From there I could just spawn foo and pass to it socket.fileno() Thoughts ? Cheers Tarek ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
Il giorno 05/giu/2012, alle ore 11:30, Tarek Ziadé ha scritto: Hey I am doing this experimentation where the WGSI server is not started with an host/port or a unix socket, but rather a FD value, corresponding to a socket already bound by the parent process. The server would then just accept new connection on the FD, using socket.fromfd() to get a socket object back, and forget about all the binding work. Here's a prototype based on wsgiref : https://github.com/tarekziade/chaussette The goal I have is to be able to just spawn web workers using subprocess and take care myself of the process management part. I wrote a blog post on my motivations here : http://blog.ziade.org/2012/06/12/shared-sockets-in-circus if you want more background. Anyways, the idea I wanted to bring here was the following: most web servers out there support regular host/port or Unix Socket, which are usually the unix: prefix followed by a path on the system. What if web servers had these two standards *and* a new one which would be a fd: prefix. For instance, we would start server foo with: $ foo --fd:12:localhost:8080 Where 12 is the fd number the foo server would use for getting the socket, and localhost:8080 would just be there as an information to be able to fill some WGSI headers that requires it. From there I could just spawn foo and pass to it socket.fileno() Thoughts ? This is the approach used by fastcgi (even if only on file descriptor 0), old inetd-style daemons, and newer upstart and systemd daemons. Gunicorn can already bind (or better, accept) from file descriptors specifying an environment variable. uWSGI supports by-default the inheritance of file descriptor 0 for fcgi-like startup, and working on generic file descriptor or inet/upstart/systemd socket activation. The vast majority of modern systems expects the file descriptor number on an environment variable: upstart: UPSTART_FDS systemd: LISTEN_FDS Circus, could follow the same behaviour, but i do not know if a standard will be required for that. Regarding the --fd:12:localhost:8080 syntax, is redundant as you can get the name of the socket mapped to a file descriptor with getsockname: http://linux.die.net/man/2/getsockname -- Roberto De Ioris http://unbit.it JID: robe...@jabber.unbit.it ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
On 6/5/12 11:46 AM, Roberto De Ioris wrote: ... Gunicorn can already bind (or better, accept) from file descriptors specifying an environment variable. I don't think you can start gunicorn using a file descriptor, or I failed to do it. The best I was able to do was to create a small wsgi server using Gunicorn as a lib. Gunicorn uses an environment variable when it respawns workers but it does not offer it as a public option as far as I understand how it works uWSGI supports by-default the inheritance of file descriptor 0 for fcgi-like startup, and working on generic file descriptor or inet/upstart/systemd socket activation. I did not find a way to start it using a provided fd -- they are plethora of options though, maybe I missed it The vast majority of modern systems expects the file descriptor number on an environment variable: upstart: UPSTART_FDS systemd: LISTEN_FDS Yes, this seem fairly standard. Circus, could follow the same behaviour, but i do not know if a standard will be required for that. The goal of the standard is just to be able to place any wsgi server out there and have it working out of the box. So far I was not able to run an existing wsgi server like this without changing its code because they all make the assumption they will be run with a host and port. Regarding the --fd:12:localhost:8080 syntax, is redundant as you can get the name of the socket mapped to a file descriptor with getsockname: http://linux.die.net/man/2/getsockname Will look into this again, I had an issue trying to do it. Thanks for the feedback! -- Roberto De Ioris http://unbit.it JID: robe...@jabber.unbit.it ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
On Tue, Jun 5, 2012 at 12:26 PM, Tarek Ziadé ta...@ziade.org wrote: On 6/5/12 11:46 AM, Roberto De Ioris wrote: ... Gunicorn can already bind (or better, accept) from file descriptors specifying an environment variable. I don't think you can start gunicorn using a file descriptor, or I failed to do it. The best I was able to do was to create a small wsgi server using Gunicorn as a lib. Gunicorn uses an environment variable when it respawns workers but it does not offer it as a public option as far as I understand how it works export GUNICORN_FD=your fd and then gunicorn will use this file descriptor when it starts. But it should be possible to pass it directly using a config option if it's needed. - benoît ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
On 6/5/12 11:41 AM, anatoly techtonik wrote: On Tue, Jun 5, 2012 at 12:30 PM, Tarek Ziadéta...@ziade.org wrote: Thoughts ? I've skimmed over the text and couldn't find any user story. What is the end goal? use a web server as a standalone, isolated process, with nothing but a single main thread that gets request then send back response. then have Circus do all the processes management. What is the responsibility of web server, web app and your controlling app? - The web server accept() connections on a socket and transforms a request into a wsgi environ it passes to a wsgi application [Meinheld, Bjoern, Whatever..] - The web app is a classical wsgi application that handles start_response and return a list of strings [the application that follows the wsgi standard] - The controlling app manages the life of the sockets and also manage the life of web app processes [Circus] Who should control keep-alives and connection drops? I don't know I did not get into those details yet. Cheers Tarek ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
On 6/5/12 12:31 PM, Benoit Chesneau wrote: On Tue, Jun 5, 2012 at 12:26 PM, Tarek Ziadéta...@ziade.org wrote: On 6/5/12 11:46 AM, Roberto De Ioris wrote: ... Gunicorn can already bind (or better, accept) from file descriptors specifying an environment variable. I don't think you can start gunicorn using a file descriptor, or I failed to do it. The best I was able to do was to create a small wsgi server using Gunicorn as a lib. Gunicorn uses an environment variable when it respawns workers but it does not offer it as a public option as far as I understand how it works export GUNICORN_FD=your fd and then gunicorn will use this file descriptor when it starts. But it should be possible to pass it directly using a config option if it's needed. What you be great then is to be able to run Gunicorn as a single process without having it forking workers, because the main goal is to be able to manage that process directly in Circus -- e.g. skip all the arbiter part in Gunicorn My attempt at this was this hack : https://github.com/tarekziade/chaussette/commit/075003a24ffe92253da60aafc6f99062e0af267d#diff-3 Cheers Tarek - benoît ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
On 6/5/12 1:56 PM, Roberto De Ioris wrote: uWSGI supports by-default the inheritance of file descriptor 0 for fcgi-like startup, and working on generic file descriptor or inet/upstart/systemd socket activation. I did not find a way to start it using a provided fd -- they are plethora of options though, maybe I missed it it is automatic if the fd is the zero one, otherwise you have to authenticate it adding a --socket/--http-socket/--fastcgi-socket directive mapping to the address (this is required for avoiding uWSGI inheriting unrelated sockets, like the ones created by ssh-agents and whatever you want). For example if you map fd 17 to 192.168.1.1:4040 you have to run uwsgi with --socket 192.168.1.1:4040 it will find fd 17 mapped to a socket, and it will know the socket is authorized to be used. Other components take the special fd://n syntax (like the various routers) but i do not think you are intersted in them Great, thanks, will try this The vast majority of modern systems expects the file descriptor number on an environment variable: upstart: UPSTART_FDS systemd: LISTEN_FDS Yes, this seem fairly standard. Circus, could follow the same behaviour, but i do not know if a standard will be required for that. The goal of the standard is just to be able to place any wsgi server out there and have it working out of the box. if this is your objective i suggest you to follow the inetd/fastcgi style approach and use file descriptor 0 as the communication socket. Flup and uWSGI will work over this automatically. Gunicorn will work simply adding GUNICORN_FD=0 Adding another env-var will mean each server will need to add a condition for that (like upstart and systemd) The thing is, the main process might bind several sockets, and have various subprocesses linked to specific ones, so I guess the uWsgi --socket approach is the most straightforward Thanks for all the info -- Roberto De Ioris http://unbit.it JID: robe...@jabber.unbit.it ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Starting Web Servers using socket FDs
Il giorno 05/giu/2012, alle ore 12:26, Tarek Ziadé ha scritto: On 6/5/12 11:46 AM, Roberto De Ioris wrote: ... Gunicorn can already bind (or better, accept) from file descriptors specifying an environment variable. I don't think you can start gunicorn using a file descriptor, or I failed to do it. The best I was able to do was to create a small wsgi server using Gunicorn as a lib. Gunicorn uses an environment variable when it respawns workers but it does not offer it as a public option as far as I understand how it works benoit has already answered about that uWSGI supports by-default the inheritance of file descriptor 0 for fcgi-like startup, and working on generic file descriptor or inet/upstart/systemd socket activation. I did not find a way to start it using a provided fd -- they are plethora of options though, maybe I missed it it is automatic if the fd is the zero one, otherwise you have to authenticate it adding a --socket/--http-socket/--fastcgi-socket directive mapping to the address (this is required for avoiding uWSGI inheriting unrelated sockets, like the ones created by ssh-agents and whatever you want). For example if you map fd 17 to 192.168.1.1:4040 you have to run uwsgi with --socket 192.168.1.1:4040 it will find fd 17 mapped to a socket, and it will know the socket is authorized to be used. Other components take the special fd://n syntax (like the various routers) but i do not think you are intersted in them The vast majority of modern systems expects the file descriptor number on an environment variable: upstart: UPSTART_FDS systemd: LISTEN_FDS Yes, this seem fairly standard. Circus, could follow the same behaviour, but i do not know if a standard will be required for that. The goal of the standard is just to be able to place any wsgi server out there and have it working out of the box. if this is your objective i suggest you to follow the inetd/fastcgi style approach and use file descriptor 0 as the communication socket. Flup and uWSGI will work over this automatically. Gunicorn will work simply adding GUNICORN_FD=0 Adding another env-var will mean each server will need to add a condition for that (like upstart and systemd) -- Roberto De Ioris http://unbit.it JID: robe...@jabber.unbit.it ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com