Skip to content

Feat: Add Experimental Triple HTTP/3 Support #2916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 35 commits into
base: develop
Choose a base branch
from

Conversation

marsevilspirit
Copy link
Member

@marsevilspirit marsevilspirit commented Jun 17, 2025

What this PR does / Why we need it

This PR introduces experimental support for HTTP/3 to the Triple protocol. By running over QUIC, HTTP/3 provides significant performance advantages over HTTP/2, including:

  • Reduced Head-of-Line Blocking: Eliminates TCP head-of-line blocking, improving throughput on lossy networks.
  • Faster Connection Setup: Combines the transport and cryptographic handshakes for a 0-RTT or 1-RTT connection setup.

Adding HTTP/3 support keeps the dubbo-go Triple protocol at the forefront of modern, high-performance web protocols and provides users with a powerful option for latency-sensitive services.


Main Changes

  • Dependency: Introduced quic-go as the underlying implementation for QUIC and HTTP/3.
  • Configuration: Added new configuration options under dubbo.protocols.triple.http3 to enable and control the HTTP/3 listener.
  • TLS Requirement: Since HTTP/3 mandates the use of TLS 1.3+, the handling of tls.Config has been reinforced. The server will fail to start if HTTP/3 is enabled without a valid TLS configuration.

How to use

client and server mode

To enable HTTP/3, you must provide a vaild TLS configuration and set the http3Enable option in your code:

  • server side
	srv, err := server.NewServer(
		server.WithServerProtocol(
			protocol.WithPort(20000),
			protocol.WithTriple(
				triple.Http3Enable(),
			),
		),
		server.WithServerTLSOption(
			tls.WithCertFile("/path/to/your/server_cert.pem"),
			tls.WithKeyFile("/path/to/your/server_key.pem"),
			tls.WithServerName("dubbogo.test.example.com"),
		),
	)
  • client side
	cli, err := client.NewClient(
		client.WithClientURL("127.0.0.1:20000"),
		client.WithClientProtocol(
			protocol.WithTriple(
				triple.Http3Enable(),
			),
		),
		client.WithClientTLSOption(
			tls.WithCACertFile("/path/to/your/server_ca_cert.pem"),
			tls.WithServerName("dubbogo.test.example.com"),
		),
	)
yaml file mode

To enable HTTP/3, you must provide a valid TLS configuration and enable the feature in your configuration file.

  • server side
# dubbo server yaml configure file
dubbo:
  registries:
    demoZK:
      protocol: zookeeper
      timeout: 10s
      address: 127.0.0.1:2181
  protocols:
    tripleProtocol:
      name: tri
      port: 20000
      triple:
        http3:
          enable: true
  provider:
    services:
      GreetTripleServer:
        interface: com.apache.dubbo.sample.Greeter
  tls_config:
    cert-file: "/path/to/your/cert.pem"
    key-file: "/path/to/your/key.pem"
    tls-server-name: dubbogo.test.example.com
  • client side
# dubbo client yaml configure file
dubbo:
  registries:
    demoZK:
      protocol: zookeeper
      timeout: 3s
      address: 127.0.0.1:2181
  consumer:
    references:
      GreetServiceImpl:
        protocol: tri
        protocol_config:
          triple:
            http3:
              enable: true
        interface: com.apache.dubbo.sample.Greeter
        registry: demoZK
        retries: 3
        timeout: 3000
  tls_config:
    ca-cert-file: "/path/to/your/server_ca_cert.pem"
    tls-server-name: dubbogo.test.example.com

Checklist

  • Necessary unit and integration tests have been added.
  • Relevant documentation has been updated.
  • The feature has been verified locally.

