Skip to content
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

Triple protocol http1 upgrade support #14026

Open
wants to merge 2 commits into
base: 3.3
Choose a base branch
from

Conversation

walklown
Copy link

@walklown walklown commented Apr 2, 2024

What is the purpose of the change

Triple protocol http1 upgrade support. For issue [Feature][3.3] Triple protocol http1 upgrade support

Brief changelog

Add Http2ServerUpgradeCodec to http1 channel handlers.

Verifying this change

https://github.com/walklown/dubbo-pr-test/tree/main/pr-test-triple

@walklown walklown force-pushed the feature/triple-http1-upgrade branch 4 times, most recently from 3b48127 to 8238e49 Compare April 2, 2024 16:25
@AlbumenJ
Copy link
Member

AlbumenJ commented Apr 7, 2024

@oxsean PTAL

@oxsean oxsean self-requested a review April 7, 2024 14:15
@walklown walklown force-pushed the feature/triple-http1-upgrade branch from 8238e49 to 6d62b56 Compare April 8, 2024 07:11
@walklown walklown requested a review from AlbumenJ April 13, 2024 15:11
@oxsean
Copy link
Collaborator

oxsean commented Apr 24, 2024

Test org.apache.dubbo.demo.provider.ApiProvider with curl:

curl.exe -v --http2 -k -H "Content-Type: application/json" -d '"asd"' http://127.0.0.1:50051/org.apache.dubbo.demo.GreeterService/sayHelloAsync

but upgrade failed, could you please take a look?
image

@oxsean
Copy link
Collaborator

oxsean commented Apr 24, 2024

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c:
https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/
https://imququ.com/post/protocol-negotiation-in-http2.html

@walklown
Copy link
Author

Test org.apache.dubbo.demo.provider.ApiProvider with curl:

curl.exe -v --http2 -k -H "Content-Type: application/json" -d '"asd"' http://127.0.0.1:50051/org.apache.dubbo.demo.GreeterService/sayHelloAsync

but upgrade failed, could you please take a look? image

Because you specified a http scheme (and not https), and asked curl to use HTTP/2, then curl will attempt to perform a HTTP/1.1 upgrade to HTTP/2, as can be seen from the logs.

Typical HTTP/1.1 upgrades are performed using GET, not POST, notably the HTTP/1.1 upgrade to WebSocket.

The server does not seem to be prepared to accept a POST with a body as an attempt to upgrade and replies with 413 because it does not expect a body.

If you try a GET without body it will likely succeed.

Alternatively, if you know that port 8889 accepts prior-knowledge clear-text HTTP/2 (that is, you can send directly HTTP/2 bytes to that port without having to perform a HTTP/1.1 upgrade), you can try:

curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello

image

`$ curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello
Note: Unnecessary use of -X or --request, POST is already inferred.

  • Trying 127.0.0.1:50052...
  • Connected to 127.0.0.1 (127.0.0.1) port 50052
  • [HTTP/2] [1] OPENED stream for http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello
  • [HTTP/2] [1] [:method: POST]
  • [HTTP/2] [1] [:scheme: http]
  • [HTTP/2] [1] [:authority: 127.0.0.1:50052]
  • [HTTP/2] [1] [:path: /org.apache.dubbo.springboot.demo.DemoService/sayHello]
  • [HTTP/2] [1] [user-agent: curl/8.5.0]
  • [HTTP/2] [1] [accept: /]
  • [HTTP/2] [1] [content-type: application/json]
  • [HTTP/2] [1] [content-length: 20]

POST /org.apache.dubbo.springboot.demo.DemoService/sayHello HTTP/2
Host: 127.0.0.1:50052
User-Agent: curl/8.5.0
Accept: /
content-type:application/json
Content-Length: 20

< HTTP/2 200
< te: trailers
< content-type: application/json
<

  • Connection #0 to host 127.0.0.1 left intact
    "Hello myFirstParameter"`

@oxsean
Copy link
Collaborator

oxsean commented Apr 25, 2024

Test org.apache.dubbo.demo.provider.ApiProvider with curl:

curl.exe -v --http2 -k -H "Content-Type: application/json" -d '"asd"' http://127.0.0.1:50051/org.apache.dubbo.demo.GreeterService/sayHelloAsync

but upgrade failed, could you please take a look? image

