psyhon 3 asyncio의 효과를 직접 느끼고 싶어요!

9021 단어 Python3asyncio

개시하다


파이썬 3에서 "asyncio"은 벤트로, 비동기 IO의 표준 모듈이다.
이본트로×비동기 I/O는 Nodejs 채택으로 유명합니다.
다중 스레드, 다중 프로세스에서 발생하는 오버헤드가 압축되고 여러 I/O 요청이 동시에 처리되는 아키텍처입니다.
머릿속으로는 그걸 알지만 실제로는 "끝내준다!"나는 이런 실감을 가지고 싶다.
그러나 파이썬 문서에 실린 asyncio 모듈의 샘플은 효과와 장점이 현실적이지 않아 조금만 개조해 실제 효과를 느낄 수 있는 샘플을 만들어 봤다.
aiohttp 실제로 느껴지기도 하지만 아사이언시가 어떻게 사용하는지는 아직 몰라서 해봤어요.

샘플을 만들어 보세요!


asyncio에서는 tcp, up 등 통신 플러그, UNIX 신호, 파이프 처리 등을 비동기적으로 처리할 수 있다.
이번에는 tcp 연결으로 해보겠습니다.

모델


3개의 tcp 서버에 요청을 보내고 결과를 얻은 고객이라는 모델로 샘플을 작성해 봤습니다.

서버측


tcp에서 요청을 기다리고 보내는 내용을 직접 보내는 echo 서버를 만듭니다.
이 때 1s를 기다리십시오. 응답으로 1s가 필요한 서버입니다.
※ 나중에 효과를 측정할 때 이해하기 쉽도록 하기 위해서다.
잼을 github에게 주었다.
※ 사실 코드의 대부분은 파이썬 문서의 샘플입니다

클라이언트


다음 Python 문서의 견본에서 사용합니다.
문서의 예시에서 tcp 연결을 한 번만 실행하기 때문에, 이블라도에서 세 번 호출할 수 있도록 코드를 추가했습니다.
이하의 multiple_request 부분은 그것과 일치한다.asyncio.wait를 사용하여 3개tcp_echo_client를 이식육에 등록합니다.
그리고 나중에 효과를 측정하기 위해
집행을 시작하여 끝날 때까지 시간을 안배하다.
async def tcp_echo_client(message, port, loop):
    """
    async tcp client
    Args:
        message: send strings
        port: send tcp request to 127.0.0.0:port
        loop: event loop
    """
    # Asyncio でコネクションをオープン
    # オープン中は別の処理にスイッチされ別の処理が実行可能
    print("open connection....")
    reader, writer = await asyncio.open_connection('127.0.0.1', port,
                                                        loop=loop)
    # サーバー側にデータ送信
    print('Send: %r' % message)
    writer.write(message.encode())
    # Asyncio でサーバー側からデータ受信
    # データ受信中は別の処理にスイッチされ別の処理が実行可能
    data = await reader.read(3072)
    print('Received: %r' % data.decode())

    # コネクションクローズ
    print('Close the socket')
    writer.close()


async def multiple_request(loop):
    """
    ポート番号 8888, 8889, 8890 にデータ送信する3つのタスクを
    イベントループに登録する

    Args:
        loop: event loop
    """
    tasks = []
    port = 8888
    for i in range(0, LOOP):
        message = 'Hello World! {0}'.format(random.randint(0, 100)) 
        tasks.append(tcp_echo_client(message, port, loop))
        port += 1
    done, pending = await asyncio.wait(tasks)


loop = asyncio.get_event_loop()
start = datetime.datetime.now()
# イベントループにより処理を開始する。
loop.run_until_complete(multiple_request(loop))
end = datetime.datetime.now()
loop.close()
print("execution time: {0}".format(end - start))

효과를 재봤어요.


8888~8890의 포트 번호로 echo 서버 3개를 시작합니다.

asyncio가 아닌 경우


우선, 비asyncio (동기화 연결) 를 측정합니다.
소스가 있다여기..
$ python tcp_echo_client_sync.py
Open: connection....
Send: 'Hello World! 76'
Received: 'Hello World! 76'
Close: tcp socket
Open: connection....
Send: 'Hello World! 96'
Received: 'Hello World! 96'
Close: tcp socket
Open: connection....
Send: 'Hello World! 22'
Received: 'Hello World! 22'
Close: tcp socket
Execution time: 0:00:03.069013
예상한 결과와 같다.
응답에 1s가 필요한 서버와 3회 연결되어 있기 때문에 3s의 실행 시간이 필요합니다.

asyncio의 상황


드디어.
$ python tcp_echo_client_asyncio.py
open connection....
open connection....
open connection....
Send: 'Hello World! 21'
Send: 'Hello World! 55'
Send: 'Hello World! 10'
Received: 'Hello World! 55'
Close the socket
Received: 'Hello World! 21'
Close the socket
Received: 'Hello World! 10'
Close the socket
execution time: 0:00:01.049011
전체 실행시간은 1s!

결과 설명


제가 설명해 드릴게요.
본식육내await에서는 상하문 스위치 등이 발생한다.
하면, 만약, 만약...
8888 포트 처리data = await reader.read(3072)
이본트로에 따라 다음 처리로

8889번 포트 처리data = await reader.read(3072)
이본트로에 따라 다음 처리로

....
8888번부터 시작된 응답 대기는 다른 처리가 막히지 않은 상태에서 실행되기 때문에 시간이 단축되었다.

좋은 웹페이지 즐겨찾기