현재 서버 응답 flow는
유저 → cloudflare proxy DNS → ec2(ap-northeast-2 region) → docker-compose nginx → fastapi
pydantic logfire를 봤을때, 실제로 서버에서 처리되는 시간 자체는 60ms정도밖에 안걸림
그런데 chrome에서 찍어보면 1초나 걸리는 어이없는 상황 발생.
어디서 이렇게 느려지는지 하나씩 부숴보자.
일단 전체 flow의 소모 시간을 보자
curl -w "\nTime: %{time_total}\n" https://testapi
Time: 1.073974?? 1초?
fastapi container일까?
먼저 fastapi container에 직접 들어가서 curl을 해봄
curl -w "\nTime: %{time_total}\n" https://testapi
Time: 0.030351
Time: 0.076722
Time: 0.050962시간은 매우 안정적이야 fastapi 서버 자체는 속도문제가 없음. 그럼 다음 단계로 가보자
nginx일까?
nginx에서 요청 헤더의 Host를 보고 가르기 때문에 헤더를 명시해주고 요청을 보냄
curl -w "\nTime: %{time_total}\n" -H "Host: testapi.test.app" -k https://localhost
Time: 0.048668
Time: 0.095096
Time: 0.037258
가끔 튀기는 하지만 애초에 fastapi도 가끔 튀니까 얘 문제는 아닌듯 함
cloudflare proxy때문인듯
cloudflare proxy는 enterprise plan을 사용하지 않으면 일본이나 홍콩의 CDN 서버를 경유하는듯 하다. → 한국의 망사용료 문제 때문에 이렇게 됐다고 함 그래서 왔다갔다 0.5초 이상의 지연시간이 추가되는것 일단 이 문제가 맞는지 확인해보기 위해 cloudflare proxied 대신 dns-only로 테스트 해보기로 함 인증서는 cloudflare 꺼 말고 lets encrypt로 생성
ec2에 cloudflare.ini 파일 생성
dns_cloudflare_email = "email@email.com"
dns_cloudflare_api_key = "cloudflare_global_key"cloudflare에서 gloabl api key 받아다가 박으면 됨. 근데 certbot에서는 global key를 이제 권장하지는 않음 https://certbot-dns-cloudflare.readthedocs.io/en/stable/
인증서 생성
docker run -it --rm --name certbot \
-v '/etc/letsencrypt:/etc/letsencrypt' \
-v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
-v './cloudflare.ini:/etc/letsencrypt/cloudflare.ini' \
certbot/dns-cloudflare certonly \
-d test.app,*.test.app \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini요래요래 돌려주면 인증서가 생성된다.
docker run -it --rm --name certbot \
-v '/etc/letsencrypt:/etc/letsencrypt' \
-v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
-v './cloudflare.ini:/etc/letsencrypt/cloudflare.ini' \
certbot/dns-cloudflare certificates --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini남은 인증서 기간 확인
docker run --rm --name certbot -v \
'/etc/letsencrypt:/etc/letsencrypt' -v \
'/var/lib/letsencrypt:/var/lib/letsencrypt' -v \
'./cloudflare.ini:/etc/letsencrypt/cloudflare.ini' \
certbot/dns-cloudflare renew --dry-run인증서 renew
0 18 */15 * * /home/ec2-user/renew.sh >> /home/ec2-user/renew.log 2>&1cloudflare proxied → dns-only 변경
주황색 구름 → 회색구름 변경
docker compose에 부착
일단 테스트 서버에만 넣어보자
services:
nginx:
image: nginx:1.27.0-alpine
container_name : nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/cert.pem:/etc/cloudflare_cert/cert.pem
- ./nginx/key.pem:/etc/cloudflare_cert/key.pem
- /etc/letsencrypt/live/test.app/fullchain.pem:/etc/letsencrypt/fullchain.pem
- /etc/letsencrypt/live/test.app/privkey.pem:/etc/letsencrypt/privkey.pemnginx 재시작
nginx -t
nginx -s reload
거의 10배이상 빨라진 걸 볼 수 있다.
다만… 고려사항
사실 cloudflare의 proxy의 도움을 받는게 좋긴 하다.
위 방법의 장점과 단점
- 장점
- 속도가 매우 빠름 (홍콩/일본 CDN 포화 상태 일 때 대비 6~10배 정도)
- 단점
- 실제 서버의 IP가 노출됨. 현재 서비스의 서버는 aws public ec2로 서빙되고 있음(private가 아님. elastic IP의 개수 대비 NAT gateway가 더 비싸서, 돈을 아끼기 위한 선택)
- DDOS 보호와 같은 cloudflare의 도움을 받을 수 없음
- 고려사항
- cloudflare가 매우 포화상태가 아닌 이상 현재 서버의 평균 응답속도는 500ms. 서비스를 이용하는데에 있어서 조금 걸리적 거릴수는 있지만 크게 느린 상황은 아님.
- 실제 서버의 IP가 노출되는 등의 위험성이 얼마나 크냐에 따라 선택할 수 있을 것 같음
