Skip to content

Instantly share code, notes, and snippets.

@otakijae
Last active October 10, 2022 14:06
Show Gist options
  • Save otakijae/5fe0f2bcff794622695ecd8dde231a49 to your computer and use it in GitHub Desktop.
Save otakijae/5fe0f2bcff794622695ecd8dde231a49 to your computer and use it in GitHub Desktop.
send http2 ping frame
func (w *HttpBo)Ping(network, address string) error {
if transport, ok := w.Client.Transport.(*http2.Transport); !ok {
return errors.New("Getting HTTP2 Client Transport failed")
} else {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, err := tls.Dial(network, address, &tls.Config{NextProtos: []string{http2.NextProtoTLS}})
if err != nil {
return err
}
cc, err := transport.NewClientConn(conn)
if err != nil {
return err
}
if err := cc.Ping(ctx); err != nil {
return err
} else if err := cc.Shutdown(ctx); err != nil {
return err
}
}
return nil
}
@otakijae
Copy link
Author

otakijae commented Oct 16, 2020

HTTP/2 프로토콜 협상

  • HTTP/1.x와 마찬가지로 HTTP/2도 80 또는 443 포트를 사용한다.
  • 따라서 클라이언트는 통신 전에 HTTP/2 또는 HTTP/1.x 둘 중 어느 것으로 통신하면 좋은지 판단 할 수 없다.
  • 프로토콜을 판단하기 위해 통신에서 먼저 하는 것은 프로토콜 협상이다.
  • 연결된 서버에서 어떤 프로토콜을 사용할 수 있는지는 아래의 어떤 ​​것인가로 검색 할 수 있다.
    • TLS의 ALPN (Application-Layer Protocol Negotiation)
    • TLS의 NPN (Next Protocol Negotiation)
    • HTTP의 Connection 또는 Upgrade 헤더
    • 협상 없이(다이렉트)

issue

  • TLS connection 맺을 때, TLS handshake 이후 사용할 다음 프로토콜 h2를 명시하지 않아서 use of closed network connection 발생함.
  • TLS를 사용할 경우 ALPN 또는 NPN가 사용된다. 이러한 TLS 방식을 사용하는 경우는 총칭하여 h2(HTTP/2 over TLS) 라고함.
conn, err := tls.Dial(network, address, &tls.Config{NextProtos: []string{http2.NextProtoTLS}})
const (
	// ClientPreface is the string that must be sent by new
	// connections from clients.
	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"

	// SETTINGS_MAX_FRAME_SIZE default
	// http://http2.github.io/http2-spec/#rfc.section.6.5.2
	initialMaxFrameSize = 16384

	// NextProtoTLS is the NPN/ALPN protocol negotiated during
	// HTTP/2's TLS setup.
	NextProtoTLS = "h2"

	// http://http2.github.io/http2-spec/#SettingValues
	initialHeaderTableSize = 4096

	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size

	defaultMaxReadFrameSize = 1 << 20
)

  • ALPN based connection for https:// URIs

    ALPN stands for Application Layer Protocol Negotiation, and is a TLS extension that allows a client to negotiate the next protocol to use after the TLS handshake is complete. If either the client or the server does not support ALPN, then it will be ignored, and HTTP/1.1 will be used instead.

    When the client connects to the server it sends a list of supported protocols. The server will then decide on the next
    protocol to use and send this back in its response. If the server decides to use HTTP/2 it will send pack 'h2' as the
    selected protocol, and HTTP/2 will be used for the connection.
    

  • set InsecureSkipVerify default value (false)
      // InsecureSkipVerify controls whether a client verifies the server's
      // certificate chain and host name. If InsecureSkipVerify is true, crypto/tls
      // accepts any certificate presented by the server and any host name in that
      // certificate. In this mode, TLS is susceptible to machine-in-the-middle
      // attacks unless custom verification is used. This should be used only for
      // testing or in combination with VerifyConnection or VerifyPeerCertificate.
    