Because you specified a http scheme (and not https), and asked curl to use HTTP/2, then curl will attempt to perform a HTTP/1.1 upgrade to HTTP/2, as can be seen from the logs.

Typical HTTP/1.1 upgrades are performed using GET, not POST, notably the HTTP/1.1 upgrade to WebSocket.

The server does not seem to be prepared to accept a POST with a body as an attempt to upgrade and replies with 413 because it does not expect a body.

If you try a GET without body it will likely succeed.

Alternatively, if you know that port 8889 accepts prior-knowledge clear-text HTTP/2 (that is, you can send directly HTTP/2 bytes to that port without having to perform a HTTP/1.1 upgrade), you can try:

curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello

image

`$ curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello Note: Unnecessary use of -X or --request, POST is already inferred.

  • Trying 127.0.0.1:50052...
  • Connected to 127.0.0.1 (127.0.0.1) port 50052
  • [HTTP/2] [1] OPENED stream for http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello
  • [HTTP/2] [1] [:method: POST]
  • [HTTP/2] [1] [:scheme: http]
  • [HTTP/2] [1] [:authority: 127.0.0.1:50052]
  • [HTTP/2] [1] [:path: /org.apache.dubbo.springboot.demo.DemoService/sayHello]
  • [HTTP/2] [1] [user-agent: curl/8.5.0]
  • [HTTP/2] [1] [accept: /]
  • [HTTP/2] [1] [content-type: application/json]
  • [HTTP/2] [1] [content-length: 20]

POST /org.apache.dubbo.springboot.demo.DemoService/sayHello HTTP/2
Host: 127.0.0.1:50052
User-Agent: curl/8.5.0
Accept: /
content-type:application/json
Content-Length: 20

< HTTP/2 200 < te: trailers < content-type: application/json <

  • Connection #0 to host 127.0.0.1 left intact
    "Hello myFirstParameter"`

Test org.apache.dubbo.demo.provider.ApiProvider with curl:

curl.exe -v --http2 -k -H "Content-Type: application/json" -d '"asd"' http://127.0.0.1:50051/org.apache.dubbo.demo.GreeterService/sayHelloAsync

but upgrade failed, could you please take a look? image

Because you specified a http scheme (and not https), and asked curl to use HTTP/2, then curl will attempt to perform a HTTP/1.1 upgrade to HTTP/2, as can be seen from the logs.

Typical HTTP/1.1 upgrades are performed using GET, not POST, notably the HTTP/1.1 upgrade to WebSocket.

The server does not seem to be prepared to accept a POST with a body as an attempt to upgrade and replies with 413 because it does not expect a body.

If you try a GET without body it will likely succeed.

Alternatively, if you know that port 8889 accepts prior-knowledge clear-text HTTP/2 (that is, you can send directly HTTP/2 bytes to that port without having to perform a HTTP/1.1 upgrade), you can try:

curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello

image

`$ curl -v --http2-prior-knowledge -X POST -k -H "content-type:application/json" -d '["myFirstParameter"]' http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello Note: Unnecessary use of -X or --request, POST is already inferred.

  • Trying 127.0.0.1:50052...
  • Connected to 127.0.0.1 (127.0.0.1) port 50052
  • [HTTP/2] [1] OPENED stream for http://127.0.0.1:50052/org.apache.dubbo.springboot.demo.DemoService/sayHello
  • [HTTP/2] [1] [:method: POST]
  • [HTTP/2] [1] [:scheme: http]
  • [HTTP/2] [1] [:authority: 127.0.0.1:50052]
  • [HTTP/2] [1] [:path: /org.apache.dubbo.springboot.demo.DemoService/sayHello]
  • [HTTP/2] [1] [user-agent: curl/8.5.0]
  • [HTTP/2] [1] [accept: /]
  • [HTTP/2] [1] [content-type: application/json]
  • [HTTP/2] [1] [content-length: 20]

POST /org.apache.dubbo.springboot.demo.DemoService/sayHello HTTP/2
Host: 127.0.0.1:50052
User-Agent: curl/8.5.0
Accept: /
content-type:application/json
Content-Length: 20

< HTTP/2 200 < te: trailers < content-type: application/json <

  • Connection #0 to host 127.0.0.1 left intact
    "Hello myFirstParameter"`

