-
Notifications
You must be signed in to change notification settings - Fork 41.2k
Common way to configure HTTP/2 #9981
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
Conversation
1d54dc1
to
bb36b9d
Compare
Thanks for the PR. Please be aware that we have another PR that proposes to enable HTTP/2 by default with Tomcat: #9964 |
Thanks for mentioning. I haven't seen this one, yet. Please note, that I haven't been able to make it work in all three containers, yet. Undertow works out of the box, but Jetty and Tomcat are more involved and I'm still working on them. |
For tomcat, you need to:
Then your changes will work. (If you don't have tomcat native installed, tomcat will log an error and http2 won't work, but everything will otherwise still function) |
Thanks for the hint, @candrews. I already saw that error message, when I tried my implementation. As I'm on Windows, I struggled to get it work using tomcat-native. I also tried to make it work using Java 9, but was unable to do so. If you don't mind, I'd like to incorporate your solution using AprLifeCycleListener in my PR. Then the only thing left to do would be Jetty support. I'll work on that later this evening. |
Of course, please do :) FWIW, I think AprLifeCycleListener should be always added, regardless of the status of the new http2 setting. |
Also, I think http2 should be enabled by default - why would it not be enabled by default? |
I think when it works out of the box on all three Servlet Containers, we should consider enabling it by default. But until then, I think it's better to leave it disabled, i.e. I'd only enable it once Tomcat no longer needs tomcat-native to run it. Otherwise the error message might be misleading. |
No server can support HTTP/2 on Java 8 without something like tomcat's tomcat-native for ALPN support. I believe that enabling http2 by default and documenting that unless the selected server's native support library is installed or Java 9 is in use that HTTP/2 won't actually be enabled is the best way to go. |
Maybe some of the Spring Boot main contributors (@wilkinsona, @philwebb, @snicoll, @dsyer) can share their thoughts on this topic? |
Undertow's an exception to that. They use a "nasty hack" to avoid the need for modifying the bootstrap class path or using native code.
I think we definitely need to avoid a configuration that will lead to Tomcat logging an error (or warning) at startup.
I could certainly be persuaded that enabling HTTP/2 by default is the way to go, but only if we can avoid the aforementioned error message from Tomcat. Perhaps we can automatically enable it with Tomcat but only if the necessary native component is available? |
A tricky thing here would be to detect, whether a user explicitly wants to have HTTP/2 enabled on Tomcat – in that case you probably want to show the error from Tomcat that helps with properly configuring tomcat-native – or whether HTTP/2 is enabled by default. In that case you want to avoid the error message and silently fall back to HTTP/1.1. |
That's a good point. I haven't looked closely enough at how Tomcat finds the native library and the error it produces when it's not there to know for certain what our options are here. It feels like a general auto-configuration problem, though. A condition (that will then provide diagnostics in the auto-config report) could be one avenue that's worth exploring. |
You can find the relevant code in the init() method of Tomcat's/Catalina's AprLifecycleListener. At least it's a starting point. Thanks for your advice. I will try to find a solution after work. |
Equipped with my notebook instead of my phone I found Unfortunately that method throws an
😕 I'm still looking for another solution... |
Jetty relies on modifying the bootclasspath. I'm not sure whether to require Spring Boot users to do that when running their app is a viable option. Two solutions come to my mind:
What do you think? Is there a general solution to problems like this one, where a feature is not equally supported by all three Servlet Containers? |
Maybe better than writing our own hack would be to use netty-tcnative-boringssl-static, which bundles tomcat-native binaries for common platforms. But I also don't really like this solution as it would make spring-boot fat jars a lot fatter. So I suggest enabling HTTP/2 only on Java 9 by default would be a sane solution. On Java 8 we could require users to provide the container specific solution to the ALPN problem themselves, if they want to enable HTTP/2. |
I don't think we should write our own nasty hack. Enabling HTTP/2 by default only on Java 9 seems like a good compromise to me. Particularly if we can also make things a bit easier for those on Java 8 as well (that could just be documentation, or documentation and some simplified configuration). |
143f2eb
to
02ed20d
Compare
Requiring Java9 for the whole build makes this PR unlikely to be merged. Do you need Java9 at runtime or are you compiling against Java 9 APIs? In the case of the latter, we need to go reflection route. As for the former, we need something that prevents the test to run when Java9 is not present, see #9530 |
@snicoll Thanks for the hint. I just rebased this feature on the branch jdk9, which already configures Travis CI to run using I can mark the test, which requires Java 9, as Do you have a clue on how to proceed? |
It turned out that it was a little harder to get Jetty's HTTP/2 support to work on Java 9. It took some time until I found the brand new <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-java-server</artifactId>
<version>9.4.7.RC0</version> which provides ALPN support for Jetty using Java 9. As this is a first Release Candidate for Jetty 9.4.7, it might make sense to wait for the first Jetty 9.4.7 stable release before this will be supported out of the box by Spring Boot. Here's the thread where I found out about the module: jetty/jetty.project#486 |
Since Jetty 9.4.7 has been released on 2017-09-14, I'll continue working on this branch. |
890bdcc
to
ff3f727
Compare
in Jetty HTTP/2 sample
ff3f727
to
5817e10
Compare
I've configured |
Could we take a step back and stop adding things in that PR? Let me come up with a detailed proposal in #10043 first and then we can cherry-pick things from this PR. |
Awesome to hear that you're making progress. |
Cherry-picking was mostly done from #10041 |
This PR is an attempt to provide a solution to #3350 that tries to be Servlet Container agnostic.
This PR is currently still in progress. Yet, I'd like to collect some thoughts on the approach taken, since PR #3904 already got closed.
My approach is to introduce a new property
server.http2.enabled=true
and then customize Tomcat, Undertow and Jetty to enable HTTP/2 in theDefaultServletWebServerFactoryCustomizer
. There, each Servlet Container can be configured in their own way.I could also think of having a similar property somewhere under
spring.http.
. If I understand the logic of Spring Boot's properties right, as this property doesn't change the behavior of Spring directly, having it underserver.http2.
is better.Please do not build upon this PR as I'm going to rebase onto the latest master and maybe fix issues in old commits as I proceed. Also, it's not fully functional as of now.