HTTPS 통신에서의 HTTP/2 연결

  • 클라이언트는 TLS 기반의 https URI로 접속하면서 ALPN(Application-Layer Protocol Negotiation)을 사용
  • ALPN 이란 단어 뜻 그대로 Layer 7에서 클라이언트와 서버가 상호 협의(negotiation) 하에 사용할 프로토콜을 결정하는 방식
  • 클라이언트가 후보 프로토콜 집합을 ALPN extension 값으로 전달하면, 서버는 그중에서 자신이 지원하는 버전 하나를 고른다.
  • HTTPS를 사용하는 HTTP/2의 ALPN extension 값은 h2
  • Application layer https에서 "h2"라는 indicator를 클라이언트가 TLS 통신으로 서버에 보내 서버가 accept하는 방식을 사용함

@otakijae
Copy link
Author

@otakijae
Copy link
Author

polling

long polling

  • 메시지를 보내는 클라이언트와 수신하는 클라이언트가 같은 채팅 서버에 접속되지 않을 수도 있다. http 서버들은 보통 stateless 서버다. 로드밸런싱을 위해 라운드로빈을 사용하는 경우, 메시지를 받은 서버는 해당 메시지를 수신할 클라이언트와의 롱 폴링 연결을 가지고 있지 않은 서버일 수도 있다.
  • load balancing & sticky session ?
  • Persistence: 부하분산 장치의 중요한 기능 중 하나. 애플리케이션이 사용중인 세션을 같은 서버에 지속적으로 할당하는 기능

web socket

  • 서버와 클라이언트 간에 socket connection을 유지해서 언제든 양방향 통신 또는 데이터 전송이 가능하도록
  • 일반 HTTP Request를 통해 handshaking 과정을 거쳐 최초 접속이 이루어진다.
  • 최초 handshake ask & ack
  • 서버 측 연결 관리 필요. http port 그대로 활용

http2

downchannel 구성 & 연결 유지 http2 ping

  • 시간 지나면 끊어짐. 계속 유지해야하는 경우 http2 ping check 필요

  • handshake GET & access token 으로 수행

  • 클라이언트가 CIC와 최초 연결 시 수행되어야 하는 작업은 downchannel을 구성하는 것입니다. Downchannel은 CIC로부터 지시 메시지를 받을 때 사용됩니다. 이때, 전달받는 지시 메시지는 클라이언트의 이벤트 메시지에 대한 응답으로 전달되는 지시 메시지가 아닌 특정 조건이나 필요에 의해 CIC가 주도(Cloud-initiated)하여 클라이언트에 보내는 지시 메시지입니다. 예를 들면, 새로운 알림(push)이 도착했다면 downchannel을 통해 지시 메시지가 전달될 것입니다.

  • Downchannel 연결이 종료되거나 끊어지면 클라이언트는 즉시 새로운 downchannel을 구성하여, CIC로부터 전달되는 지시 메시지를 받지 못하는 일이 없도록 해야합니다.

  • CIC와 연결이 유지되고 있는지 파악하기 위해 클라이언트는 1 분 간격으로 HTTP/2 PING 프레임을 CIC로 전송해야 합니다. CIC로부터 HTTP/2 PING ACK 응답을 받지 못하면 클라이언트는 즉시 새로운 연결을 구성해 클라이언트와 CIC간의 연결이 지속될 수 있도록 해야합니다. HTTP/2 PING 프레임에 대한 자세한 설명은 HTTP/2 PING Payload Format을 참조합니다.

multipart message 음성 파일 전송/수신 (push)

  • 사용자 음성 데이터를 전송 혹은 음성 답변 데이터를 받는데 사용
  • 예를 들면, 사용자의 음성 입력을 CIC로 전달하려면 SpeechRecognizer.Recognize 이벤트 메시지와 함께 녹음한 사용자의 음성 데이터를 함께 전송해야 합니다.
    클라이언트는 Content-Type을 multipart/form-data로 설정하고 첫 번째 메시지 파트에는 이벤트 메시지 정보가 담긴 JSON 데이터를 두 번째 메시지 파트에는 사용자의 음성이 담긴 바이너리 데이터를 담아서 보낼 수 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment