최근 작업요청이 많아지는 것 같더니, 다량의 호출로 인해 Database 접근 오류가 발생하였다.
오류내용은 다음과 같다.
QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30.00 (Background on this error at: https://sqlalche.me/e/14/3o7r)
원인을 확인해보면, 실제 Database 자체에 부하가 아닌 Database와 연결을 해주는 Connection 부분이 Overflow 오류이다.
즉 메세지 내용대로 Database에 접근할 수 있는 연결 가능 수가 5 개이고 대기 가능수가 10개인데 이 수치를 넘어가면서 더이상 연결을 할 수 없는 문제가 발생한 것이다.
대부분 Database하고 Connection은 특정한 갯수로 연결하여 관리하는데, 과도한 요청이 발생하면 이와같이 연결 오류가 발생할 수 있다.
이 오류를 해결하기 위해서는 2가지를 진행하는 것을 추천한다.
1. Database Connection Size 올리기
가장 기본적으로 해야 하는 부분으로 Database의 연결할 수 있는 Connection 수를 기존 보다 늘리는 방향이다.
engine = create_engine("mysql://u:p@host/db", pool_size=10, max_overflow=20)
필자의 Database init 함수 부분에 추가한다면 아래와 같이 추가 하여 기본 연결 수와 최대 대기수를 늘릴 수 있다.
def init_app(self, databasename, app: FastAPI, **kwargs):
"""
DB 초기화 함수
"""
self._engine = create_engine(
database,
echo=db_echo,
pool_recycle=900,
pool_pre_ping=True,
pool_size=10,
max_overflow=20
)
self._session = sessionmaker(autocommit=False, autoflush=False, bind=self._engine)
아래 문서에서도 보면, 보다 자세한 설정 방법을 알 수 있다.
Error Messages — SQLAlchemy 1.4 Documentation
2. 연결 시도 자체에 대한 지연 연결 구성
추가로 Database의 연결할 수 있는 Connection 수로 문제를 해결 할 수 있지만, 과도한 Connection 설정으로 실제 Database에 많은 연결이 있을 경우 Database가 처리하지 못하는 경우까지 갈 수 있다. 따라서 연결 시도 자체에 지연을 줄 수 있도록 구성하면 효과적이다.
Python 코드로 지연 코드를 작성해 본다면, 위 Connection 설정을 적절하게 변경한후 오류가 발생하였을 때, 대기 시간을 주는 방식이다.
아래는 필자의 FastAPI의 db session을 설정하는 부분이다.
def get_db(self):
"""
요청마다 DB 세션 유지 함수
:return:
"""
if self._session is None:
raise Exception("must be called 'init_app'")
db_session = None
is_error = True # 데이터 베이스에서 오류가 있는 경우 재시도 할 수 있도록 함
retry_count = 0
while is_error:
try:
db_session = self._session()
is_error = False
yield db_session
except Exception:
if retry_count > 5:
is_error = False # 무한 시도 방지
time.sleep(1.5)
retry_count += 1
finally:
db_session.close()
이외에도 호출 부분에서도 적절한 유휴타임을 준다면 보다 효과적으로 Database 접근 부하를 줄일 수 있을 것이다.
'Python' 카테고리의 다른 글
Python - 코루틴과 이벤트루프 이해 정리 (0) | 2024.03.25 |
---|---|
Python - 멀티 쓰레드(thread) 이해 (0) | 2024.03.25 |
Python - GIL, 멀티 쓰레드(thread) vs 멀티 프로세스(multiprocessing, subprocess) (0) | 2024.03.25 |
Python - *args와 **kwargs 이해 (0) | 2024.03.25 |
Python - JSON 데이터 검색 및 불러오기(dumps, loads, items) (0) | 2024.03.25 |