1

目前,我有一个有两个服务器的应用程序:第一个处理订单并单独响应,第二个将结果广播给其他感兴趣的订阅者。它们需要从不同的端口提供服务。我可以 start() 他们两个,但我只能得到一个或另一个到 serve_forever() 因为我读到它是一个阻塞函数。我正在寻找有关如何防止两个服务器退出的想法。缩写代码如下:

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

也许我只是需要一种方法来阻止两者退出,但我不确定如何。最后,我希望两台服务器都永远监听传入的连接并处理它们。

4

3 回答 3

2

我知道这个问题有一个公认的答案,但有一个更好的答案。我正在为像我这样以后发现这篇文章的人添加它。

关于服务器的 gevent 文档中所述:

BaseServer.serve_forever() 方法调用 BaseServer.start() 然后等待直到中断或服务器停止。

所以你可以这样做:

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

gevent介绍文档解释了为什么这样做:

与其他网络库不同,尽管以与 eventlet 类似的方式,gevent 在专用的 greenlet 中隐式启动事件循环。没有必须调用 run() 或 dispatch() 函数的反应器。当来自 gevent 的 API 的函数想要阻塞时,它会获取 gevent.hub.Hub 实例——一个运行事件循环的特殊 greenlet——并切换到它(据说 greenlet 将控制权交给了 Hub)。

当 serve_forever() 阻塞时,它不会阻止任一服务器继续通信。

注意:在上面的代码中,交易服务器是决定整个应用程序何时停止的服务器。如果您希望广播服务器决定这一点,您应该在start()andserve_forever()调用中交换它们。

于 2018-08-10T14:25:27.517 回答
1

好的,我可以使用线程和 gevent 的 monkeypatch 库来做到这一点:

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()
于 2013-08-27T12:36:43.950 回答
0

在其自己的 Python 实例中启动每个服务器循环(每个 gevent 一个控制台)。我从来没有理解过试图从一个程序运行多个服务器。您可以多次运行同一台服务器,并使用像 nginx 这样的反向代理来进行负载平衡和相应的路由。

于 2013-08-27T04:37:35.627 回答