ALPN configuration

33 views
Skip to first unread message

Stéphane Vaucher

unread,
Aug 16, 2019, 3:57:18 PM8/16/19
to OPS4J
Hi everyone,

I've been using using pax web for HTTP/1.1 communications, and I've tried setting things up for HTTP/2 and have some configuration issues. I would like some guidance to help me diagnose what's going wrong. If this is a typical configuration issue, I'll gladly update documentation on your wiki to help future users. If this is a code issue, I'll gladly share a fix if I find one. Questions are underlined.

Environment: 
  • jetty 9.4.18 
  • pax-web 7.2.10 
  • equinox org.eclipse.osgi_3.12.0.v20170512-1932
  • java 1.8.0_211
Main code I looked at JettyFactoryImpl.createSecureConnector.

In order to see if HTTP/2 should be enabled, it checks for the presence of these classes:

bundle.loadClass("org.eclipse.jetty.alpn.ALPN");
bundle.loadClass("org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory");
bundle.loadClass("org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory");

This check is correct. At this point, I can access the server if I explicitly specify HTTP/2 (e.g., using cURL), but not from a browser [1,2]. ALPN does not seem to be configured out of the box. [3,4]

Is that the case? Is there a specific bundle that should ensure gets started?

I didn't see an explicit instantiation of a ConnectionFactory for ALPN org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory. I tried adding one, but I haven't had much success. ALPNServerConnectionFactory fails to resolve an instance of org.eclipse.jetty.io.ssl.ALPNProcessor.Server.

The test I ran was to add another connection factory.
Class<?> alpnClass = bundle.loadClass("org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory");
alpnFactory = (NegotiatingServerConnectionFactory) ConstructorUtils.invokeConstructor(alpnClass, (Object) new String[] {"ssl", "http/2", "http/1.1"}); // << FAILS HERE
alpnFactory.setDefaultProtocol("http/1.1");
connectionFactories.add(alpnFactory);

The class exists (precondition described above), but it fails running ServiceLoader.load(Server.class) where Server is ALPNProcessor.Server.

Is there an OSGI way of setting this up?

To set this up, I saw in the Jetty documentation, that I should have the alpn-boot on my bootclasspath (currently org.mortbay.jetty.alpn.boot is loaded as a bundle) . The version distributed with pax-web seems older (w.r.t. to my JDK). I updated the Java set-up from within dev environment to include a version of org.mortbay.jetty.alpn.boot that is supposed to compatible with my version of my JDK. I also added the org.eclipse.jetty.alpn.openjdk8.server bundle to my environment. As far as I can tell ServiceLoaders have to be dealt with a special way according to https://osgi.org/specification/osgi.cmpn/7.0.0/service.loader.html.

Are there steps I should be following? 
Does anyone have a set-up like up mine up and running? I suspect that people running Java9 might not have this type of issue.
Thoughts?

Regards,
Stephane Vaucher

[1] Access directly using http2
$ curl --http2-prior-knowledge -k https://dev.com:9443                                                                    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0

[2] Access using http
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    64    0    64    0     0     64      0 --:--:-- --:--:-- --:--:--  2064
invalid_preface <<<< 
curl: (52) Empty reply from server

[3] Expected negotiation result
Checking with openssl, I see that I would expect something like:
$ openssl s_client -connect google.com:443 -alpn h2 | grep ALPN\ p
ALPN protocol: h2

[4] What I get
$ openssl s_client -connect dev:9443 -alpn h2 | grep ALPN\
No ALPN negotiated

Stéphane Vaucher

unread,
Nov 8, 2019, 3:23:06 PM11/8/19
to OPS4J
Hi everyone,

I managed to get things working after upgrading to Java11, but I needed to apply a few changes to JettyFactoryImpl. I'm unsure how alpn/h2 support is functional for others with the current state of the code.

When we find ALPN classes (alpnClassesAvailable), the main thing is that SSLConnectionFactory will lead to alpn and not to h2 following (significant changes are in bold):

//SAME
Class<?> comparatorClass = bundle.loadClass("org.eclipse.jetty.http2.HTTP2Cipher");

Comparator<String> cipherComparator = (Comparator<String>) FieldUtils.readDeclaredStaticField(comparatorClass, "COMPARATOR");
sslContextFactory.setCipherComparator(cipherComparator);

// Say that SSL should support alpn, not h2
sslFactory = new SslConnectionFactory(sslContextFactory, "alpn");
// was sslFactory = new SslConnectionFactory(sslContextFactory, "h2");

connectionFactories.add(sslFactory);

Class<?> loadClass = bundle.loadClass("org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory");
http2Factory = (AbstractConnectionFactory) ConstructorUtils.invokeConstructor(loadClass, httpsConfig);
connectionFactories.add(http2Factory);

//Explicitely configure ALPN
loadClass = bundle.loadClass("org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory");
alpnFactory = (NegotiatingServerConnectionFactory) ConstructorUtils.invokeConstructor(loadClass, (Object) new String[] {"ssl", "h2", "http/1.1"});
alpnFactory.setDefaultProtocol("h2");
connectionFactories.add(alpnFactory);

This leads the server to serve up h2 requests unless we explicitely requested http1.1.

