2017-06-30 16 views
6

दो aiohttp.web.Application() ऑब्जेक्ट्स एक ही प्रक्रिया में चल रहे हैं, उदा। विभिन्न बंदरगाहों पर? कुछ बराबर जहां कई web.Applications() एक ही समय में चलाने के लिए विन्यस्त किया जा सकता है या नहींएकाधिक aiohttp एप्लिकेशन() एक ही प्रक्रिया में चल रहा है?

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) 

मैं सोच रहा हूँ:

मैं की तरह aiohttp कोड के उदाहरण के एक झुंड को देखते हैं। की तरह कुछ:

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

मेरे उपयोग के मामले कि मैं एक मौजूदा अजगर वेब रूपरेखा कि बात इस तरह का होता है है है, और मैं एक प्रोटोटाइप है कि aiohttp साथ अजगर 3.6 में अनुरूप है निर्माण कर रहा हूँ।

मैं समझता हूं कि एकाधिक पायथन सर्वर पीछे चल सकते हैं उदा। nginx (http://aiohttp.readthedocs.io/en/stable/deployment.html भी देखें); यह वह नहीं है जो मैं कर रहा हूं। मैं एक ही पायथन प्रक्रिया में चल रहे एक ही एसिन्सीओ इवेंट लूप के साथ दो एआईओटीपी वेब सर्वरों की संभावना का पता लगाना चाहता हूं, जो दो अलग-अलग बंदरगाहों पर काम करता है।

उत्तर

5

हाँ, आप कर सकते हैं - बस run_app के पुन: कार्यान्वयन के साथ कुछ रैपर लिखें।

यहां एक साधारण उदाहरण है। run_app के सभी ऐप-विशिष्ट हिस्सों को समर्पित कक्षा AppWrapper पर ले जाया गया है। MultiApp केवल सभी कॉन्फ़िगर किए गए ऐप्स को प्रारंभ करने के लिए ज़िम्मेदार है, लूप को चालू रखें और साफ़ करें।

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 की पद्धति के उपयोग, कि बदलाव का विषय हो सकता बारे में पता होना। ,

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

एक पक्ष नोट के रूप में फिर से सोचो कि आपको यह की जरूरत है:

अब इसका इस्तेमाल करते हैं। लगभग सभी मामलों में decoupling बेहतर विकल्प है। एक ही प्रक्रिया में कई अंतराल सेट करना उन्हें एक-दूसरे पर निर्भर करता है। एक ऐसा मामला है जो मेरे दिमाग में आता है और इसमें "अच्छा" तर्क है, आंतरिक आंकड़े/डीबग एंडपॉइंट।

1

हालांकि इसके बाद के संस्करण जवाब स्वीकार किया गया है, यहाँ एक एक और तरीका है:

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

टर्मिनल में खुला दो टैब:

test.py बनाएँ। एक टैब में, चलाने

python test.py 

अन्य टैब में, चलाने

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

आप प्रतिसाद मिलेगा

"App1 OK" 
"App2 OK" 
संबंधित मुद्दे