多个aiohttp Application()在同一进程中运行? [英] Multiple aiohttp Application()'s running in the same process?

查看:74
本文介绍了多个aiohttp Application()在同一进程中运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

两个 aiohttp.web.Application()对象是否可以在同一进程中运行,例如在不同的端口上?

Can two aiohttp.web.Application() objects be running in the same process, e.g. on different ports?

我看到一堆aiohttp代码示例,例如:

I see a bunch of examples of aiohttp code like:

from aiohttp import web
app = web.Application()
app.router.add_get('/foo', foo_view, name='foo')
web.run_app(app, host='0.0.0.0', port=10000)

我想知道是否有一些等价的地方,可以将多个 web.Applications()配置为同时运行。像这样:

I'm wondering if there's some equivalent where multiple web.Applications() can be configured to run at the same time. Something like:

from aiohttp import web
app1 = web.Application()
app1.router.add_get('/foo', foo_view, name='foo')
app2 = web.Application()
app2.router.add_get('/bar', bar_view, name='bar')
# This is the wishful thinking code:
web.configure_app(app1, host='0.0.0.0', port=10000)
web.configure_app(app2, host='0.0.0.0', port=10001)
web.run_apps()

我的用例是我有现有的python网络框架可以执行这种操作,而我正在构建一个与aiohttp在python 3.6中类似的原型。

My use case is that I have an existing python web framework that does this kind of thing, and I'm building a prototype that's analogous in python 3.6 with aiohttp.

我了解可以运行多个python服务器在例如后面nginx(另请参见 http://aiohttp.readthedocs.io/en/stable/deployment.html );那不是我所追求的。我想探讨两个具有相同asyncio事件循环,在相同python进程中运行,在两个不同端口上运行的aiohttp Web服务器的可能性。

I understand that multiple python servers can run behind e.g. nginx (see also http://aiohttp.readthedocs.io/en/stable/deployment.html); that's not what I'm after. I want to explore the possibility of two aiohttp web servers with the same asyncio event loop, running in the same python process, serving on two different ports.

推荐答案

是的,您可以-只需编写一些包装即可重新实现 run_app

Yes, you can - just write some wrapper with re-implementation of run_app.

这里是一个简单的示例。 run_app 的所有特定于应用程序的部分都移至专用类 AppWrapper MultiApp 仅负责初始化所有已配置的应用程序,继续运行循环并进行清理。

Here is a simple example. All app-specific parts of run_app are moved to the dedicated class AppWrapper. The MultiApp is responsible only for initialize all configured apps, keep running the loop and clean up.

import asyncio
from aiohttp import web


class AppWrapper:

    def __init__(self, aioapp, port, loop):
        self.port = port
        self.aioapp = aioapp
        self.loop = loop
        self.uris = []
        self.servers = []

    def initialize(self):
        self.loop.run_until_complete(self.aioapp.startup())
        handler = self.aioapp.make_handler(loop=self.loop)

        server_creations, self.uris = web._make_server_creators(
            handler, loop=self.loop, ssl_context=None,
            host=None, port=self.port, path=None, sock=None,
            backlog=128)

        self.servers = self.loop.run_until_complete(
            asyncio.gather(*server_creations, loop=self.loop)
        )

    def shutdown(self):
        server_closures = []
        for srv in self.servers:
            srv.close()
            server_closures.append(srv.wait_closed())
        self.loop.run_until_complete(
            asyncio.gather(*server_closures, loop=self.loop))

        self.loop.run_until_complete(self.aioapp.shutdown())

    def cleanup(self):
         self.loop.run_until_complete(self.aioapp.cleanup())

    def show_info(self):
        print("======== Running on {} ========\n".format(', '.join(self.uris)))


class MultiApp:    

    def __init__(self, loop=None):
        self._apps = []
        self.user_supplied_loop = loop is not None
        if loop is None:
            self.loop = asyncio.get_event_loop()
        else:
            self.loop = loop

    def configure_app(self, app, port):
        app._set_loop(self.loop)
        self._apps.append(
            AppWrapper(app, port, self.loop)
        )

    def run_all(self):
        try:
            for app in self._apps:
                app.initialize()
            try:
                for app in self._apps:
                    app.show_info()
                print("(Press CTRL+C to quit)")
                self.loop.run_forever()
            except KeyboardInterrupt:  # pragma: no cover
                pass
            finally:
                for app in self._apps:
                    app.shutdown()
        finally:
            for app in self._apps:
                app.cleanup()

        if not self.user_supplied_loop:
            self.loop.close()

注意:请注意用法内部 aiohttp 的方法,可能会有所更改。

Note: be aware of the use of internal aiohttp's method, that may be subject of change.

现在让我们使用它:

from aiohttp import web

async def handle1(request):
    return web.Response(text='SERVER 1')


async def handle2(request):
    return web.Response(text='SERVER 2')

app1 = web.Application()
app1.router.add_get('/', handle1)

app2 = web.Application()
app2.router.add_get('/', handle2)

ma = MultiApp()
ma.configure_app(app1, port=8081)
ma.configure_app(app2, port=8071)
ma.run_all()

作为旁注,请再想一想为什么需要这个。在几乎所有情况下,去耦都是更好的选择。在同一过程中设置许多端点会使它们彼此依赖。我想到一种情况,它具有良好的推理能力,即内部统计信息/调试端点。

As a side note, think again why you need this. In almost all cases the decoupling is the better choice. Setting many endpoints in the same process make them depend on each other. There's one case that comes to my mind and has "good" reasoning, the internal stats / debug endpoint.

这篇关于多个aiohttp Application()在同一进程中运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