Do these changes make sense to you?

The negociation process succeeds with both: 
curl -v for all requests lists:
* ALPN, offering h2
* ALPN, offering http/1.1

$ curl -k --http1.1 https://localhost:9443
* ALPN, server accepted to use http/1.1

$ curl -k --http2 https://localhost:9443

-v lists: * * ALPN, server accepted to use h2

Please let me know if these changes make sense. If so, let me know if you want a PR.

Regards,
Stephane Vaucher

Grzegorz Grzybek

unread,
Nov 12, 2019, 10:36:38 AM11/12/19
to op...@googlegroups.com
Hello

I'm usually lagging behind, cleaning some rooms after party's over. I joined many hypes when they stopped being a hype and I quite enjoy it.

But seriously - same with http/2 (thought I don't think the hype is over - it's nice, future-proof technology) - I only recently read about how it works (frames, streams, ..), so I can't be of much help here.

you said:

I managed to get things working after upgrading to Java11

Do you think it's required to use Java11? If not, then if you have PR + some test showing how to configure/use http2 with different containers (Jetty, Tomcat, Undertow) it'd be great to see it. If you checked only Jetty - that's still good.

For now, I can only say - please send the PR, I'll be happy to merge it.

regards
Grzegorz Grzybek


--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ops4j/8fe39fd4-5837-41df-bac6-d497cd20a759%40googlegroups.com.

Stéphane Vaucher

unread,
Nov 12, 2019, 12:08:07 PM11/12/19
to op...@googlegroups.com
Hi  Grzegorz,

Comments inline

I'm usually lagging behind, cleaning some rooms after party's over. I joined many hypes when they stopped being a hype and I quite enjoy it.

I don't exactly know the specific use-cases where http2 is better. From my limited/theoretical understanding, it can help with certain loads (probably unoptimized loads like images).
 
[...]
you said:

I managed to get things working after upgrading to Java11 

Do you think it's required to use Java11?

The change is not Java11-specific. I had many moving parts, and I got everything running after doing my upgrade to Java 11. It's only Java 11 tested. For execution on Java 8, it should be a matter of following the steps to configure the bundles correctly. These steps are documented outside pax-web (on the jetty web site).

>  If not, then if you have PR + some test showing how to configure/use http2 with different containers (Jetty, Tomcat, Undertow) it'd be great to see it. If you checked only Jetty - that's still good.  

I only changed the JettyFactoryImpl class, so, unless Tomcat and Undertow use that class, it won't work. I didn't see any existing automated tests for HTTP1.1 vs HTTP2 support. That actually why I was suspecting that HTTP2 wasn't supported correctly. I ran my tests using curl as detailed in my previous message. I'm on equinox, so my runtime infrastructure is likely different than yours.

For now, I can only say - please send the PR, I'll be happy to merge it.
 


--
-- 
Benchmark Consulting
460 rue St-Catherine St Ouest, Suite 612
Montréal, Québec H3B-1A7


CONFIDENTIALITY NOTICE: The information contained in this e-mail is confidential and may be proprietary information intended only for the use of the individual or entity to whom it is addressed. If the reader of this message is not the intended recipient, you are hereby notified that any viewing, dissemination, distribution, disclosure, copy or use of the information contained in this e-mail message is strictly prohibited. If you have received and/or are viewing this e-mail in error, please immediately notify the sender by reply e-mail, and delete it from your system without reading, forwarding, copying or saving in any manner. Thank you.
AVIS DE CONFIDENTIALITE: L’information contenue dans ce message est confidentiel, peut être protégé par le secret professionnel et est réservé à l'usage exclusif du destinataire. Toute autre personne est par les présentes avisée qu'il lui est strictement interdit de diffuser, distribuer ou reproduire ce message. Si vous avez reçu cette communication par erreur, veuillez la détruire immédiatement et en aviser l'expéditeur. Merci.

Grzegorz Grzybek

unread,
Nov 12, 2019, 1:25:30 PM11/12/19
to op...@googlegroups.com
Thank you very much Stéphane.

I'd be happy to investigate it further - give me a little time to review http/2 (h2 and h2c) in pax-web in general.

regards
Grzegorz Grzybek

Grzegorz Grzybek

unread,
Feb 19, 2020, 12:41:05 AM2/19/20
to op...@googlegroups.com
Hello again

How time flies...

Only now I'm deep in pax web code in order to do some pax-web 8 refactoring. My main goal is to make all 3 runtimes as similar (in terms of configuration and features) as possible. For Jetty, I found https://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-jdk9 and was quite surprised that JDK9+ has support for HTTP/2.
Normally my work is about fixing nasty deadlocks and memory leaks, so I rather don't have time checking what's new.

But because JDK14 is going to be released in <1 month, I think it's time to admit that world doesn't end on JDK8.

I'll look more at HTTP/2 support - also in Undertow and Tomcat, but I can't promise any particular date when it's done.

As Jean-Baptiste said, your PR has been moved to https://github.com/ops4j/org.ops4j.pax.web/pull/277. Please let me finish the refactoring and I'll take care of consistent HTTP/2 support (with tests).

regards
Grzegorz Grzybek

Reply all
Reply to author
Forward
0 new messages