简体   繁体   English

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

[英]Twisted as a client/server problems

I'm using twisted to create a "client/server", a programme which act as a client to get some data, and as a server to re-send this data or just to send other data to clients. 我正在使用Twisted创建“客户端/服务器”,该程序充当客户端以获取一些数据,并用作服务器以重新发送此数据或仅将其他数据发送给客户端。

I'm using twistd and my code to initialize my factories look like that: 我正在使用twisted,我的代码初始化工厂如下所示:

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))

My problem is when the client part cannot connect (because server is unavaiable), it's look like it "block" all my server part. 我的问题是客户端部分无法连接(因为服务器不可用)时,它似乎“阻塞”了我所有的服务器部分。 It's still possible to communicate between my server part and other clients but it's really slow... (and when my client part can be connected it's juste work fine). 我的服务器部分和其他客户端之间仍然可以进行通信,但速度确实很慢...(而且当我的客户端部分可以连接时,它就可以正常工作)。

Thanks in advance for anyhelp. 在此先感谢您的帮助。

EDIT: 编辑:

Here's my ServerFactory code (a lot of useless code...): 这是我的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)

And here's the client factory with a lot of useless code: 这是客户端工厂,其中包含许多无用的代码:

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

If more information needed I will post the entire code to pastebin. 如果需要更多信息,我会将整个代码发布到pastebin。 AND, I'm a newbie at python AND twisted (but i used to code in C or C++) 而且,我是python AND twisted的新手(但是我以前用C或C ++编写代码)

There are two things you should be able to change right off the bat. 您应该可以立即改变两件事。 Get rid of the time.sleep(30) calls. 摆脱time.sleep(30)调用。 Also, you're heavily using the threadpool so you'll likely want to increase the size of it. 另外,您正在大量使用线程池,因此可能需要增加线程池的大小。 Every 30 seconds you're creating 5 threads and because the reactor threadpool size defaults to 5 any other threads you create are going to end up waiting behind those 5. I'm thinking that having a bunch of queued up threads waiting may be why your service is running more slowly or even appearing to block. 您每30秒创建5个线程,并且由于反应堆线程池大小默认为5,因此您创建的任何其他线程最终都将在这5个线程之后等待。我在想一堆排队的线程可能在等待您的创建服务运行速度更慢甚至出现阻塞。

In the short term you may just create your own twisted.python.threadpool.Threadpool in your ServerFactory: 短期内,您可以在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)

However, in the long term wherever possible you should look into using an Asynchronous API for dealing with your services. 但是,从长远来看,您应该考虑使用异步API处理服务。

For example, your checkHttpd code could be made asynchronous by using twisted.web.client.Agent . 例如,可以使用twisted.web.client.Agent使您的checkHttpd代码异步。 For PostgreSQL you can use txPostgres . 对于PostgreSQL,您可以使用txPostgres I am not familiar with your scamd service above so connecting to it with asynchronous IO may be more difficult (ie: you may have to write an asynchronous version of the protocol for that service). 我不熟悉上面的scamd服务,因此使用异步IO连接到它可能会更加困难(即:您可能必须为该服务编写协议的异步版本)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM