http통신의 비동기적 구현

codakcodak·2023년 5월 4일
0

코루틴

asyncio,aiohttp의 awaitable객체를 활용하여 코루틴으로 비동기적구현을 한다.

import aiohttp
import time
import asyncio
import os
import threading

async def fetch(session,url):
	#현재의 프로세스id와 쓰레드id를 출력
    print(f"{os.getpid()} process | {threading.get_ident()} url : {url}")
    async with session.get(url) as response:
        result=await response.text()
        return result
    
async def main():
    urls=["https://google.com","https://naver.com"]*10

    async with aiohttp.ClientSession() as session:
        result=await asyncio.gather(*[fetch(session,url) for url in urls])
        
if __name__=="__main__":
    start = time.time()
    asyncio.run(main())
    print("실행시간 :", time.time() - start,"seconds")
$ python async_thread.py
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
실행시간 : 0.5672705173492432 seconds

기본적으로 하나의 프로세스와 하나의 쓰레드를 사용하여 진행된다.

멀티쓰레드

ThreadPoolExecutor를 활용하여 비동기적으로 구현한다.

import requests
import time
import os
import threading
from concurrent.futures import ThreadPoolExecutor

def fetch(params):
    session=params[0]
    url=params[1]
    print(f"{os.getpid()} process | {threading.get_ident()} url : {url}")
    with session.get(url) as response:
        return response.text

def main():
    #max_workers는 최대 쓰레드 갯수
    #멀티쓰레드를 사용할 경우 우선순위와 쓰레드의 공간을 만드는 자원이 소비되어 코루틴으로 비동기구현보다 느릴 수 있다.
    executor=ThreadPoolExecutor(max_workers=5)
    urls=["https://google.com","https://naver.com"]*10

    with requests.Session() as session:
        # result=[fetch(session,url) for url in urls]
        params=[(session,url) for url in urls]
        result=list(executor.map(fetch,params))

if __name__=="__main__":
    start = time.time()
    main()
    print("실행시간 :", time.time() - start,"seconds")
$ python multi_thread.py
12008 process | 29332 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 28144 url : https://google.com
12008 process | 13928 url : https://naver.com
12008 process | 30116 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 13928 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 12032 url : https://google.com
12008 process | 29332 url : https://naver.com
12008 process | 28144 url : https://google.com
12008 process | 30116 url : https://naver.com
12008 process | 29332 url : https://google.com
12008 process | 30116 url : https://naver.com
12008 process | 30116 url : https://google.com
12008 process | 13928 url : https://naver.com
12008 process | 13928 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 12032 url : https://google.com
12008 process | 28144 url : https://naver.com
실행시간 : 1.5067389011383057 seconds

workers에서 설정한 5개가 출력결과를 살펴보면 일치함을 알 수 있다.실행시간을 살펴보면 처음의 코루틴과 비교하면 느리다는 것을 알 수 있는데 이는 쓰레드풀의 생성 및 관리를 위한 시간이 들기때문에 느린 것이다.그리고 파이썬은 GIL로 인해 멀티쓰레드로 병렬적 처리는 불가능하기 때문에 비동기적으로 구현을 할거면 코루틴을 활용하는 것이 나아보인다.

profile
숲을 보는 코더

0개의 댓글