There is no documentation mentioned that methods other than GET are not supported. I think it might be because you haven't set maxContentLength
https://github.com/netty/netty/blob/4379f0b92dc1ae375bba9afa1c279b5aa867a3eb/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java#L190

--http2-prior-knowledge will skip negotiation, therefore this test is meaningless.

@walklown
Copy link
Author

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c: https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/ https://imququ.com/post/protocol-negotiation-in-http2.html

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c: https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/ https://imququ.com/post/protocol-negotiation-in-http2.html

The current common implementation of ALPN is through extended TLS. TLS processing in Dubbo is in ‘org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServerHandler’, before confirming the RPC protocol. Extensions to this implementation will have an impact on all RPC protocols. Could you please confirm whether support is needed at this level?

@oxsean
Copy link
Collaborator

oxsean commented Apr 25, 2024

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c: https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/ https://imququ.com/post/protocol-negotiation-in-http2.html

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c: https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/ https://imququ.com/post/protocol-negotiation-in-http2.html

The current common implementation of ALPN is through extended TLS. TLS processing in Dubbo is in ‘org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServerHandler’, before confirming the RPC protocol. Extensions to this implementation will have an impact on all RPC protocols. Could you please confirm whether support is needed at this level?

I think so, but we need to confirm whether adding ALPN support cause a regression in protocols other than Triple, such as the Dubbo protocol.

@walklown walklown force-pushed the feature/triple-http1-upgrade branch from 6d62b56 to 2ac7b09 Compare April 25, 2024 10:43
@walklown
Copy link
Author

walklown commented Apr 25, 2024

There is no documentation mentioned that methods other than GET are not supported. I think it might be because you haven't set maxContentLength https://github.com/netty/netty/blob/4379f0b92dc1ae375bba9afa1c279b5aa867a3eb/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java#L190

--http2-prior-knowledge will skip negotiation, therefore this test is meaningless.

You are right, thanks for the guidance. I have submitted a fix

@walklown
Copy link
Author

walklown commented Apr 25, 2024

Please look into whether Application-Layer Protocol Negotiation is supported in addition to h2c: https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/ https://imququ.com/post/protocol-negotiation-in-http2.html

The current common implementation of ALPN is through extended TLS. TLS processing in Dubbo is in ‘org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServerHandler’, before confirming the RPC protocol. Extensions to this implementation will have an impact on all RPC protocols. Could you please confirm whether support is needed at this level?

I think so, but we need to confirm whether adding ALPN support cause a regression in protocols other than Triple, such as the Dubbo protocol.

OK, I will submit a commit try to implement it.

@walklown
Copy link
Author

walklown commented Apr 26, 2024

I think so, but we need to confirm whether adding ALPN support cause a regression in protocols other than Triple, such as the Dubbo protocol.

Submitted a commit. Please take a look, thanks.

My test:
https://github.com/walklown/dubbo-pr-test/blob/main/pr-test-triple/dubbo-triple-provider/src/main/java/org/apache/dubbo/springboot/demo/provider/ProviderApplication.java
https://github.com/walklown/dubbo-pr-test/blob/main/pr-test-triple/dubbo-triple-netty-http1-upgrade/src/main/java/com/walklown/prtest/triple/netty/Http2ALPNClient.java

Copy link

sonarcloud bot commented Apr 26, 2024

@oxsean
Copy link
Collaborator

oxsean commented Apr 29, 2024

LGTM, but have you tested no impact to dubbo protocol?
And It would be good to place your test as a unit test in the Dubbo project, or you could put it in the integration tests as well:
https://github.com/apache/dubbo-integration-cases

@walklown
Copy link
Author

LGTM, but have you tested no impact to dubbo protocol? And It would be good to place your test as a unit test in the Dubbo project, or you could put it in the integration tests as well: https://github.com/apache/dubbo-integration-cases

Submitted some test cases to apache/dubbo-integration-cases#22

  1. Http2ClientT: Test on triple protocol to support other clients http1 to upgrade http2
  2. DubboConsumerT: triple protocol and dubbo protocol RPC function testing, including turning on and off ssl

@walklown
Copy link
Author

@AlbumenJ The problem has been solved, PTAL.

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

Successfully merging this pull request may close these issues.

None yet

3 participants