2016-09-24 20 views
1

我使用aiohttp的最新版本(1.0.2)與python3.5我有以下的服務器代碼python3.5:用aiohttp可以一致地提供幾個響應嗎?

import asyncio 

from aiohttp.web import Application, Response, StreamResponse, run_app 


async def long(request): 
    resp = StreamResponse() 
    name = request.match_info.get('name', 'Anonymous') 
    resp.content_type = 'text/plain' 
    for _ in range(1000000): 
     answer = ('Hello world\n').encode('utf8') 

     await resp.prepare(request) 
     resp.write(answer) 
    await resp.write_eof() 
    return resp 


async def init(loop): 

    app = Application(loop=loop) 
    app.router.add_get('/long', long) 
    return app 

loop = asyncio.get_event_loop() 
app = loop.run_until_complete(init(loop)) 
run_app(app) 

如果我再運行兩個捲曲在不同的終端要求curl http://localhost:8080/long,只有第一個將接收數據

我的想法是,使用asyncio,你可以在一個單線程代碼,開始服務於其他的反應,而在其他正在等待I/O

大部分的代碼我在網上發現了大約concurent + ASYNCIO只有約會談客戶端sid e,但不是服務器端

我錯過了什麼,或者我對asyncio的工作原理有何理解?

回答

2

只需按下await resp.drain()resp.write()後給了aiohttp機會任務之間切換:

import asyncio 

from aiohttp.web import Application, Response, StreamResponse, run_app 


async def long(request): 
    resp = StreamResponse() 
    name = request.match_info.get('name', 'Anonymous') 
    resp.content_type = 'text/plain' 
    await resp.prepare(request) # prepare should be called once 
    for _ in range(1000000): 
     answer = ('Hello world\n').encode('utf8') 

     resp.write(answer) 
     await resp.drain() # switch point 
    await resp.write_eof() 
    return resp 


async def init(loop): 

    app = Application(loop=loop) 
    app.router.add_get('/long', long) 
    return app 

loop = asyncio.get_event_loop() 
app = loop.run_until_complete(init(loop)) 
run_app(app) 
+0

感謝,出於某種原因,我的大腦就開始想'等待resp.prepare(請求)'是事做切換點。然而,用你的代碼,在我的兩個捲髮中,我仍然只有一個接收數據 –

+0

也許原因是:''Hello world \ n''太短,輸出緩衝太大。增加'await asyncio.sleep(0)'將顯式地切換任務。 –

+0

的確,現在我已經添加了'asyncio.sleep(0)'我的2個捲髮正在接收字節(如果我刪除了對'drain'的調用,也可以工作),我應該更喜歡這種解決方案,字節一次發送一次? –

相關問題