티스토리 뷰
Photo by Paweł Czerwiński on Unsplash
TL;DR
- Go언어의 default http client는 timeout이 없다. Request를 보내서 response가 올때까지 무한정 기다린다.
- 따라서 custom 하게 timeout을 설정한 http client를 생성해서 사용하자
모범 답안
playground: https://play.golang.org/p/CdazCatBjrS
- 여기서 실행은 되지 않는다. 코드만 참고하자
- 실행은 별도로 PC에서 테스트하거나 https://repl.it 사이트에서 테스트하자
1) c 라는 timeout 설정이 들어가있는 http.Client를 생성한 다음, HTTP request를 보내면
2) httptest.NewServer()로 생성된 테스트 서버가 1분이나 지나서 보낼 응답을 기다리지 않고 time out 이 걸린다는 것이다.
모범답안 분석
http.Client는 총 3개의 timeout을 설정할 수 있는데 위 예제에서는 http.Client의 Timeout: 3 * time.Second 에 걸려서 timeout이 걸렸다.
세 개의 timeout 설정을 하나씩 챙겨보자
1) http.Client의 Timeout - 코드: https://bit.ly/3qeyuik
- 클라이언트로 request를 보내고 기다리는 시간을 말한다. 보통은 이것만 설정해줘도 충분하다
- 연결 시간, 리디렉션 시간, 그리고 매우 중요하게도 response body를 읽는 시간을 모두 합친 시간이다.
- 즉, response를 return 받더라도 타이머가 계속 돌아간다는 것이다
- Timeout 값을 설정하지 않았을 경우의 zero value는 timeout이 없다는 것이다.
- Client는 내부의 Transport에게 cancel을 요청할 수도 있다. (그만해!)
2) net.Dialer의 Timeout - 코드: https://bit.ly/388EW4m
TCP 연결이 되고 그 위에서 HTTP request와 response가 오가게 되는데, 그 연결을 위한, 마치 전화를 거는 것과 같은, Dialing 을 한 이후 연결이 되기까지 기다리는 Timeout 시간이다.
- 만약 여러 IP에 dialing을 하면 각각의 dialing 후 대기시간의 합이 된다
- 여기서 Timeout을 설정하는 것과 상관없이 OS에서 TCP dialing의 Timeout을 두기도 하는데 보통 3분 정도이다.
3) http.Transport의 TLSHandshakeTimeout - 코드: https://bit.ly/3kIvJVm
참고링크: https://www.leafcats.com/202
HTTPS로 보안통신을 한다는 것은 결국 SSL/TLS 연결 위에서 HTTP 통신을 한다는 것으로 보면 된다. 만약 FTP가 SSL/TLS 위에서 동작한다면 SFTP가 된다. 암호화된 연결을 하려면 처음에 handshake 과정이 필요한데 그 Timeout 시간을 설정할 수 있다.
1) 2) 3) 을 종합해보면 2) 안에 3)이 포함이 되고, 1) 안에 2)가 포함이 된다
4) net.Dialer의 KeepAlive - 코드: https://bit.ly/2OkUJG6
덤으로 KeepAlive 까지 알아보자. 참고링크: https://hamait.tistory.com/341
- 주된 목적은 어느 한쪽이 끊겼는데 연결을 유지하는 것을 방지하는 것이다.
- TCP 네트워크 연결이 유지되도록 해주는 keep-alive probe들 간의 인터벌 시간이다. default는 15초마다
- 만약 네트워크 프로토콜이나 OS가 이걸 지원하지 않는다면 무시된다.
- 위에 언급한데로 default는 15초이며, 음수값을 넣으면 disable 된다.
문제있는 녀석
playground: https://play.golang.org/p/qmrfyRCl6Qp
custom하게 timeout이 설정된 http.Client를 생성하는 대신에 default http client를 사용하는 http.Get() 함수를 이용했다.
default http client는 Timeout 필드가 설정되어 있지 않으며 zero value 일때에 무한히 기다리게 된다.
이 예제에서는 1분 뒤에야 response를 받게 되지만 실제 production에서 user가 한없이 기다릴 수는 없는 것이다.
즉, 서비스에는 문제가 발생하는데, 에러도, 로그상의 기록도, CPU나 메모리상의 문제도 없는 상태에서 멘붕이 오게 되는 것이다.
- request를 보내는 서버가 일시적으로 죽었거나, 더 이상 서비스를 하지 않는 경우를 생각해보면 된다.
- user의 경우는 보통 response를 받아서 원하는 작업을 해야 하는데 이유도 모른채 무한정 기다리게 되는 것이다.
다음 포스팅에는 context 패키지를 활용하는 방법을 정리해보겠다
참고 링크: https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779
'golang' 카테고리의 다른 글
Go HTTP server를 GitHub Action을 이용해 Heroku로 deploy 해보자 (0) | 2021.03.29 |
---|---|
Golang - http.Client에 context 패키지를 쓰면 더 좋다 (0) | 2021.03.05 |
코로나 바이러스 확진자 동향 3주간 비교 - Heroku로 서비스하기 (0) | 2021.03.03 |
코로나 바이러스 확진자 동향 3주간 비교 - 차트 만들기 (0) | 2021.03.03 |
코로나 바이러스 확진자 동향 3주간 비교 - 데이터를 먹기좋게 요리하기 (0) | 2021.03.03 |
- Total
- Today
- Yesterday
- golang
- strange
- 노션
- websocket
- JIRA
- 제이펍
- API
- Bug
- 독서
- Shortcut
- 영화
- bun
- 2023
- agile
- github
- notion
- 잡학툰
- pool
- ChatGPT
- go
- solid
- 클린 애자일
- postgres
- Gin
- 체호프
- OpenAI
- 인텔리제이
- 독서후기
- intellij
- folklore
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |