How can I keep multiple gevent servers serving forever?
gevent lock example
Currently, I have an application that has two servers: the first processes orders and responds individually, the second broadcasts results to other interested subscribers. They need to be served from different ports. I can start() both of them, but I can only get one or the other to serve_forever() as I read it is a blocking function. I am looking for ideas on how to keep both the servers from exiting. abbreviated code below:
def main(): stacklist =  subslist =  stacklist.append(CreateStack('stuff')) subslist.append(Subscription('stuff')) bcastserver = BroadcastServer(subslist) # creates a new server tradeserver = TradeServer(stacklist) # creates a new server bcastserver.start() # start accepting new connections tradeserver.start() # start accepting new connections #bcastserver.serve_forever() #if I do it here, the first one... #tradeserver.serve_forever() #blocks the second one class TradeServer(StreamServer): def __init__(self, stacklist): self.stacklist = stacklist StreamServer.__init__(self, ('localhost', 12345), self.handle) #self.serve_forever() #If I put it here in both, neither works def handle(self, socket, address): #handler here class BroadcastServer(StreamServer): def __init__(self, subslist): StreamServer.__init__(self, ('localhost', 8000), self.handle) self.subslist = subslist #self.serve_forever() #If I put it here in both, neither works def handle(self, socket, address): #handler here
Perhaps I just need a way to keep the two from exiting, but I'm not sure how. In the end, I want both servers to listen forever for incoming connections and handle them.
I know this question has an accepted answer, but there is a better one. I'm adding it for people like me who find this post later.
As described on in the gevent documentation about servers:
The BaseServer.serve_forever() method calls BaseServer.start() and then waits until interrupted or until the server is stopped.
So you can just do:
def main(): stacklist =  subslist =  stacklist.append(CreateStack('stuff')) subslist.append(Subscription('stuff')) bcastserver = BroadcastServer(subslist) # creates a new server tradeserver = TradeServer(stacklist) # creates a new server bcastserver.start() # starts accepting bcast connections and returns tradeserver.serve_forever() # starts accepting trade connections and blocks until tradeserver stops bcastserver.stop() # stops also the bcast server
The gevent introduction documentation explains why this works:
Unlike other network libraries, though in a similar fashion as eventlet, gevent starts the event loop implicitly in a dedicated greenlet. There’s no reactor that you must call a run() or dispatch() function on. When a function from gevent’s API wants to block, it obtains the gevent.hub.Hub instance — a special greenlet that runs the event loop — and switches to it (it is said that the greenlet yielded control to the Hub).
When serve_forever() blocks, it does not prevent either server from continuing communication.
Note: In the above code the trader server is the one that decides when the whole application stops. If you want the broadcast server to decide this, you should swap them in the
Implementing servers, At this point, any new connection accepted on 127.0.0.1:1234 will result in a new gevent.Greenlet spawned running the handle function. To stop a server use The BaseServer.serve_forever () method calls BaseServer.start () and then waits until interrupted or until the server is stopped. The gevent.pywsgi module contains an implementation of a PEP 3333 WSGI server. In addition, gunicorn is a stand-alone server that supports gevent.
ok, I was able to do this using threading and with gevent's monkeypatch library:
from gevent import monkey def main(): monkey.patch_thread() # etc, etc t = threading.Thread(target=bcastserver.serve_forever) t.setDaemon(True) t.start() tradeserver.serve_forever()
Gevent Tutorial, A switch between the two subtasks is known as a context switch. yield when the main program receives a SIGQUIT may hold the program's execution longer than expected. Gevent provides two WSGI servers for serving content over HTTP. Flask in Production: Gevent Server. Guide from the official documentation. Running app.run on servers is slow. It uses only a single thread and doesn't do any multiplexing. To improve performance, we're going to use gevent.
Start each server loop in its own instance of Python (one console per gevent). I've never understood trying to run multiple servers from one program. You can run the same server many times and use a reverse proxy like nginx to load balance and route accordingly.
Failed to run with gRPC-python · Issue #938 · gevent/gevent · GitHub, Exception gevent.hub.LoopExit: LoopExit('This operation would block forever'. except KeyboardInterrupt: server.stop(0) def run_forever(): Using gevent as a Python WSGI server has one great side-effect: you can spin off greenlets to do background processing whenever you want. Of course, it's also nice to be able to handle thousands of simultaneous connections without seriously taxing your server.
PyWSGI doesn't seem to be stoppable · Issue #613 · gevent/gevent , Is there actually any way to stop the server? from gevent import monkey monkey.patch_all() from gevent import pywsgi import socket def Simple Websocket echo client/server with Flask and gevent / gevent-websocket - flask_geventwebsocket_example.py http_server. serve_forever Raw.
Standalone WSGI Containers, These servers stand alone when they run; you can proxy to them from your web server. Gevent is a coroutine-based Python networking library that uses greenlet to provide a The two problematic values in the WSGI environment usually are Here's a simple nginx configuration which proxies to an application served on This is because libuv doesn't allow multiple watchers for the same file descriptor, unlike libev, so gevent emulates that behaviour at the Python level, and it turns out that there was a bug doing so (when a Python watcher was stopped, it didn't properly update the events libuv was watching for).
pypiserver · PyPI, A minimal PyPI server for use with pip/easy_install. pypiserver 1.3.2 start PyPI compatible package server serving packages from PACKAGES_DIRECTORY. Valid values include paste, cherrypy, twisted, gunicorn, gevent, wsgiref, auto. You can also include this option permanently in your configuration-files or gevent version: 1.1.0 Python version: 2.7.5 Operating System: CentOS Linux release 7.2.1511 (Core) Description: I'm running a Gevent WSGI server with ssl which after serving content for a long time starts to refuse to handle further requ
- the two servers need to share the same internal state
- now we need to ask ourselves if that's a good design decision.
- yes, i agree it isn't ideal. the design requires a broadcast server to publish a subscription based summary of activity over one port, and handle interaction via a different API on another port. I think a database solution wont be fast enough: 000's of messages per second mean polling can't be used. I'd like to eventually daemonize both processes, so if they can be independently started and stopped. This would require some sort of transport link between them. For now, it just works, and running them from the same process helps me develop and test other functionality more quickly.
- rewrote it as separate processes with a socket transport layer. Unfortunately, that took the messages/sec performance down by a factor of 10, but the setup could be useful if the separation is needed, and the performance requirements were lower. Still, I'm glad I explored it, thank you for your input.
- how are you passing data back and forth exactly? raw connections or with a library?