扭曲为客户端/服务器问题

时间:2011-05-05 15:06:07

标签: python client twisted block

我正在使用twisted创建一个“客户端/服务器”,一个充当客户端以获取某些数据的程序,以及作为服务器重新发送此数据或仅将其他数据发送给客户端。

我正在使用twistd和我的代码初始化我的工厂看起来像这样:

application = service.Application('monitorD', uid=0, gid=0)
factoryMonitord = ServerFactory(p)
internet.TCPServer(9000, factoryMonitord).setServiceParent(service.IServiceCollection(application))
#because I need to send some datas from client factory to clients of serverfactory
factoryScamd = ClientFactory(factoryMonitord)
internet.TCPClient("localhost", 8001, factoryScamd).setServiceParent(service.IServiceCollection(application))

我的问题是当客户端部分无法连接时(因为服务器不可用),它看起来像是“阻塞”我的所有服务器部分。它仍然可以在我的服务器部分和其他客户端之间进行通信,但它真的很慢......(当我的客户端部分可以连接时,它的工作正常)。

提前感谢任何帮助。

编辑:

这是我的ServerFactory代码(很多无用的代码......):

class ServerFactory(protocol.ServerFactory):
    protocol = ServerProtocol

    def __init__(self, portal):
        #self.tp = ClientFactory.tp 
        self.tp = []
        self.portal = portal
        self.loop_vol_raid_areca = LoopingCall(self.checkVolRaidAreca)
        self.loop_vol_raid_areca.start(30)
        self.loop_services = LoopingCall(self.checkServices)
        self.loop_services.start(30)

    def buildProtocol(self, addr):
        p = protocol.ServerFactory.buildProtocol(self, addr)
        p.portal = self.portal
        return p

    def sendList(self, data):
        if data:
            if isinstance(data, list):
                for element in data:
                    if isinstance(element, list):
                        self.clean_data = "".join(element)
                self.sendToClients(self.clean_data)

    def sendToClients(self, data):
        print "SEND to MonitorC from MonitorD, tp:", self.tp
        if data:
            for tp in self.tp:
                self.protocol.sendLine(tp, data)

    def checkServices(self):
        self.scamd = threads.deferToThread(checkScamd)
        self.scamd.addCallback(self.sendToClients)
        self.httpd = threads.deferToThread(checkHttpd)
        self.httpd.addCallback(self.sendToClients)
        self.postgres = threads.deferToThread(checkPostgres)
        self.postgres.addCallback(self.sendToClients)

    def checkVolRaidAreca(self):
        self.vol = threads.deferToThread(check_vol_areca)
        self.vol.addCallback(self.sendList)
        self.event = threads.deferToThread(get_last_event_areca)
        self.event.addCallback(self.sendList)

这是客户端工厂,有很多无用的代码:

class ClientFactory(protocol.ClientFactory):
    protocol = ClientProtocol

    def __init__(self, MonitordFactory):
        self.tp = MonitordFactory.tp

    def clientConnectionFailed(self, connector, reason):
        print "Connection to scamd failed - retrying..."
        time.sleep(30)
        connector.connect()

    def clientConnectionLost(self, connector, reason):
        print "Connection to scamd lost - retrying..."
        time.sleep(30)
        connector.connect()

    def getCamList(self, data):
        cams_list = data.split("\x00")
        self.cams_array = []
        for i in cams_list:
            if str.find(i, "camera") != -1:
                i = i.split(" ")
                i = filter(lambda x: len(x)>0, i)
                self.cams_array.append(i)

    def checkCams(self, data):
        data = data.split(" ")
        for i in self.cams_array:
            if i[1] == data[2]:
                if data[3] == "-1":
                    msg = i[6] + " ERREUR -1"
                if data[3] == "0":
                    msg = i[6] + " ERREUR 0"
                if data[3] == "1":
                    msg = i[6] + " ERREUR 1"
                if data[3] == "2":
                    msg = i[6] + " ERREUR 2 (RECO)"
        return msg

如果需要更多信息,我会将整个代码发布到pastebin。 并且,我是python的新手并且扭曲了(但我习惯用C或C ++编写代码)

1 个答案:

答案 0 :(得分:1)

你应该能够立即改变两件事。摆脱time.sleep(30)电话。此外,您正在大量使用线程池,因此您可能希望增加它的大小。你每30秒创建5个线程,并且因为反应堆线程池大小默认为5,你创建的任何其他线程最终都会在那些线程后面等待5.我认为让一堆排队的线程等待可能就是为什么你的服务运行缓慢甚至出现阻塞。

在短期内,您可以在ServerFactory中创建自己的twisted.python.threadpool.Threadpool

class ServerFactory(protocol.ServerFactory):
    protocol = ServerProtocol

    def __init__(self, portal):
        # ...
        self.threadpool = ThreadPool(25, 50)

    def checkServices(self):
        # ...
        self.postgres = threads.deferToThreadPool(reactor, self.threadpool, checkPostgres)

但是,从长远来看,您应该考虑使用异步API来处理您的服务。

例如,您可以使用twisted.web.client.Agent使checkHttpd代码异步。对于PostgreSQL,您可以使用txPostgres。我不熟悉您的scamd服务,因此使用异步IO连接它可能会更困难(例如:您可能必须为该服务编写协议的异步版本)。