Open spockz opened 4 years ago
So, I don't believe you need to cache the Engine
but rather the Context
. My understanding is that if the Context
is cached, then it will work. We provide the Netty4ClientEngineFactory
and Netty4ServerEngineFactory
as the defaults because they're the safest in terms of correctness, but they aren't the best in terms of performance.
As I mentioned in gitter, we mostly use ones which are tied to our internal security infrastructure. They create a single context and reuse it, because the parameters are known ahead of time. We also have one which precreates (some) contexts and then chooses the appropriate one based on the situation. I believe you would want something similar. I'm talking to the team now about seeing if we can/should open source that.
Hey @spockz, yesterday I moved our ExternalClientEngineFactory
into OSS Finagle. It's here. I recommend taking a look at it, and perhaps using it in your tests to see if it exhibits the behavior that you're expecting. If so, we can talk about how to write one that completely suits your use case.
Thank you for the example @ryanoneill. Caching the netty SslContext
indeed does make more sense as the context creates the engine. Based on the input I create my own ExternalContextClientEngineFactory
which gets a preconstructed netty SslContext
passed in. I also configured the client with the SslContextClientEngineFactoryClient
that takes a javax SSLContext
. The results are astonishing to me. The SslContextClientEngineFactory
is ±2.5x faster than the netty based client engine factory. Moreover, when making many connections the SslContextClientEngineFactory
is 10x faster per connection, indicating re-use. The ExternalContextClientEngineFactory
is as slow as the standard Netty4 based one.
[info] Benchmark Mode Cnt Score Error Units
[info] SslConnectionPerformanceBench.externalSslContextClientEngineFactoryClient thrpt 10 ≈ 10⁻⁷ ops/ns
[info] SslConnectionPerformanceBench.netty4ClientEngineFactoryClient thrpt 10 ≈ 10⁻⁷ ops/ns
[info] SslConnectionPerformanceBench.sslContextClientEngineFactoryClient thrpt 10 ≈ 10⁻⁶ ops/ns
[info] SslConnectionPerformanceBench.externalSslContextClientEngineFactoryClient avgt 10 14935413.067 ± 607647.575 ns/op
[info] SslConnectionPerformanceBench.netty4ClientEngineFactoryClient avgt 10 14478829.727 ± 1718539.667 ns/op
[info] SslConnectionPerformanceBench.sslContextClientEngineFactoryClient avgt 10 1259970.414 ± 163441.278 ns/op
[info] SslConnectionPerformanceBench.externalSslContextClientEngineFactoryClient ss 10 23296255.900 ± 2266746.677 ns/op
[info] SslConnectionPerformanceBench.netty4ClientEngineFactoryClient ss 10 23388622.700 ± 1750611.302 ns/op
[info] SslConnectionPerformanceBench.sslContextClientEngineFactoryClient ss 10 8867196.300 ± 2869120.745 ns/op
Do you have any explanations for this? I had to copy some finagle private classes btw.
We provide the Netty4ClientEngineFactory and Netty4ServerEngineFactory as the defaults because they're the safest in terms of correctness, but they aren't the best in terms of performance.
Can you share a bit more on why it is more "correct" and "safe" to use a context per connection instead of re-using it? Is it because settings might have been changed on either side since the last connection was established?
No TLS Session re-use when using
Netty4ClientEngineFactory
(default)Expected behavior
When establishing a second connection between the same client and server instance the TLS sessions should be re-used.
Actual behavior
Each connection gets its own TLS session when configuring the client with
SslClientConfiguration
.Using the default
SslClientEngineFactory
leads to using theNetty4ClientEngineFactory
which has this behaviour. Configuring the sslcontext directly with.withTransport.tls(SSLContext)
leads to using theSslContextClientEngineFactory
which does work.Steps to reproduce the behavior
See testcases: https://github.com/spockz/finagle-tls-session-reuse/blob/master/src/test/scala/com/github/spockz/finagle/it/tls/TlsTest.scala, output:
Possible fixes
Failure(renegotiation unsupported..
. This appears to be because the engine is already destroyed.SslContextClientEngineFactory
mitigates the session issue, but this drops back to using JSSE for TLS which drops performance on JDK8 and loses H2.