2

Service があるとします。

import rpyc

class MyService(rpyc.Service):
    my_dict = {}

    def exposed_put(self, key, val):
        MyService.my_dict[key] = val

    def exposed_get(self, key):
        return MyService.my_dict[key]

    def exposed_delete(self, key):
        del MyService.my_dict[key]

ここで、ThreadedServer で実行されている Service を開始します。

from rpyc.utils.server import ThreadedServer
server = ThreadedServer(MyService, port=8000)
server.start()

同じマシンの別のプロセスで、サーバーへの新しい接続を開きます。

import rpyc
c = rpyc.connect('localhost', 8000)

...しかし、接続のルートにアクセスする前に、サーバープロセスの制御端末で Ctrl-Z などの理由でサーバープロセスが停止します。今、次の方法でルートにアクセスしようとすると:

c.root

... Python がハングします。クライアント側で Ctrl-C を実行すると、次のようになります。

In [31]: c.root
^C---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-31-856a441cc51a> in <module>()
----> 1 c.root

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/protocol.pyc in root(self)
    465         """Fetches the root object (service) of the other party"""
    466         if self._remote_root is None:
--> 467             self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
    468         return self._remote_root
    469

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/protocol.pyc in sync_request(self, handler, *args)
    436         seq = self._send_request(handler, args)
    437         while seq not in self._sync_replies:
--> 438             self.serve(0.1)
    439         isexc, obj = self._sync_replies.pop(seq)
    440         if isexc:

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/protocol.pyc in serve(self, timeout)
    385                   otherwise.
    386         """
--> 387         data = self._recv(timeout, wait_for_lock = True)
    388         if not data:
    389             return False

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/protocol.pyc in _recv(self, timeout, wait_for_lock)
    342             return None
    343         try:
--> 344             if self._channel.poll(timeout):
    345                 data = self._channel.recv()
    346             else:

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/channel.pyc in poll(self, timeout)
     41     def poll(self, timeout):
     42         """polls the underlying steam for data, waiting up to *timeout* seconds"""
---> 43         return self.stream.poll(timeout)
     44     def recv(self):
     45         """Receives the next packet (or *frame*) from the underlying stream.

/home/mack/anaconda/lib/python2.7/site-packages/rpyc/core/stream.pyc in poll(self, timeout)
     39             while True:
     40                 try:
---> 41                     rl, _, _ = select([self], [], [], timeout)
     42                 except select_error as ex:
     43                     if ex[0] == errno.EINTR:

KeyboardInterrupt:

そのため、サーバー プロセスが停止していても接続されている (基になるソケットがまだ開いている) 場合、Stream.pollへの呼び出しは無限ループで終了するようです。これは Stream の実装では予期しないケースであると考えるのは正しいですか? バージョン 3.3.0 を使用しています。このケースを検出し、クライアントのハングを回避するにはどうすればよいですか?

4

1 に答える 1

2

サーバーが引っ張られるリスクがある場合は、c.closedクライアント側でコールバック関数を提供して、サーバーが閉じたことを通知し、名前を付けて初期化子に渡すこともできる値を確認してから、on_exit登録することができますatexitでそれ。

サーバーが一時停止している、またはリモートでビジーであるというリモートの可能性に対処するには、ハートビート、つまりサーバーが利用可能であることをクライアントに通知する定期的なコールバックを実装する必要があります。

于 2015-12-20T06:56:38.410 に答える