Skip to main content
 首页 » 编程设计

python之当出现故障或挂起时,如何确保关闭负载均衡器中的所有连接

2025年05月04日11qq号

我正在尝试编写一个简单的负载均衡器。它工作正常,直到其中一台服务器(BalanceServer)不关闭连接然后...... 客户端 (ReverseProxy) 断开连接,但与 BalanceServer 的连接保持打开状态。 我尝试将回调 (#3) 添加到 ReverseProxy.connectionLost 以关闭与其中一台服务器的连接,就像我在服务器断开连接时关闭连接 (clientLoseConnection) 所做的那样,但那时 ServerWriter 为 Null我不能在 #1 和 #2 处终止它


当其中一方断开连接时,如何确保所有连接都关闭?我想当客户端和其中一个服务器都挂起时,这里的某种超时也会很好,但是我如何添加它以便它在两个连接上都有效?


from twisted.internet.protocol import Protocol, Factory, ClientCreator 
from twisted.internet import reactor, defer 
from collections import namedtuple 
 
BalanceServer = namedtuple('BalanceServer', 'host port') 
 
SERVER_LIST = [BalanceServer('127.0.0.1', 8000), BalanceServer('127.0.0.1', 8001)] 
 
def getServer(servers): 
    while True: 
        for server in servers: 
            yield server 
 
# this writes to one of balance servers and responds to client with callback 'clientWrite' 
class ServerWriter(Protocol): 
    def sendData(self, data): 
        self.transport.write(data) 
 
    def dataReceived(self, data): 
        self.clientWrite(data) 
 
    def connectionLost( self, reason ): 
        self.clientLoseConnection() 
 
# callback for reading data from client to send it to server and get response to client again     
def transferData(serverWriter, clientWrite, clientLoseConnection, data): 
    if serverWriter: 
        serverWriter.clientWrite = clientWrite 
        serverWriter.clientLoseConnection = clientLoseConnection 
        serverWriter.sendData(data) 
 
def closeConnection(serverWriter): 
    if serverWriter: #1 this is null 
        #2 So connection is not closed and hangs there, till BalanceServer close it  
        serverWriter.transport.loseConnection() 
 
# accepts clients 
class ReverseProxy(Protocol): 
    def connectionMade(self): 
        server = self.factory.getServer() 
        self.serverWriter = ClientCreator(reactor, ServerWriter) 
        self.client = self.serverWriter.connectTCP( server.host, server.port ) 
 
    def dataReceived(self, data): 
        self.client.addCallback(transferData, self.transport.write,  
                    self.transport.loseConnection, data ) 
 
    def connectionLost(self, reason): 
        self.client.addCallback(closeConnection) #3 adding close doesn't work 
 
 
class ReverseProxyFactory(Factory): 
    protocol = ReverseProxy 
    def __init__(self, serverGenerator): 
        self.getServer = serverGenerator 
 
plainFactory = ReverseProxyFactory( getServer(SERVER_LIST).next ) 
reactor.listenTCP( 7777, plainFactory ) 
reactor.run() 

请您参考如下方法:

您可能想查看 twisted.internet.protocols.portforward 以了解连接两个连接然后断开连接的示例。或者只使用 txloadbalancer甚至不要编写自己的代码。

但是,如果没有任何流量通过它,loseConnection 永远不会强行终止连接。因此,如果您没有应用程序级 ping 或任何数据通过您的连接,它们可能永远不会关闭。 This is a long-standing bug in Twisted.实际上,是存在时间最长的错误。也许您想帮助修复 :)。