Gunicorn Transition: add wsgi entrypoint and gunicorn config, bump version to 4.1.41
This commit is contained in:
32
gunicorn_config.py
Normal file
32
gunicorn_config.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Gunicorn 최적화 설정 (Bottleproof v2)
|
||||||
|
import multiprocessing
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 1. 네트워크 설정
|
||||||
|
bind = "0.0.0.0:9099"
|
||||||
|
backlog = 2048
|
||||||
|
|
||||||
|
# 2. 프로세스 관리
|
||||||
|
# GeventWebSocketWorker: SocketIO(WebSocket) 지원을 위해 필수
|
||||||
|
worker_class = "geventwebsocket.gunicorn.workers.GeventWebSocketWorker"
|
||||||
|
workers = 1 # SocketIO 세션 일관성을 위해 1개 권장 (Redis message queue 미사용 시)
|
||||||
|
worker_connections = 1000
|
||||||
|
timeout = 600
|
||||||
|
keepalive = 5
|
||||||
|
|
||||||
|
# 3. PID 관리 (정밀한 프로세스 제어를 위해 추가)
|
||||||
|
pidfile = "data/gunicorn.pid"
|
||||||
|
|
||||||
|
# 4. 로깅 설정
|
||||||
|
# data/log 폴더 자동 생성 보장
|
||||||
|
log_dir = "data/log"
|
||||||
|
if not os.path.exists(log_dir):
|
||||||
|
os.makedirs(log_dir, exist_ok=True)
|
||||||
|
|
||||||
|
accesslog = os.path.join(log_dir, "gunicorn_access.log")
|
||||||
|
errorlog = os.path.join(log_dir, "gunicorn_error.log")
|
||||||
|
loglevel = "info"
|
||||||
|
capture_output = True
|
||||||
|
|
||||||
|
# 5. 개발 편의성
|
||||||
|
reload = False # 운영 환경에서는 False
|
||||||
@@ -319,8 +319,6 @@ class Framework:
|
|||||||
# 이건 필요 없음
|
# 이건 필요 없음
|
||||||
self.config['DEFINE']['GIT_VERSION_URL'] = 'https://raw.githubusercontent.com/flaskfarm/flaskfarm/main/lib/framework/version.py'
|
self.config['DEFINE']['GIT_VERSION_URL'] = 'https://raw.githubusercontent.com/flaskfarm/flaskfarm/main/lib/framework/version.py'
|
||||||
self.config['DEFINE']['CHANGELOG'] = 'https://github.com/flaskfarm/flaskfarm'
|
self.config['DEFINE']['CHANGELOG'] = 'https://github.com/flaskfarm/flaskfarm'
|
||||||
#self.config['DEFINE']['WEB_DIRECT_URL'] = "http://52.78.103.230:49734"
|
|
||||||
|
|
||||||
|
|
||||||
def __process_args(self):
|
def __process_args(self):
|
||||||
# celery 에서 args 처리시 문제 발생.
|
# celery 에서 args 처리시 문제 발생.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
VERSION="4.1.40"
|
VERSION="4.1.41"
|
||||||
|
|||||||
110
restart_gunicorn.sh
Executable file
110
restart_gunicorn.sh
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# FlaskFarm + Celery Gunicorn 정밀 재시작 스크립트 (v2)
|
||||||
|
# "한 번에 정확하게" - PID 기반 제어 및 포트 자동 대기 포함
|
||||||
|
|
||||||
|
cd /Volumes/WD/Users/Work/python/flaskfarm
|
||||||
|
|
||||||
|
# 색상 및 스타일
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
|
||||||
|
echo -e "${YELLOW}${BOLD}========================================${NC}"
|
||||||
|
echo -e "${YELLOW}${BOLD} FlaskFarm Gunicorn Precise Launcher${NC}"
|
||||||
|
echo -e "${YELLOW}${BOLD}========================================${NC}"
|
||||||
|
|
||||||
|
# 1. 환경 및 의존성 검증
|
||||||
|
echo -e "\n${BLUE}[1/5] 환경 및 의존성 검증...${NC}"
|
||||||
|
|
||||||
|
# pyenv 초기화
|
||||||
|
export PYENV_ROOT="$HOME/.pyenv"
|
||||||
|
export PATH="$PYENV_ROOT/bin:$PATH"
|
||||||
|
if command -v pyenv &> /dev/null; then
|
||||||
|
eval "$(pyenv init -)"
|
||||||
|
eval "$(pyenv virtualenv-init -)" 2>/dev/null
|
||||||
|
pyenv rehash
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 필수 패키지 체크 및 버전 강제 (Gunicorn gevent worker 요구사항 대응)
|
||||||
|
PYTHON_EXE=$(which python)
|
||||||
|
if ! $PYTHON_EXE -c "import gevent; from packaging import version; exit(0) if version.parse(gevent.__version__) >= version.parse('24.10.1') else exit(1)" &>/dev/null; then
|
||||||
|
echo -e "${YELLOW} ! gevent 버전 낮음 또는 미설치 감지. 업그레이드를 진행합니다 (>=24.10.1)...${NC}"
|
||||||
|
$PYTHON_EXE -m pip install "gevent>=24.10.1" gevent-websocket gunicorn --upgrade
|
||||||
|
fi
|
||||||
|
echo -e " ✓ Python: $($PYTHON_EXE --version)"
|
||||||
|
echo -e " ✓ Gunicorn: $($PYTHON_EXE -m gunicorn --version | head -n 1)"
|
||||||
|
|
||||||
|
# 2. 기존 프로세스 정밀 종료
|
||||||
|
echo -e "\n${RED}[2/5] 기존 프로세스 종료 중...${NC}"
|
||||||
|
|
||||||
|
# PID 파일 기반 종료 (Gunicorn)
|
||||||
|
PID_FILE="data/gunicorn.pid"
|
||||||
|
if [ -f "$PID_FILE" ]; then
|
||||||
|
OLD_PID=$(cat "$PID_FILE")
|
||||||
|
if ps -p $OLD_PID > /dev/null; then
|
||||||
|
echo " - PID $OLD_PID 종료 시도 (SIGTERM)..."
|
||||||
|
kill -15 $OLD_PID 2>/dev/null
|
||||||
|
sleep 2
|
||||||
|
if ps -p $OLD_PID > /dev/null; then
|
||||||
|
echo " - PID $OLD_PID 강제 종료 (SIGKILL)..."
|
||||||
|
kill -9 $OLD_PID 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 남은 고아 프로세스 정리
|
||||||
|
pkill -9 -f "gunicorn.*wsgi:app" 2>/dev/null
|
||||||
|
echo " ✓ FlaskFarm Gunicorn 프로세스 정리 완료"
|
||||||
|
|
||||||
|
# Celery 워커 종료
|
||||||
|
pkill -9 -f "celery.*worker" 2>/dev/null
|
||||||
|
pkill -9 -f "celery -A flaskfarm" 2>/dev/null
|
||||||
|
echo " ✓ Celery 워커 프로세스 정리 완료"
|
||||||
|
|
||||||
|
# 3. 포트 가용성 확인 (9099)
|
||||||
|
echo -e "\n${BLUE}[3/5] 포트(9099) 상태 확인...${NC}"
|
||||||
|
MAX_WAIT=10
|
||||||
|
COUNT=0
|
||||||
|
while lsof -i :9099 > /dev/null; do
|
||||||
|
if [ $COUNT -ge $MAX_WAIT ]; then
|
||||||
|
echo -e "${RED} ! 포트 9099가 여전히 점유 중입니다. 강제 해제 시도...${NC}"
|
||||||
|
lsof -ti :9099 | xargs kill -9 2>/dev/null
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo " - 포트 해제 대기 중... ($COUNT/$MAX_WAIT)"
|
||||||
|
sleep 1
|
||||||
|
COUNT=$((COUNT+1))
|
||||||
|
done
|
||||||
|
echo " ✓ 포트 9099 사용 가능"
|
||||||
|
|
||||||
|
# 4. Celery 워커 시작 (백그라운드)
|
||||||
|
echo -e "\n${GREEN}[4/5] Celery 워커 시작 중...${NC}"
|
||||||
|
CELERY_LOG_FILE="data/log/celery_worker.log"
|
||||||
|
mkdir -p "data/log"
|
||||||
|
|
||||||
|
export GEVENT_NOWAITPID=1
|
||||||
|
nohup celery -A main.celery worker \
|
||||||
|
--loglevel=info \
|
||||||
|
--pool=gevent \
|
||||||
|
--concurrency=4 \
|
||||||
|
--config_filepath=data/config_mac.yaml \
|
||||||
|
--running_type=local \
|
||||||
|
> "$CELERY_LOG_FILE" 2>&1 &
|
||||||
|
|
||||||
|
echo " ✓ Celery 워커 시작됨 (Log: $CELERY_LOG_FILE)"
|
||||||
|
|
||||||
|
# 5. Gunicorn 정밀 기동
|
||||||
|
echo -e "\n${GREEN}[5/5] Gunicorn 기동...${NC}"
|
||||||
|
echo -e "${YELLOW}========================================${NC}"
|
||||||
|
|
||||||
|
# 프레임워크 우회 환경변수
|
||||||
|
export FF_CONFIG="data/config_mac.yaml"
|
||||||
|
export FF_GUNICORN="true"
|
||||||
|
export FF_REPEAT="0"
|
||||||
|
|
||||||
|
# 실행 (exec을 통해 셸을 gunicorn으로 대체하여 신호 전달 보장)
|
||||||
|
exec $PYTHON_EXE -m gunicorn -c gunicorn_config.py wsgi:app
|
||||||
16
wsgi.py
Normal file
16
wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Gunicorn 환경에서 프레임워크의 argparse 충돌을 방지하기 위한 sys.argv 조작
|
||||||
|
# main.py나 프레임워크 코드를 직접 수정하지 않기 위해 별도의 wsgi entrypoint를 사용합니다.
|
||||||
|
if 'gunicorn' in sys.argv[0] or os.environ.get('FF_GUNICORN') == 'true':
|
||||||
|
config_path = os.environ.get('FF_CONFIG', '.')
|
||||||
|
repeat = os.environ.get('FF_REPEAT', '0')
|
||||||
|
# 프레임워크가 기대하는 인자 형식으로 sys.argv를 재구성
|
||||||
|
sys.argv = [sys.argv[0], '--config', config_path, '--repeat', repeat]
|
||||||
|
|
||||||
|
# 프레임워크의 메인 앱 임포트
|
||||||
|
from main import app, celery
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
34
로그 보는법.md
Normal file
34
로그 보는법.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# FlaskFarm Gunicorn 환경 로그 확인 가이드
|
||||||
|
|
||||||
|
Gunicorn 및 Celery 환경에서 발생하는 로그를 확인하는 방법입니다.
|
||||||
|
|
||||||
|
## 1. 실시간 로그 모니터링 (추천)
|
||||||
|
터미널에서 아래 명령어를 실행하여 실시간으로 로그가 쌓이는 것을 볼 수 있습니다.
|
||||||
|
|
||||||
|
### 웹 서버 (Gunicorn) 로그
|
||||||
|
웹 접속 오류나 서버 상태를 확인할 때 사용합니다.
|
||||||
|
```bash
|
||||||
|
tail -f data/log/gunicorn_error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### 백그라운드 작업 (Celery) 로그
|
||||||
|
다운로드 및 데이터 처리 등 비동기 작업 상태를 확인할 때 사용합니다.
|
||||||
|
```bash
|
||||||
|
tail -f data/log/celery_worker.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### 애플리케이션 통합 로그 (FlaskFarm)
|
||||||
|
플러그인 로직 및 시스템 전반의 상세 로그를 확인할 때 사용합니다.
|
||||||
|
```bash
|
||||||
|
tail -f data/log/framework.log
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 주요 로그 파일 경로
|
||||||
|
모든 로그는 `data/log/` 폴더에 집중되어 있습니다.
|
||||||
|
|
||||||
|
- `data/log/gunicorn_access.log`: HTTP 요청 기록 (방문자 기록)
|
||||||
|
- `data/log/gunicorn_error.log`: Gunicorn 서버 구동 및 에러 기록
|
||||||
|
- `data/log/celery_worker.log`: Celery 워커의 기동 및 작업 로그
|
||||||
|
- `data/log/framework.log`: 애플리케이션 비즈니스 로직 로그
|
||||||
Reference in New Issue
Block a user