4

クライアントとサーバーを通信させるために、Python 2.7 とzeroRPCを使用しています。クライアントがサーバーにリクエストを送信し、サーバーがリクエストを受信したことを確認するために応答を送信するようにします。しかし、サーバーがその要求に対して重い計算を実行するようにします。これらの計算には数時間かかり、応答がないため、クライアントは待機し続ける必要はありません。サーバーがリクエストを受信したことを確認した直後に、クライアントとサーバーの接続を終了する必要があります。これどうやってするの?

これが(簡略化した)私が今持っているものです。

サーバーコード:

impor time
import zerorpc

class HelloRPC(object):
    def hey(self, name):
        print 'Hey, %s' % name # just so I can check that the request was received
        # send response confirming that request was received
        # terminate connection
        time.sleep(100000000000000) # some heavy computations

s = zerorpc.Server(HelloRPC())
s.bind('tcp://0.0.0.0:4242')
s.run()

クライアントコード:

import zerorpc

c = zerorpc.Client()
c.connect('tcp://MyServerName:4242')
c.hey('macarena')

動作しません: わかりますzerorpc.exceptions.LostRemote: Lost remote after 10s heartbeat。引数を使用して接続を無期限に維持できることはわかっていますが、前述heartbeatしたように、計算には数時間かかり、応答が返されないため、接続を維持する必要はないと思います。

gevent について読んだことがありますが、この目的でそれを使用する方法がわかりません (仕事に適したツールでさえありますか?)。Python の multiprocessing パッケージを使用して、サブプロセスなどを生成する必要がありますか? この種のことについてどうやって行くのですか?

4

1 に答える 1

6

これは、サーバーがハートビートを送り返していないために発生します。メイン スレッドは、非 gevent 協調ループで約 10 秒間ブロックされます (デフォルトのハートビート頻度の 2 倍)。

Gevent はコルーチン (greenlet) を協調的に実行します。コルーチンが gevent ループに戻らない場合、ループはブロックされます。

タスクが CPU バウンドである可能性があります。この場合、CPU のビットを長時間かき回しながら、協調性を維持しようとしています。zerorpc (および gevent) を使用して CPU バウンド コードを実行するには、次の 2 つの方法があります。

  • 定期的に gevent IOLoop に戻ります ( gevent.sleep(0))。デフォルトのハートビートは 5 秒であり、ハートビート周波数の 2 倍の後に切断が想定されるため、安全のためにはおよそ 5 秒ごとに譲歩する必要があります。

  • より一般的な解決策は、CPU バウンド コードを独自のプロセスで実行することです (たとえば、CPU ごとに 1 つのプロセス)。

    • 1 つのプロセスは、ネットワークにアクセスできるサービス API になります (ハートビートが有効になっている zerorpc.Server)。このプロセスは決してブロックされず、協調スケジューリングを尊重します。
    • 集中的な計算のための CPU と同じ数のプロセス。
    • サービス API と CPU バウンド プロセスは zerorpc と通信しますが、今回はハートビートがオフになっています (そしておそらく非常に長いタイムアウト値)。
    • サービス API プロセスでは、CPU バウンド プロセスに対する競合を自分で制御できます。
于 2015-06-23T21:20:25.220 に答える