使用autbahn.asyncio.wamp非阻塞地运行多个ApplicationSessions

时间:2017-03-01 15:23:48

标签: python python-3.x python-asyncio autobahn wamp-protocol

我正在尝试同时在python中运行两个ComplexTypeModelBinderProvider。以前,我使用this post's answer中建议的修改高速公路库来完成此操作。我现在 需要更专业的解决方案。

在谷歌搜索了一段时间后this post appeared quite promising,但使用了autobahn.asyncio.wamp.ApplicationSession库,而不是twisted。我无法为asyncio库的asyncio分支找到类似的解决方案,因为它似乎没有使用autobahn

我遇到的主要问题是Reactors正在阻塞(这就是我之前将其外包给线程的原因),所以我不能在它之后运行第二个ApplicationRunner.run()

我确实需要同时访问2个websocket频道,单身ApplicationRunner似乎无法做到这一点。

我的代码到目前为止:

ApplicationSession

我对from autobahn.asyncio.wamp import ApplicationSession from autobahn.asyncio.wamp import ApplicationRunner from asyncio import coroutine import time channel1 = 'BTC_LTC' channel2 = 'BTC_XMR' class LTCComponent(ApplicationSession): def onConnect(self): self.join(self.config.realm) @coroutine def onJoin(self, details): def onTicker(*args, **kwargs): print('LTCComponent', args, kwargs) try: yield from self.subscribe(onTicker, channel1) except Exception as e: print("Could not subscribe to topic:", e) class XMRComponent(ApplicationSession): def onConnect(self): self.join(self.config.realm) @coroutine def onJoin(self, details): def onTicker(*args, **kwargs): print('XMRComponent', args, kwargs) try: yield from self.subscribe(onTicker, channel2) except Exception as e: print("Could not subscribe to topic:", e) def main(): runner = ApplicationRunner("wss://api.poloniex.com:443", "realm1", extra={}) runner.run(LTCComponent) runner.run(XMRComponent) # <- is not being called if __name__ == "__main__": try: main() except KeyboardInterrupt: quit() except Exception as e: print(time.time(), e) 库的了解有限,我担心文档不会改善我的情况。我在这里俯瞰什么吗?一个函数,一个参数,它可以让我复合我的组件或同时运行它们吗?

也许是与provided here类似的解决方案,它实现了替代autobahn

相关主题

Running two ApplicationSessions in twisted

Running Autobahn ApplicationRunner in Thread

Autobahn.wamp.ApplicationSession Source

Autobahn.wamp.Applicationrunner Source

如同要求的那样,来自@ stovfl使用ApplicationRunner代码回答的追溯:

multithreading

2 个答案:

答案 0 :(得分:2)

正如我从traceback看到的那样,我们只能达到第4步的第2步

  

来自 asyncio 文档:
  该模块提供了使用协同程序编写单线程并发代码的基础结构,通过套接字和其他资源多路复用I / O访问

所以我使用multithreading删除了我的第一个提案 我可以想象以下三个选项:

  1. 使用multiprocessing代替multithreading
  2. 执行此操作
  3. 使用coroutine
  4. 中的asyncio loop执行此操作
  5. channels
  6. 中的def onJoin(self, details)之间切换

    第二个提案,使用multiprocessing的第一个选项 我可以开始两个asyncio loops,因此appRunner.run(...)应该有用。

    如果class ApplicationSession是唯一的不同,您可以使用一个 channel。 如果您需要传递不同的class ApplicationSession,请将其添加到args=

    class __ApplicationSession(ApplicationSession):
            # ...
            try:
                yield from self.subscribe(onTicker, self.config.extra['channel'])
            except Exception as e:
                # ...
    
    import multiprocessing as mp
    import time
    
    def ApplicationRunner_process(realm, channel):
            appRunner = ApplicationRunner("wss://api.poloniex.com:443", realm, extra={'channel': channel})
            appRunner.run(__ApplicationSession)
    
    if __name__ == "__main__":
        AppRun = [{'process':None, 'channel':'BTC_LTC'},
                  {'process': None, 'channel': 'BTC_XMR'}]
    
        for app in AppRun:
            app['process'] =  mp.Process(target = ApplicationRunner_process, args = ('realm1', app['channel'] ))
            app['process'].start()
            time.sleep(0.1)
    
        AppRun[0]['process'].join()
        AppRun[1]['process'].join()
    

答案 1 :(得分:1)

遵循方法you linked for twisted,通过异步设置 start_loop = False

,我设法获得了相同的行为
import asyncio
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner

runner1 = ApplicationRunner(url, realm, extra={'cli_id': 1})
coro1 = runner1.run(MyApplicationSession, start_loop=False)

runner2 = ApplicationRunner(url, realm, extra={'cli_id': 2})
coro2 = runner2.run(MyApplicationSession, start_loop=False)

asyncio.get_event_loop().run_until_complete(coro1)
asyncio.get_event_loop().run_until_complete(coro2)
asyncio.get_event_loop().run_forever()

class MyApplicationSession(ApplicationSession):

    def __init__(self, cfg):
        super().__init__(cfg)
        self.cli_id = cfg.extra['cli_id']

   def onJoin(self, details):
        print("session attached", self.cli_id)