3

simpleXMLRPC サーバーに問題があります。私のプログラムには、別のサーバーから到達可能なサーバーがあります。サーバーを simpleXMLServer のインスタンスを持つコンピューターと呼び、クライアントを他のサーバーと呼びましょう。

したがって、クライアントがサーバーに接続すると、サーバーはサーバー内の関数を呼び出します。この関数は、実行に時間がかかり (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 のインスタンスです)。神経節の)。それはクライアントのコードです:

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という例外を除いて同じエラーが発生します。

そして、私が何をしても、このサーバーを再度呼び出すと、最初にこのエラーが発生した後に常にこのエラーが発生し、応答がまったくありません。私はそれに対処する方法がわかりません。私はそれで数日間立ち往生しています...

誰でも私を助けてくれませんか?

ありがとう

4

2 に答える 2

0

基本的に、クライアントの接続を強制終了しているため、サーバーは接続が終了したと報告しています。

その後応答がない理由はわかりませんが、考慮すべきことの 1 つは、サーバーがシングルスレッドであるため、低速な操作が進行中の間、他の接続を処理できないことです。

また、シグナルは への呼び出しと同じスレッドに配信されsignal()ない可能性があるため、問題が発生する可能性があることに注意してください。Python が舞台裏で何らかの魔法をかけて正しいスレッドに確実に通知されるようにしない限り、問題が発生する可能性があります。同様に、例外のスローが普遍的に許可されているかどうかはわかりません。確かに、C からは、常にメイン スタック上にあると期待するべきではありません。

于 2011-07-19T10:44:23.793 に答える
0

クライアント マシンでも simpleXMLRPC サーバーを実行し、元のサーバーにワーカー スレッドとキューを実装してみませんか。元のサーバーは引数をキューにプッシュし、すぐに戻ります。ワーカー スレッドはキューで待機し、データが利用可能になると実行されます。完了すると、クライアントからの呼び出しを受け取ったときとまったく同じ方法で、データをリモート プロシージャ コールの引数としてクライアントに送り返します。

このようにすることは、クライアントもサーバーもブロックしないことを意味します。

于 2013-10-03T10:15:38.123 に答える