Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View processes not stopped when streaming with python flask

Tags:

python

flask

I use a simple Flask application with gunicorn's gevent worker to serve server-sent events.

To stream the content, i use:

response = Response(eventstream(), mimetype="text/event-stream")

which streams events from redis:

def eventstream():
    for message in pubsub.listen():
        # ...
        yield str(event)

deployed with:

gunicorn -k gevent -b 127.0.0.1:50008 flaskapplication

But after its used for a while, i have 50 redis connections open, even when no one is connected to the server-sent events stream anymore.

It seems, like the view does not terminate, because gunicorn is non-blocking and pubsub.listen() is blocking.

How can i fix this? Should i limit the number of processes gunicorn may spawn, or should flask kill the view after some timeout? If possible, it should stop the view/redis connections on inactivity, without disconnecting users, who are still connected to the SSE stream.

like image 771
allo Avatar asked Nov 01 '22 23:11

allo


1 Answers

You can run gunicorn with -t <seconds> to specify a timeout for your workers which will kill them if they are silent for a number of seconds, usually 30 is typical. I think this should work for your issue, but not completely sure.

From what I've seen, it seems like you could also rewrite your worker to use Timeout from gevent.

This might look something like the following:

from gevent import Timeout

def eventstream():
    pubsub = redis.pubsub()
    try:
        with Timeout(30) as timeout:
            pubsub.subscribe(channel)
            for message in pubsub.listen():
                # ...
                yield str(event)
    except Timeout, t:
        if t is not timeout:
            raise
        else:
            pubsub.unsubscribe(channel)

This example was helpful for getting a hang of how this should work.

like image 73
Nat Dempkowski Avatar answered Nov 10 '22 14:11

Nat Dempkowski