そのため、Twisted + Stomper を STOMP クライアントとして使用するアプリケーションを用意しました。これは、作業を multiprocessing.Pool のワーカーにファームアウトします。
Pythonスクリプトを使用してこれを起動すると、これは問題なく動作するように見えます。これは(簡略化して)次のようになります。
# stompclient.py
logging.config.fileConfig(config_path)
logger = logging.getLogger(__name__)
# Add observer to make Twisted log via python
twisted.python.log.PythonLoggingObserver().start()
# initialize the process pool. (child processes get forked off immediately)
pool = multiprocessing.Pool(processes=processes)
StompClientFactory.username = username
StompClientFactory.password = password
StompClientFactory.destination = destination
reactor.connectTCP(host, port, StompClientFactory())
reactor.run()
これは展開用にパッケージ化されるので、twistd スクリプトを利用して tac ファイルから実行することにしました。
これが私の非常によく似た tac ファイルです。
# stompclient.tac
logging.config.fileConfig(config_path)
logger = logging.getLogger(__name__)
# Add observer to make Twisted log via python
twisted.python.log.PythonLoggingObserver().start()
# initialize the process pool. (child processes get forked off immediately)
pool = multiprocessing.Pool(processes=processes)
StompClientFactory.username = username
StompClientFactory.password = password
StompClientFactory.destination = destination
application = service.Application('myapp')
service = internet.TCPClient(host, port, StompClientFactory())
service.setServiceParent(application)
説明のために、いくつかの詳細を折りたたんだり変更したりしています。うまくいけば、それらは問題の本質ではありませんでした。たとえば、私のアプリにはプラグイン システムがあり、プールは別のメソッドによって初期化され、その後、プラグインの process() メソッドの 1 つを渡す pool.apply_async() を使用して、作業がプールに委任されます。
したがって、スクリプト (stompclient.py) を実行すると、すべてが期待どおりに機能します。
非デーモン モード (-n) で twist を実行しても、問題なく動作するように見えます。
twistd -noy stompclient.tac
ただし、デーモン モードで実行すると機能しません。
twistd -oy stompclient.tac
アプリケーションは正常に起動しているように見えますが、作業をフォークしようとするとハングします。「ハング」とは、子プロセスが何も要求されず、親 (pool.apply_async() と呼ばれる) がそこに座って応答が返されるのを待っているように見えることを意味します。
私は Twisted + multiprocessing で愚かなことをしていると確信していますが、誰かが私のアプローチの欠陥を説明してくれることを本当に望んでいます。
前もって感謝します!