@marsevilspirit marsevilspirit requested review from FoghostCn, No-SilverBullet and Copilot and removed request for FoghostCn and No-SilverBullet June 17, 2025 13:21
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds experimental HTTP/3 support to the Triple protocol over QUIC, enabling users to choose between HTTP/2 and HTTP/3 transports. It updates server and client startup logic, configuration types, and compatibility layers to include an Http3Enable option and Http3Config.

  • Introduce Http3Enable option and Http3Config YAML fields for server and client.
  • Extend server (Run, startHttp3, Stop, GracefulStop) and client (http3.Transport) to handle HTTP/3.
  • Update config, compatibility, and constants to support CallHTTP3.

Reviewed Changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated no comments.

Show a summary per file
File Description
protocol/triple/triple_protocol/server.go Added Run, startHttp3, Stop, GracefulStop and HTTP/3 fields (addr, http3Srv)
protocol/triple/server.go Integrated HTTP/2/3 selection logic and TLS handling
protocol/triple/client.go Added HTTP/3 transport setup using QUIC in newClientManager
protocol/triple/options.go Introduced Http3Enable option
common/constant/key.go Defined new CallHTTP3 constant
global/http3_config.go New Http3Config type with clone/default methods
global/triple_config.go Extended TripleConfig with Http3 field
global/reference_config.go Updated ReferenceConfig to include ClientProtocolConfig
global/client_protocol_config.go Renamed ProtocolClientConfig to ClientProtocolConfig
config/http3_config.go New config.Http3Config type
config/triple_config.go Extended config.TripleConfig with Http3 field
config/reference_config.go Renamed Methods to MethodsConfig and added ProtocolClientConfig
config/client_protocol_config.go Added config.ClientProtocolConfig definition
protocol/options.go Updated ClientOptions.ProtocolClient type
compat.go Updated compatibility conversions to include HTTP/3 config
go.mod Bumped dependencies and added quic-go/qpack modules
global/config_test.go Added tests for TripleConfig and Http3Config cloning
Comments suppressed due to low confidence (2)

protocol/triple/client.go:259

  • Missing import for fmt; add import "fmt" at the top to resolve fmt.Errorf usage.
			return nil, fmt.Errorf("TRIPLE http3 client must have TLS config, but TLS config is nil")

protocol/triple/triple_protocol/server.go:23

  • [nitpick] Imports are split across multiple blocks and mixed order; consider consolidating standard library and external imports into a single organized import block.
	"errors"

// Whether to enable HTTP/3 negotiation.
// If set to false, HTTP/2 alt-svc negotiation will be skipped,
// enabling HTTP/3 but disabling HTTP/2 on the consumer side.
// negotiation bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good job

// TODO: Refactor to support starting HTTP/2 and HTTP/3 servers simultaneously.
// The current switch logic is mutually exclusive. Future work should allow enabling
// both protocols, likely based on configuration, and run them concurrently.
switch callProtocol {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comment!
According to my understanding, in order to support something like this (negotiation = true configuration, you must first start the HTTP/2 server, and use Alt-Svc in HTTP/2 to inform the client that HTTP/3 is supported.) Do you need to modify this logic? Change it to something like this? Pseudocode demonstration

func (s *Server) Run(tlsConf *tls.Config) error {
    var wg sync.WaitGroup
    var errChan = make(chan error, 2)

    if s.config.EnableHTTP2 {
        wg.Add(1)
        go func() {
            defer wg.Done()
            if err := s.startHttp2(tlsConf); err != nil {
                errChan <- fmt.Errorf("http2 error: %w", err)
            }
        }()
    }

    if s.config.EnableHTTP3 {
        wg.Add(1)
        go func() {
            defer wg.Done()
            if err := s.startHttp3(tlsConf); err != nil {
                errChan <- fmt.Errorf("http3 error: %w", err)
            }
        }()
    }

    wg.Wait()
    close(errChan)

    for err := range errChan {
        return err
    }

    return nil
}

This is just a question I have, no need to modify the code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, i will implement it in next PR.

Copy link
Contributor

@1kasa 1kasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link

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

Successfully merging this pull request may close these issues.

3 participants