простойXMLRPC серверный питон - PullRequest
3 голосов
/ 18 июля 2011

У меня проблема с сервером simpleXMLRPC.В моей программе есть сервер, доступ к которому можно получить с другого сервера.Давайте назовем server компьютер, на котором есть экземпляр simpleXMLServer, а client другой сервер.

Поэтому, когда клиент подключается к моему серверу, сервер вызывает функцию на сервере.Иногда эта функция может занять много времени (до 5 минут), а затем отправить длинное сообщение.

class Report(object):    
    __instance = None

    def __new__(self):
        if self.__instance is None:
            self.__instance = object.__new__(self)
            self.__instance.__init()
        return self.__instance

    def __init(self):
        self._lastRequestTime = 0
        self._lastRequest     = ''
        self._minInterval     = 1
        self._timeout         = 2
        self.__lock           = Utils.Threading.Lock()
        self.__lockEvent      = Utils.Threading.Lock()
        self._event           = Utils.Threading.Event()
        reportThread = threading.Thread(name   = 'reportThread',
                                        target = self.reportLoop)
        reportThread.start()

    def _reportAll(self):
        tmp = Somewhere.reportAll()
        try:
            self.__lock.acquire()
            self._lastRequest = tmp
        finally:
            self.__lock.release()

    def reportLoop(self):
        while 1:
            self._event.wait()
            self._reportAll()
            try:
                self.__lockEvent.acquire()
                self._event.clear()
            finally:
                self.__lockEvent.release()

    def reportAll(self):
        if abs(Utils.Time.time() - self._lastRequestTime) > self._minInterval or len(self._lastRequest) == 0:
            self._lastRequestTime = time.time()
        else:
            return self._lastRequest

        try:
            self.__lockEvent.acquire()
            self._event.set()    
        finally:
            self.__lockEvent.release()

        try:
            self.__lock.acquire()
            return self._lastRequest
        finally:
            self.__lock.release()

Вот как я создаю сервер:

def startListen(self):
    logging.basicConfig(level = logging.DEBUG)
    try:
        # Create server
        self._server = SimpleXMLRPCServer(("192.168.0.57", 49007), requestHandler=RequestHandler)
        self._server.register_introspection_functions()
        self._server.register_function(Report().reportAll, 'reportAll')
        self._server.serve_forever()
    except:
        return self.restart()

Чтобы избежатьдолгое ожидание на клиентском сервере (что может привести к зависанию клиентской программы), я создал на сервере моего клиента сигнал, который останавливает поток клиента, что бы ни случилось через 5 секунд (мой клиент на самом деле является экземпляром демона gmond of ganglia),Вот код клиента:

def getMessage(self):

    def timeoutHandler(signum, frame):
        raise Exceptions.BFException('Timeout  %d s lasted' % defaultTimeout)

    self._client = None
    msg = None

    # To be sure that will not freeze, we set a signal
    signal.signal(signal.SIGALRM, timeoutHandler)
    signal.alarm(defaultTimeout)

    try:
        self._client = xmlrpclib.ServerProxy('http://192.168.0.57:49007')
        msg = self._client.reportAll() 
    except:
        print 'The connection has not been established'
        self._client = None
        msg = None
    finally:
        signal.alarm(0)
        return msg

Однако, что бы я ни делал, иногда он полностью зависает, и я получаю эту ошибку:

Exception happened during processing of request from ('192.168.0.85', 55417)
Traceback (most recent call last):
  File "C:\Python26\lib\SocketServer.py", line 283, in _handle_request_noblock
    self.process_request(request, client_address)
  File "C:\Python26\lib\SocketServer.py", line 309, in process_request
    self.finish_request(request, client_address)
  File "C:\Python26\lib\SocketServer.py", line 322, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Python26\lib\SocketServer.py", line 617, in __init__
    self.handle()
  File "C:\Python26\lib\BaseHTTPServer.py", line 329, in handle
    self.handle_one_request()
  File "C:\Python26\lib\BaseHTTPServer.py", line 323, in handle_one_request
    method()
  File "C:\Python26\lib\SimpleXMLRPCServer.py", line 491, in do_POST
    self.wfile.write(response)
  File "C:\Python26\lib\socket.py", line 318, in write
    self.flush()
  File "C:\Python26\lib\socket.py", line 297, in flush
    self._sock.sendall(buffer(data, write_offset, buffer_size))
error: [Errno 10053] Une connexion établie a été abandonnée par un logiciel de votre ordinateur hôte

Если я делаю то же самое в дистрибутиве Debian, Я получаю ту же ошибку за исключением того, что я получаю: [Errno 32] Broken Pipe .

И что бы я ни делал, при повторном вызове этого сервера я всегда получаю эту ошибку после получения первоговремя этой ошибки, а ответа нет вообще.Я не знаю, как с этим справиться.Я застрял на несколько дней на этом ...

Может ли кто-нибудь мне помочь, пожалуйста?

Спасибо

Ответы [ 2 ]

0 голосов
/ 03 октября 2013

Почему бы не запустить сервер simpleXMLRPC на клиентском компьютере, а также реализовать исходный сервер с рабочим потоком и очередью.Ваш исходный сервер выдвинет аргументы в очередь и немедленно вернется.Рабочий поток ожидает в очереди и выполняется, когда доступны данные.По завершении он отправляет данные обратно клиенту в качестве аргументов для вызова удаленной процедуры точно так же, как он получил вызов от клиента.

Выполнение этого способа означает, что ни клиент, ниСервер заблокирует.

0 голосов
/ 19 июля 2011

В основном вы убиваете соединение клиента, поэтому сервер сообщает, что соединение было прервано.

Я не уверен, почему вы не получаете ответа после этого, но нужно учитывать, чтосервер является однопоточным, поэтому во время медленной операции никакие другие соединения не могут быть обработаны.

Также обратите внимание, что сигнал может не доставляться в тот же поток, что и вызов signal(), так чтоможет вызвать у вас проблемы, если Python не замаскирует магию, чтобы убедиться, что правильный поток уведомлен.Точно так же я не уверен, что выбрасывание исключения универсально разрешено, конечно, из C, вы не должны ожидать, что всегда будете в главном стеке.

...