2017-06-30 13 views
6

Aynı işlem içinde iki aiohttp.web.Application() nesnesi çalışabilir, örn. farklı limanlarda? Birden web.Applications() aynı anda çalışmasına yapılandırılabilir bazı eşdeğer olup olmadığını merak ediyorumÇoklu aiohttp Uygulama() aynı işlemde mi çalışıyor?

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) 

:

ben gibi aiohttp kod örneklerinden bir demet görüyoruz. gibi bir şey:

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() 

Benim kullanım durumunda ben bu tür şeyleri yapar varolan piton web çerçevesi olması ve ben aiohttp ile piton 3.6 analog olan bir prototip inşa ediyorum.

Birden çok python sunucusunun, ör. nginx (ayrıca bakınız http://aiohttp.readthedocs.io/en/stable/deployment.html); Ben peşindeyim bu değil. İki farklı bağlantı noktasında hizmet veren aynı python işleminde çalışan aynı asyncio olay döngüsüne sahip iki aiohttp web sunucusu olasılığını araştırmak istiyorum.

cevap

5

Evet, yapabilirsin - run_app'un yeniden uygulanmasıyla bir miktar sarıcı yazabilirsin.

İşte basit bir örnek. run_app'un uygulamaya özel tüm parçaları, AppWrapper özel sınıfına taşınır. MultiApp sadece tüm yapılandırılmış uygulamaları başlatmak, döngüyü çalıştırmaya ve temizlemek için sorumludur.

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() 

Not: değişimin tabi olabilir iç aiohttp 'ın yönteminin uygulanmasında dikkat edin.

Şimdi bunu kullanalım: Bir yan not olarak

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() 

, bu neden ihtiyaç tekrar düşünün. Hemen hemen her durumda, dekuplaj daha iyi bir seçimdir. Aynı süreçte birçok uç noktanın ayarlanması, bunların birbirine bağımlı olmasını sağlar. Aklıma gelen ve "iyi" bir akıl yürütme, iç istatistik/hata ayıklama son noktasına sahip olan bir vaka var. Yukarıdaki yanıt kabul edilmiştir rağmen

1

, burada bir başka yaklaşımdır: terminalinde

from aiohttp import web 
import asyncio 
import sys 

@asyncio.coroutine 
def status1(request): 
    return web.json_response('App1 OK') 

@asyncio.coroutine 
def status2(request): 
    return web.json_response('App2 OK') 

def start(): 
    try: 
     loop = asyncio.get_event_loop() 

     # App1 
     app1 = web.Application() 
     app1.router.add_get('/status', status1) 
     handler1 = app1.make_handler() 
     coroutine1 = loop.create_server(handler1, '0.0.0.0', 8081) 
     server1 = loop.run_until_complete(coroutine1) 
     address1, port1 = server1.sockets[0].getsockname() 
     print('App1 started on http://{}:{}'.format(address1, port1)) 

     # App2 
     app2 = web.Application() 
     app2.router.add_get('/status', status2) 
     handler2 = app2.make_handler() 
     coroutine2 = loop.create_server(handler2, '0.0.0.0', 8082) 
     server2 = loop.run_until_complete(coroutine2) 
     address2, port2 = server2.sockets[0].getsockname() 
     print('App2 started on http://{}:{}'.format(address2, port2)) 

     try: 
      loop.run_forever() 
     except KeyboardInterrupt: 
      pass 
     finally: 
      server1.close() 
      loop.run_until_complete(app1.shutdown()) 
      loop.run_until_complete(handler1.shutdown(60.0)) 
      loop.run_until_complete(handler1.finish_connections(1.0)) 
      loop.run_until_complete(app1.cleanup()) 

      server2.close() 
      loop.run_until_complete(app2.shutdown()) 
      loop.run_until_complete(handler2.shutdown(60.0)) 
      loop.run_until_complete(handler2.finish_connections(1.0)) 
      loop.run_until_complete(app2.cleanup()) 

     loop.close() 
    except Exception as e: 
     sys.stderr.write('Error: ' + format(str(e)) + "\n") 
     sys.exit(1) 

if __name__ == '__main__': 
    start() 

açık iki sekme:

test.py oluşturun. bir sekmede, diğer sekmede

python test.py 

çalıştırmak çalıştırmak

curl -X GET http://localhost:8081/status 
curl -X GET http://localhost:8082/status 

Sen tepki alacak

"App1 OK" 
"App2 OK" 
İlgili konular