관리 메뉴

백엔드 엔지니어 이재혁

[MSA 전환기] Day 2 - 타임아웃 및 http/2 설정 본문

케어매칭 서비스 배포

[MSA 전환기] Day 2 - 타임아웃 및 http/2 설정

alex00728 2025. 11. 1. 16:33

어제는 API Gateway를 만들어서 MSA 환경의 기본 바탕을 만들었다면, 

오늘은 API Gateway가 역할을 제대로 할 수 있도록 설정을 좀 해주었다.

 

오늘 요약

추가 문제

Netty를 사용할 때, http/2 통신을 함에도 http/1.1 로그가 찍히는 문제 원인 파악

 

목차

타임아웃 및 커넥션 풀 설정
upstream http/2 설정
WireShark로 검증
http/2 통신을 하는데도 http/1.1 로그가 찍힌 이유 (Netty 관련)

 

 

 

자세히 알아보기

1. 타임아웃 및 커넥션 풀 설정

무한 대기로 인한 리소스 낭비 방지를 위해 `connect-timeout`과 `response-timeout`을 설정하자.

이어서 `connection pool` 설정을 더해 커넥션 생성에 따른 오버헤드도 최소화하고자 했다.

spring:
  cloud:
    gateway:
      httpclient: # 글로벌 설정
        connect-timeout: 3000 # 3s
        response-timeout: 10000 # 5s
        pool:
          max-idle-time: 65s # 커넥션 유지할 시간 (keep-alive)
          max-connections: 200
          acquire-timeout: 20000 # 풀에서 커넥션 기다리는 최대 시간

 

upstream http/2 요청

Spring Cloud Gateway에 http/2 설정을 위한 클래스를 만들어주었다.

@Configuration
public class Http2UpstreamConfig {

    @Bean
    public HttpClientCustomizer http2ClientCustomizer() {
        return httpClient -> httpClient.protocol(HttpProtocol.H2C);
    }
}

 

참고로, TLS 인증서는 발급받지 않고, 로컬에서 테스트할거라 h2c로 구성했다.

(h2c는 `http2cleartext`를 말한다. 암호화되어 있지 않은 평문이라는 것)


백엔드 http/2 활성화

Spring MVC 백엔드의 `application.yaml` 설정. http/2를 활성화하자.

server:
  http2:
    enabled: true

 

로그로 확인하기

http/2로 통신을 하는지 확인해보자. Spring Cloud Gateway `application.yaml` 설정에 netty 로깅 추가

logging:
  level:
    reactor.netty.http.client: DEBUG

 

로그

[gateway] [ctor-http-nio-5] r.n.http.client.HttpClientOperations     : [0c4fc870, L:/127.0.0.1:10985 - R:localhost/127.0.0.1:8081](H2 - -1) New HTTP/2 stream
[gateway] [ctor-http-nio-5] r.netty.http.client.HttpClientConfig     : [0c4fc870, L:/127.0.0.1:10985 - R:localhost/127.0.0.1:8081](H2 - -1) Initialized HTTP/2 stream pipeline AbstractHttp2StreamChannel$3{(reactor.left.h2ToHttp11Codec = io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.client.Http2StreamBridgeClientHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
[gateway] [ctor-http-nio-5] r.netty.http.client.HttpClientConnect    : [0c4fc870/1-1, L:/127.0.0.1:10985 - R:localhost/127.0.0.1:8081] Handler is being applied: {uri=http://localhost:8081/api/caregivers, method=GET}
[gateway] [ctor-http-nio-5] r.n.http.client.Http2ConnectionProvider  : [0c4fc870/1-1, L:/127.0.0.1:10985 - R:localhost/127.0.0.1:8081] Stream opened, now: 1 active streams and 100 max active streams.
[gateway] [ctor-http-nio-5] r.n.http.client.HttpClientOperations     : [0c4fc870/1-1, L:/127.0.0.1:10985 - R:localhost/127.0.0.1:8081] Received response (auto-read:false) : RESPONSE(decodeResult: success, version: HTTP/1.1)
HTTP/1.1 200 OK
# ...

 

`(H2 - -1) New HTTP/2 stream` → http/2로 요청을 하고 있기는 한데

`RESPONSE(decodeResult: success, version: HTTP/1.1)` http/1.1가 찍힌다.

 

http/2 요청에 실패한건가??

 

WireShark로 검증

로컬 네트워크(192.168.0.10 / 휴대폰)에서 `http://192.168.0.2:8080/carematching/api/caregivers` 요청을 했다.

 

클라이언트 ↔ 서버:8080(API Gateway)는 `HTTP/1.1` 기반 통신 중

 

8080 (API Gateway) ↔ 8081 (백엔드)는 `HTTP/2` 기반 통신 중

모든 통신이 http/2로 잘 이뤄지고 있다

 

실제 네트워크 통신은 HTTP/2로 잘 이뤄지고 있는 것 같은데, API Gateway의 로그는 왜 저런 것일까?

 

결론: Netty의 의도된 HTTP/1.1 구현체 사용

컴퓨터에서 이것저것 해봐도 http/2 통신이 제대로 되고 있는 것 같은데... 온라인에 완전히 같은 사례가 있었다.

Netty의 issue로 등록된 내용: HTTP/1.1 is being logged and recorded by metrics even though HTTP/2 is enabled

it records certain HTTP/1.1 logs that I don't understand, despite observing only HTTP/2 requests in Wireshark.

 

Wireshark에는 http/2 통신만 보이는데 http/1.1 로그가 찍히는 이상한 상황이 완전히 같았다.

이에 대한 netty 메인테이너 분의 답변

HTTP/2 pool uses HTTP/1.1 pool for establishing connections to the remote.

 

그러니까, TCP 연결 관리는 HTTP 버전과 관계없이 동일하기 때문에 기존의 HTTP/1.1 구현체를 그대로 사용해서 관리하고, TCP 연결 수립이 끝나면 HTTP/2 풀이 데이터 통신을 시작한다.

 

그래서 HTTP/1.1 구현체의 로그가 나와서 HTTP/1.1이 찍힌거다...

`x-http2-stream-id: <filtered>` 이런 로그는 http/2에서만 나오는 것이기 때문에 HTTP/2 통신이 잘 되고 있던거였다.

 

 

downstream 설정?

Spring Cloud Gateway는 downstream에 대해 http2를 끈 상태로 뒀다.

Nginx는 아직 reverse proxy에 대해서 http/2를 지원하지 않기 때문.

 

Nginx에서 http/2를 지원하기 위한 PR이 열려서 개발이 활발하게 진행되고 있다. 머지 않아 http/2를 지원할지도?

 

업데이트: 위 PR이 받아들여지고, Nginx 1.29.4부터 upstream http/2가 지원된다.