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:
Vadim Vlasov
2023-02-10 17:27:52 +08:00
committed by GitHub
parent fc36e63ea6
commit 8649cc03aa
7 changed files with 116 additions and 2 deletions

View File

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

View File

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

View File

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

View File

@@ -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()
}
}
}

View File

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

View File

@@ -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()
}

View File

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