린스토리

[Python 3.X aiohttp error] "aiohttp.client_exceptions.ServerDisconnectedError: Server disconnected" 해결 본문

Python/API

[Python 3.X aiohttp error] "aiohttp.client_exceptions.ServerDisconnectedError: Server disconnected" 해결

rinaaaLee 2022. 8. 11. 12:33

ML 모델을 Flask를 사용해 RestAPI로 만든 후, 비동기로 다수의 모델을 동시에 돌리고자 비동기모듈을 지원해주는 asyncio와 HTTP 요청을 위한 aiohttp를 활용해 모델을 호출했다. 그런데 한 모델을 호출할 때는 괜찮았는데, 2개 이상의 모델을 호출하고자 하면 제목과 같은 에러가 나오게 됐다. 한 번 모델을 호출했는데 거기에 하나 더 호출하고자 하니 서버 연결이 끊긴다는 건데.. 어떻게 해결하면 되는지 알아보자.


에러를 잡고자 검색을 하니 아래와 같은 설명을 발견했다.

The server could limit the duration of a TCP connection. By default, aiohttp uses HTTP keep-alive so that the same TCP connection can be used for multiple requests. This improves performances since a new TCP connection does not have to be made for each request. However, some servers limit the duration of a TCP connection, and if you use the same TCP connection for many requests, the server can close it before you are done with it. You can disable HTTP keep-alive as a workaround.

부족하지만.. 번역을 해보자면,

우선 aiohttp는 Python 3.4부터 표준 라이브러리로 추가된 asyncio를 위한 HTTP 서버/클라이언트 프레임워크이다. 

디폴트로, aiohttp는 다수의 요청에 같은 TCP 연결을 사용하도록 HTTP를 계속 살려놓는다. 이렇게 하면 각 요청에 TCP 연결을 계속 만들 필요가 없어 성능이 향상된다. 그런데 몇 서버는 TCP 연결 지속을 제한 걸어두어 다수 요청이 들어오면 서버 연결이 끊기는 일이 생기게 된다. 

이럴 때는 HTTP를 계속 살리지 않으면 된다..! 그러면 각 요청에 TCP 연결을 만들겠지..?

 

그래서 에러가 났던 코드는 다음과 같았다.

async def requestss(user_):
    async with aiohttp.ClientSession() as session:
        posting = 'http://127.0.0.1:8081/training'
        print(posting)
        data_ = user_
        async with session.post(posting, data=data_) as resp:
            await asyncio.sleep(5)
            print(await resp.text())
            
tasks = [requestss(user_) for user_ in user_list]
asyncio.run(asyncio.wait(tasks))

 

여기서,

connector = aiohttp.TCPConnector(force_close=True)
async with aiohttp.ClientSession(connector=connector) as session:

이런 방식으로 문제를 해결할 수 있었다.

 

그래서 최종 에러를 해결한 코드는,

async def requestss(user_):
    connector = aiohttp.TCPConnector(force_close=True)
    async with aiohttp.ClientSession(connector=connector) as session:
        posting = 'http://127.0.0.1:8081/training'
        print(posting)
        data_ = user_
        async with session.post(posting, data=data_) as resp:
            await asyncio.sleep(5)
            print(await resp.text())
            
tasks = [requestss(user_) for user_ in user_list]
asyncio.run(asyncio.wait(tasks))

위와 같다.


생각보다 단순하게 해결하게 됐다.

각 모델을 호출하니 문제없이 모델이 돌아간다. 동시에!!

Comments