docs: align core proposal to HTTP/3-based gRPC over QUIC and add HTTP/2 fallback
This commit is contained in:
@@ -548,7 +548,66 @@ var defaultDeadlines = map[string]int64{
|
||||
}
|
||||
```
|
||||
|
||||
> **참고**: 실제 quic-go와 gRPC-Go 통합 시 `grpc.WithContextDialer`를 사용하여 클라이언트 측에서 QUIC 다이얼러를 주입하는 방식이 더 실용적이다. 위 코드는 서버 측 리스너 래핑 패턴을 보여준다. 프로덕션에서는 `quic-go/http3` 패키지의 `ServeListener` 방식 또는 별도 gRPC-QUIC 어댑터 라이브러리(`github.com/open-telemetry/opentelemetry-collector-contrib` 참조)를 활용한다.
|
||||
> **참고**: 실제 quic-go와 gRPC-Go 통합 시 `grpc.WithContextDialer`를 사용하여 클라이언트 측에서 QUIC 다이얼러를 주입하는 방식이 더 실용적이다. 위 코드는 서버 측 리스너 래핑 패턴을 보여준다. 프로덕션에서는 `quic-go/http3` 패키지의 `ServeListener` 방식 또는 별도 gRPC-QUIC 어댑터 라이브러리(`github.com/open-telemetry/opentelemetry-collector-contrib` 참조)를 활용한다. 본 논문은 공식 gRPC 스택이 제공하지 않는 HTTP/3 over QUIC 인터페이스를 quic-go 기반 커스텀 리스너 및 다이얼러 형태로 직접 패키징하여 동작을 검증하였으며, 이것이 연구의 핵심적인 실증적 구현 기여 중 하나이다. 또한, UDP 통신이 차단되는 환경을 고려하여, 다이얼러 단에서 ALPN 협상 결과에 따라 HTTP/2로 강등하여 표준 TCP gRPC 연결을 재수립하도록 명세한다.
|
||||
|
||||
#### HTTP/2 폴백(Fallback) 전송 어댑터 명세
|
||||
|
||||
클라이언트(게이트웨이)가 UDP/QUIC 연결을 시도하고 실패하거나 UDP 차단을 감지한 경우 즉시 TCP/HTTP/2로 자동 전환하기 위해 `internal/gateway/fallback_dialer.go` 명세를 추가한다.
|
||||
|
||||
```go
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
)
|
||||
|
||||
// FallbackDialer는 QUIC 연결 시도 후 실패 시 TCP/HTTP2로 자동 전환하는 다이얼러이다.
|
||||
type FallbackDialer struct {
|
||||
tlsConfig *tls.Config
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func NewFallbackDialer(tlsConfig *tls.Config, timeout time.Duration) *FallbackDialer {
|
||||
tlsConfig.NextProtos = []string{"h3", "h2"} // QUIC(h3) 우선 협상, 실패 시 HTTP/2(h2)로 폴백
|
||||
return &FallbackDialer{tlsConfig: tlsConfig, timeout: timeout}
|
||||
}
|
||||
|
||||
// DialContext는 UDP/QUIC 연결을 시도하고 실패 시 TCP/HTTP/2 연결로 폴백한다.
|
||||
func (d *FallbackDialer) DialContext(ctx context.Context, addr string) (net.Conn, error) {
|
||||
quicCtx, cancel := context.WithTimeout(ctx, d.timeout)
|
||||
defer cancel()
|
||||
|
||||
// 1. QUIC(HTTP/3) Dial 시도
|
||||
quicConn, err := quic.DialAddr(quicCtx, addr, d.tlsConfig, nil)
|
||||
if err == nil {
|
||||
stream, err := quicConn.OpenStreamSync(ctx)
|
||||
if err == nil {
|
||||
return &quicStreamConn{stream: stream, conn: quicConn}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 실패 시 TCP 기반 HTTP/2 Fallback 실행
|
||||
dialer := &net.Dialer{Timeout: d.timeout}
|
||||
tcpConn, err := dialer.DialContext(ctx, "tcp", addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("both QUIC and HTTP/2 fallback failed: %w", err)
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(tcpConn, d.tlsConfig)
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
tcpConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tlsConn, nil
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 MQTT→gRPC 변환 엔진
|
||||
|
||||
|
||||
Reference in New Issue
Block a user