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

Merged
merged 4 commits into from
May 11, 2024

Conversation

walklown
Copy link
Contributor

@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
Contributor 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
Contributor 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
Contributor 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
Contributor 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
Contributor 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

@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
Contributor 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
Contributor Author

@AlbumenJ The problem has been solved, PTAL.

@oxsean
Copy link
Collaborator

oxsean commented May 8, 2024

@walklown Sorry, I forgot commit the comments, please take a look.

@walklown
Copy link
Contributor Author

walklown commented May 8, 2024

@walklown Sorry, I forgot commit the comments, please take a look.

Submitted, thanks for your guidance !

@walklown walklown force-pushed the feature/triple-http1-upgrade branch from aab8c3e to 6016080 Compare May 9, 2024 03:15
@walklown
Copy link
Contributor Author

walklown commented May 9, 2024

The check item 'dubbo-samples-test-13787' failed because the tests attribute in 'case-configuration.yml' was set incorrectly. I think it should be replaced with

 tests:
   - "**/*IT.class"
image

@AlbumenJ

Copy link

sonarcloud bot commented May 10, 2024

@AlbumenJ AlbumenJ merged commit b9e1dc0 into apache:3.3 May 11, 2024
17 of 19 checks passed
@walklown walklown deleted the feature/triple-http1-upgrade branch May 11, 2024 07:53
@codecov-commenter
Copy link

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 38.52%. Comparing base (a12975a) to head (8238e49).
Report is 490 commits behind head on 3.3.

Current head 8238e49 differs from pull request most recent head 3836719

Please upload reports for the commit 3836719 to get more accurate results.

Additional details and impacted files
@@            Coverage Diff             @@
##              3.3   #14026      +/-   ##
==========================================
- Coverage   38.55%   38.52%   -0.04%     
==========================================
  Files        1895     1896       +1     
  Lines       79272    79313      +41     
  Branches    11528    11529       +1     
==========================================
- Hits        30560    30552       -8     
- Misses      44439    44483      +44     
- Partials     4273     4278       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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.

4 participants