add option to enable compression for gRPC-server (#133)
* add grpc server compression * change compression config defaults * fix review issue * add note about compression in readme * add compression section to server config doc
This commit is contained in:
@@ -59,6 +59,11 @@ port: 2449
|
||||
tls:
|
||||
enabled: false
|
||||
|
||||
compression:
|
||||
grpc:
|
||||
server:
|
||||
enabled: false
|
||||
|
||||
proxy:
|
||||
host: 0.0.0.0
|
||||
port: 8545
|
||||
@@ -103,6 +108,7 @@ Which sets the following:
|
||||
|
||||
- gRPC access through 0.0.0.0:2449
|
||||
** TLS security is disabled (_please don't use in production!_)
|
||||
** compression is disabled for gRPC server (enabled by default)
|
||||
- JSON RPC access through 0.0.0.0:8545 (both HTTP and WebsScket)
|
||||
** proxy requests to Ethereum and Kovan upstreams
|
||||
** request path for Ethereum Mainnet is `/eth`, `/kovan` for Kovan Testnet, and `/btc` for bitcoin
|
||||
|
||||
@@ -21,6 +21,12 @@ tls:
|
||||
client:
|
||||
require: true
|
||||
ca: "ca.crt"
|
||||
|
||||
compression:
|
||||
grpc:
|
||||
server:
|
||||
enabled: false
|
||||
|
||||
cluster:
|
||||
include: "upstreams.yaml"
|
||||
----
|
||||
@@ -29,6 +35,7 @@ It configures following:
|
||||
|
||||
- server is listening with gRCP API on `0.0.0.0:2449`
|
||||
- TLS is enabled
|
||||
- compression is disabled for gRPC server (enabled by default)
|
||||
- server certificate is located at `server.crt` with the key for it at `server.p8.key`
|
||||
- the server requires a client authentication by TLS client certificate signed by `ca.crt` certificate
|
||||
- no JSON RPC is configured
|
||||
@@ -51,6 +58,10 @@ a| `tls`
|
||||
| TLS configuration for gRPC.
|
||||
See link:08-authentication.adoc[Authentication] for details
|
||||
|
||||
a| `compression`
|
||||
|
|
||||
| Compression configuration
|
||||
|
||||
a| `proxy`
|
||||
|
|
||||
| Proxy configuration
|
||||
@@ -60,6 +71,21 @@ a| `upstreams`
|
||||
| Upstreams configuration
|
||||
|===
|
||||
|
||||
=== Compression
|
||||
Compression is enabled by default on the gRPC server
|
||||
(the server accepts compressed requests and can send compressed responses).
|
||||
Responses will be compressed if a client supports compression (sends relevant headers),
|
||||
otherwise, communication will be uncompressed.
|
||||
But if for some reason you need to disable compression forcibly,
|
||||
add the lines below to the config:
|
||||
[source,yaml]
|
||||
----
|
||||
compression:
|
||||
grpc:
|
||||
client:
|
||||
enabled: false
|
||||
----
|
||||
|
||||
=== Enabling JSON RPC proxy
|
||||
|
||||
In addition to the gRPC protocol, Dshackle provides access compatible with Bitcoin and Ethereum JSON RPC.
|
||||
|
||||
@@ -18,7 +18,11 @@ package io.emeraldpay.dshackle
|
||||
|
||||
import io.emeraldpay.dshackle.config.MainConfig
|
||||
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerGrpc
|
||||
import io.grpc.Codec
|
||||
import io.grpc.Server
|
||||
import io.grpc.ServerCall
|
||||
import io.grpc.ServerCallHandler
|
||||
import io.grpc.ServerInterceptor
|
||||
import io.grpc.netty.NettyServerBuilder
|
||||
import io.micrometer.core.instrument.Metrics
|
||||
import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics
|
||||
@@ -42,6 +46,17 @@ open class GrpcServer(
|
||||
|
||||
private var server: Server? = null
|
||||
|
||||
class CompressionInterceptor : ServerInterceptor {
|
||||
override fun <ReqT : Any, RespT : Any> interceptCall(
|
||||
call: ServerCall<ReqT, RespT>,
|
||||
headers: io.grpc.Metadata,
|
||||
next: ServerCallHandler<ReqT, RespT>
|
||||
): ServerCall.Listener<ReqT> {
|
||||
call.setCompression(Codec.Gzip().messageEncoding)
|
||||
return next.startCall(call, headers)
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
fun start() {
|
||||
log.info("Starting gRPC Server...")
|
||||
@@ -53,9 +68,12 @@ open class GrpcServer(
|
||||
.let {
|
||||
if (mainConfig.accessLogConfig.enabled) {
|
||||
it.intercept(accessHandler)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
if (mainConfig.compression.grpc.serverEnabled) {
|
||||
it.intercept(CompressionInterceptor())
|
||||
log.info("Compression enabled for gRPC server")
|
||||
}
|
||||
it
|
||||
}
|
||||
|
||||
tlsSetup.setupServer("Native gRPC", mainConfig.tls, true)?.let {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.emeraldpay.dshackle.config
|
||||
|
||||
class CompressionConfig(
|
||||
var grpc: GRPC = GRPC()
|
||||
) {
|
||||
/**
|
||||
* Config example:
|
||||
* ```
|
||||
* compression:
|
||||
* grpc:
|
||||
* server:
|
||||
* enabled: true
|
||||
* client:
|
||||
* enabled: false
|
||||
* ```
|
||||
*/
|
||||
class GRPC(
|
||||
var serverEnabled: Boolean = true,
|
||||
var clientEnabled: Boolean = true
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun default(): CompressionConfig {
|
||||
return CompressionConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.emeraldpay.dshackle.config
|
||||
|
||||
import org.yaml.snakeyaml.nodes.MappingNode
|
||||
import java.io.InputStream
|
||||
|
||||
class CompressionConfigReader : YamlConfigReader(), ConfigReader<CompressionConfig> {
|
||||
fun read(input: InputStream): CompressionConfig? {
|
||||
val configNode = readNode(input)
|
||||
return read(configNode)
|
||||
}
|
||||
|
||||
override fun read(input: MappingNode?): CompressionConfig {
|
||||
val config = CompressionConfig()
|
||||
getMapping(input, "compression")?.let { node ->
|
||||
readGRPC(config.grpc, getMapping(node, "grpc"))
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
private fun readGRPC(grpcCompressionConfig: CompressionConfig.GRPC, input: MappingNode?) {
|
||||
getMapping(input, "server")?.let { serverNode ->
|
||||
getValueAsBool(serverNode, "enabled")?.let {
|
||||
grpcCompressionConfig.serverEnabled = it
|
||||
}
|
||||
}
|
||||
getMapping(input, "client")?.let { clientNode ->
|
||||
getValueAsBool(clientNode, "enabled")?.let {
|
||||
grpcCompressionConfig.clientEnabled = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,4 +28,5 @@ class MainConfig {
|
||||
var accessLogConfig: AccessLogConfig = AccessLogConfig.default()
|
||||
var health: HealthConfig = HealthConfig.default()
|
||||
var signature: SignatureConfig? = null
|
||||
var compression: CompressionConfig = CompressionConfig.default()
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class MainConfigReader(
|
||||
private val accessLogReader = AccessLogReader()
|
||||
private val healthConfigReader = HealthConfigReader()
|
||||
private val signatureConfigReader = SignatureConfigReader(fileResolver)
|
||||
private val compressionConfigReader = CompressionConfigReader()
|
||||
|
||||
fun read(input: InputStream): MainConfig? {
|
||||
val configNode = readNode(input)
|
||||
@@ -83,6 +84,9 @@ class MainConfigReader(
|
||||
signatureConfigReader.read(input).let {
|
||||
config.signature = it
|
||||
}
|
||||
compressionConfigReader.read(input).let {
|
||||
config.compression = it
|
||||
}
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user