使用bottle和gevent.wsgi响应客户端断开连接?

时间:2013-11-21 01:38:13

标签: python wsgi bottle gevent

我使用bottlegevent.wsgi实现了一个小型异步服务器。有一个例程用于实现长轮询,看起来很像bottle documentation中的“事件回调”示例:

def worker(body):
  msg = msgbus.recv()
  body.put(msg)
  body.put(StopIteration)

@route('/poll')
def poll():
  body = gevent.queue.Queue()
  worker = gevent.spawn(worker, body)
  return body

此处,msgbus是ZMQ sub套接字。

这一切都运行正常,但是如果客户端断开连接的话 worker上已阻止msgbus.recv(),绿色任务将挂起 围绕“永远”(好吧,直到收到消息),并且只会 找到有关断开连接的客户端尝试发送时的信息 响应。

如果我不想阻止,我可以使用msgbus.poll(timeout=something) 永远等待ipc消息,但我仍然无法检测到客户端 断开。

想要做的事情就是获得类似客户端的引用 套接字,以便我可以在某种selectpoll循环中使用它, 或者在我的greenlet中获得某种异步通知,但是 我不确定如何使用这些完成这些任务 框架(瓶子和gevent)。

有没有办法通知客户断开连接?

1 个答案:

答案 0 :(得分:1)

啊哈! wsgi.input变量(至少在gevent.wsgi下)具有rfile成员,该成员是类似文件的对象。 WSGI spec似乎不需要这样做,因此它可能不适用于其他服务器。

通过这个,我能够修改我的代码,看起来像:

def worker(body, rfile):
  poll = zmq.Poller()
  poll.register(msgbus)
  poll.register(rfile, zmq.POLLIN)

  while True:
    events = dict(poll.poll())

    if rfile.fileno() in events:
      # client disconnect!
      break

    if msgbus in events:
      msg = msgbus.recv()
      body.put(msg)
      break

    body.put(StopIteration)

@route('/poll')
def poll():
  rfile = bottle.request.environ['wsgi.input'].rfile
  body = gevent.queue.Queue()
  worker = gevent.spawn(worker, body, rfile)
  return body

这很有效......

...除OpenShift外,您必须使用。{ 端口8000上的alternate frontend,支持websockets。