- #Project
- #Burgerput
Burgerput의 로딩 로직 자동화
Prolip
2024-04-17
cURL과 crontab으로 로딩 로직 자동화하기, ALB idle timeout 설정하기
시작..
저번 포스팅인 Burgerput의 로딩 로직에 이어서 마지막 방법인 cURL과 crontab을 이용한 방법을 기록해보고자 합니다..
세 번째 시도 - cURL과 crontab을 이용하기
“로딩하는 과정을 서버 상에서 자동화 시키는 방법은 없을까? 우리 웹 어플리케이션을 이용하지 않는 시간에 미리 로딩 과정을 거친다면 이용자는 로딩하는 과정을 기다리지 않아도 되고 참 좋을텐데..”
위의 고민을 하다가 이 방법을 최종적으로 채택하게 되었으며 현재도 잘 사용 중입니다.
cURL을 이용해 로딩 요청 보내기
cURL은 client for URLs의 약자로 커맨드 라인 툴 및 URL을 기반으로 데이터를 전송하기 위해 제공되는 라이브러리 입니다.
커맨드 라인, 스크립트에서 데이터를 전송하는 데 사용되며 다양한 프로토콜을 지원합니다.
명령어 사용법
$ curl -option 엔드포인트
위의 형식으로 사용이 가능하며 option은 다음과 같습니다.
short | long | description |
---|---|---|
-X | —request | HTTP method 설정 (GET, POST 등) |
-L | —location | 리다이렉션 따라가기 |
-d | —data | request body에 담을 데이터 설정 POST 요청 등에 사용 |
-H | —header | 헤더 추가 |
-o | —output | 출력 결과를 파일로 저장 |
—max-time | 수행 과정의 총 제한 시간 설정 | |
—connect-timeout | 연결 타임 아웃 설정 | |
-v | —verbose | 동작 과정 출력 |
-k | —insecure | SSL 인증서 무시 |
더 많은 명령어는 man curl을 통해 확인 가능합니다.
이전 포스팅에서 API 엔드포인트를 통해 로딩 요청을 진행한다고 말씀 드렸습니다..
그렇기에 생각한 과정입니다.
- curl을 이용해 get 요청을 시도하면 서버 상에서 로딩이 이루어질 것이다.
- 우리 배포 환경을 생각했을 때 ALB를 이용해 http 요청을 https로 리다이렉트 시키고 있으니 -L 옵션을 통해 리다이렉션을 쫓아야 된다.
위의 고려 사항은 다음과 같이 간단하게 도출 됩니다.
$ curl -L -X GET $API_URL
그런데 이렇게 등록하면 서버에서 로딩이 정상적으로 이루어졌는지 관리자 입장에서 어떻게 판단할까요?
결과를 파일로 저장한다고 한들 로그를 매일 확인하는 것은 매우 불필요한 과정이라고 생각이 듭니다.
로딩 결과를 메일로 받아보기
위의 고민을 끝으로 서버 상에서 로딩 결과를 response body에 담아서 보내주도록 수정했습니다.
로딩이 성공적으로 이루어진다면 true, 혹은 동작 과정에서 에러가 나서 로딩이 실패한다면 false 이런 식으로 말이죠..
그래서 다음 사항들울 고려하며 구현했습니다..
- 서버 상에서 보내주는 response를 이용해 loading 결과를 판단
- 로딩 결과는 현재 시간과 함께 로그 파일에 기록
- 결과를 나와 Yellta씨의 메일로 전송
- 로딩이 만약 실패한다면?
- Selenium의 동작 과정 중 메모리 과부화 등의 이유로 실패한 거라면 재시도를 할만하다고 생각
- MAX_RETRIES 상수를 만들어 최대 횟수를 지정
- RETIRES 변수를 통해 재시도 횟수 기록
- 빠르게 재시도 하다가 에러가 날 수 있으니 약간 대기 시간을 줄까
- 최대 횟수까지 재시도 후 만약 성공하지 못한다면 그 때 메일로 로딩 실패를 알림
#!/bin/bash API_URL=서버 URL LOG_FILE=로그 파일 저장 위치 MAX_RETRIES=3 RETRIES=0 while [ $RETRIES -lt $MAX_RETRIES ] do response=$(curl -L -X GET $API_URL) result=$(echo "$response" | jq -r '.result') current_time=$(date "+%Y-%m-%d %H:%M:%S") # loading 값 확인 if [ "$result" == true ]; then echo "[$current_time] Loading is true. Exiting the loop." >> $LOG_FILE sh Loading_Success.sh > sys.log ssmtp 내 이메일@gmail.com < sys.log ssmtp Yellta씨 이메일@gmail.com < sys.log break else echo "[$current_time] Loading is false. Retrying..." >> $LOG_FILE RETRIES=$((RETRIES + 1)) fi # 일정 시간 대기 후 다음 시도 sleep 5 done if [ $RETRIES -eq $MAX_RETRIES ]; then echo "[$current_time] Reached maximum retries. Exiting without success." >> $LOG_FILE sh Loading_Failed.sh > sys.log ssmtp 내 이메일@gmail.com < sys.log ssmtp Yellta씨 이메일@gmail.com < sys.log fi
그래서 이렇게 작성해봤습니다.
- result를 response에서 할당하는 부분에서 사용된 jq는 커맨드 라인에서 JSON 데이터를 파싱하고 쿼리하는 데 사용되는 도구로 json 형식의 response 데이터에서 result에 해당하는 필드를 추출하려고 사용했습니다.
- while을 통해 실패할 경우 RETIRES를 +1 하며 3회가 될 때까지 실행 시키도록 구현해봤습니다.
- SMTP 서버 구성하기 싫기도 하고 간결하게 로딩 결과만 보낼 생각이기 때문에 ssmtp를 이용했습니다.
- 각 로딩 결과는 Loading_Success, Loading_Failed 쉘 스크립트를 따로 작성해서 사용했습니다.
ssmtp 사용 법은 굳이 적지 않겠습니다.
진짜 쉬워서.. 그냥 gmail 쓰시면 되는데 앱 비밀번호 발급해서 conf 파일에 설정만 하면 됩니다. 대신 첨부 파일은 전송 불가합니다.
자 이제 어떻게 이 기능을 자동화 시켰을까요??
crontab
crontab은 유닉스 계열 시스템에서 특정한 작업을 수행하는 cron을 원하는 주기에 맞게 수행할 수 있도록 설정하는 작업입니다.
여기서 cron은 유닉스 계열 운영체제의 시간 기반 job scheduler 입니다.
날짜, 시간, 심지어 간격까지 직접 고정 시켜 원하는 작업을 주기적으로 실행 시킬 수 있습니다.
기본 명령어는 다음과 같습니다.
Crontab의 명령어 옵션
- -e : 등록, 편집 등의 기능을 수행합니다.
- -l : 현재 crontab에 등록되어 있는 cron 목록을 출력합니다.
- -d : 등록된 cron을 삭제합니다.
- -r : 사용자 이름으로 등록된 cron을 모두 삭제합니다.
기본적인 명령어 옵션만 설명하겠습니다..
저는 매일 오전 8시 35분에 cron이 실행되길 원했습니다.
등록하는 방법엔 편집기를 이용해 /etc/crontab을 수정하는 방법과 crontab -e를 사용하는 방법이 있습니다만, crontab -e를 이용해 등록했습니다.
35 8 * * * 로딩스크립트.sh
- ‘35’ : 분
- ‘8’ : 시
- ‘*’ : 일 (매 일)
- ‘*’ : 월 (매 월)
- ‘*’ : 요일 (0부터 일요일 ~ 6은 토요일인데 모든 요일)
위의 형식으로 작성했습니다.
만약 매주 수요일 오후 4시라면 어떻게 설정할까요?
0 16 * * 3 무언가.sh
이렇게 설정하면 되겠군요.. 어렵지 않습니다. 마지막으로 매월 15일부터 20일까지 실행되길 원한다면요?
0 16 15-20 * * 무언가.sh
이렇게 설정하면 되겠군요..
문제 발생..
이렇게 잘 작성해서 이제 문제가 없겠다 싶어서 테스트를 해봤으나 실패했습니다 ^^
요청 후 정확히 60초가 경과했을 때 timeout 에러가 발생했습니다.
시도 1 - curl 옵션으로 타임 아웃 설정해보기
네 소용 없었습니다.
쉘 스크립트 내의 코드를 보면 아시겠지만 curl 명령어 옵션에 타임 아웃 설정이 안 보이셨을텐데 이유는 설정해도 소용이 없었기 때문에 빼버린 것입니다..
시도 2 - 로드 밸런서의 유휴 제한 시간 설정
다음으로 시도한 방법은 로드 밸런서의 idle timeout 설정입니다.
위에서 설명했습니다만, 우리 프로젝트는 ALB를 이용해 http로 들어오는 요청을 https로 리다이렉션 시키는 방법을 통해 인증서를 적용 중입니다.
ALB는 유휴 제한 시간 값이 존재하여 통신 중 기본 설정 시간인 60s를 넘어가면 해당 connection을 닫아버려 504 timeout을 받는 것이었습니다…
curl을 통해 get 요청을 보내면 서버는 로딩이 모두 끝난 후에 그 결과를 반환합니다.
그런데 로딩은 로그인부터 시작해 기기 장비 목록을 크롤링하고, 식품 목록을 크롤링하는데 이 과정에서 소요되는 시간은 약 3분으로 기본 설정 값인 60s로는 당연히 에러가 날 수 밖에 없었기에 300s 정도로 넉넉하게 설정하여 해결했습니다.
설정 방법은 해당 로드 밸런서의 속성 탭에 유휴 제한 시간을 편집하시면 됩니다.
어디 있는지 위치를 알려드리기 위해 하나 생성해서 보여드립니다..
해당 위치에서 편집을 통해 해결했습니다.
마치며..
해당 과정을 통해 서버 단에서 로딩 과정을 실행 시키며, 이를 자동화 시키게 되었습니다..
실제로 매장 사람들이 로딩 사라져서 너무 편하다고 말해줘서 아주 뿌듯했다는 것입니다.. 야호!