Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
imp(server): Add query-only mode flag for gRPC (#1360)
Browse files Browse the repository at this point in the history
* add grpc only mode flag

* add change log

* add tmNode nil check

* only flag to modes

* fix close for query mode

* fix hint

* keep grpc-only & json-rpc-only

* rm space

* mv apiSrv close

* mv cpuProfileCleanup

* mv tmNode stop

* disable indexer on query only

which need tm client on start

* update nix

* revert json-rpc-only change
  • Loading branch information
mmsqe authored Oct 19, 2022
1 parent db94d8e commit 236ca33
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 87 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (ledger) [#1277](https://github.com/evmos/ethermint/pull/1277) Add Ledger preprocessing transaction hook for EIP-712-signed Cosmos payloads.
* (rpc) [#1296](https://github.com/evmos/ethermint/pull/1296) Add RPC Backend unit tests.
* (rpc) [#1352](https://github.com/evmos/ethermint/pull/1352) Make the grpc queries run concurrently, don't block the consensus state machine.
* (cli) [#1360](https://github.com/evmos/ethermint/pull/1360) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag.
* (rpc) [#1378](https://github.com/evmos/ethermint/pull/1378) Add support for EVM RPC metrics

### Bug Fixes
Expand Down
1 change: 1 addition & 0 deletions server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (

// GRPC-related flags.
const (
GRPCOnly = "grpc-only"
GRPCEnable = "grpc.enable"
GRPCAddress = "grpc.address"
GRPCWebEnable = "grpc-web.enable"
Expand Down
173 changes: 86 additions & 87 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ which accepts a path for the resulting pprof file.
cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
cmd.Flags().String(srvflags.AppDBBackend, "", "The type of database for application and snapshots databases")

cmd.Flags().Bool(srvflags.GRPCOnly, false, "Start the node in gRPC query only mode without Tendermint process")
cmd.Flags().Bool(srvflags.GRPCEnable, true, "Define if the gRPC server should be enabled")
cmd.Flags().String(srvflags.GRPCAddress, serverconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
cmd.Flags().Bool(srvflags.GRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)")
Expand All @@ -158,7 +159,7 @@ which accepts a path for the resulting pprof file.
cmd.Flags().Bool(srvflags.RPCEnable, false, "Defines if Cosmos-sdk REST server should be enabled")
cmd.Flags().Bool(srvflags.EnabledUnsafeCors, false, "Defines if CORS should be enabled (unsafe - use it at your own risk)")

cmd.Flags().Bool(srvflags.JSONRPCEnable, true, "Define if the gRPC server should be enabled")
cmd.Flags().Bool(srvflags.JSONRPCEnable, true, "Define if the JSON-RPC server should be enabled")
cmd.Flags().StringSlice(srvflags.JSONRPCAPI, config.GetDefaultAPINamespaces(), "Defines a list of JSON-RPC namespaces that should be enabled")
cmd.Flags().String(srvflags.JSONRPCAddress, config.DefaultJSONRPCAddress, "the JSON-RPC server address to listen on")
cmd.Flags().String(srvflags.JSONWsAddress, config.DefaultJSONRPCWsAddress, "the JSON-RPC WS server address to listen on")
Expand Down Expand Up @@ -239,8 +240,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
cfg := ctx.Config
home := cfg.RootDir
logger := ctx.Logger
var cpuProfileCleanup func() error

if cpuProfile := ctx.Viper.GetString(srvflags.CPUProfile); cpuProfile != "" {
fp, err := ethdebug.ExpandHome(cpuProfile)
if err != nil {
Expand All @@ -257,15 +256,13 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
return err
}

cpuProfileCleanup = func() error {
defer func() {
ctx.Logger.Info("stopping CPU profiler", "profile", cpuProfile)
pprof.StopCPUProfile()
if err := f.Close(); err != nil {
logger.Error("failed to close CPU profiler file", "error", err.Error())
return err
}
return nil
}
}()
}

traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
Expand Down Expand Up @@ -313,30 +310,47 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
}

genDocProvider := node.DefaultGenesisDocProviderFunc(cfg)
tmNode, err := node.NewNode(
cfg,
pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()),
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
node.DefaultDBProvider,
node.DefaultMetricsProvider(cfg.Instrumentation),
ctx.Logger.With("server", "node"),
var (
tmNode *node.Node
gRPCOnly = ctx.Viper.GetBool(srvflags.GRPCOnly)
)
if err != nil {
logger.Error("failed init node", "error", err.Error())
return err
}
if gRPCOnly {
ctx.Logger.Info("starting node in query only mode; Tendermint is disabled")
config.GRPC.Enable = true
config.JSONRPC.EnableIndexer = false
} else {
tmNode, err = node.NewNode(
cfg,
pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()),
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
node.DefaultDBProvider,
node.DefaultMetricsProvider(cfg.Instrumentation),
ctx.Logger.With("server", "node"),
)
if err != nil {
logger.Error("failed init node", "error", err.Error())
return err
}

if err := tmNode.Start(); err != nil {
logger.Error("failed start tendermint server", "error", err.Error())
return err
if err := tmNode.Start(); err != nil {
logger.Error("failed start tendermint server", "error", err.Error())
return err
}

defer func() {
if tmNode.IsRunning() {
_ = tmNode.Stop()
}
logger.Info("Bye!")
}()
}

// Add the tx service to the gRPC router. We only need to register this
// service if API or gRPC or JSONRPC is enabled, and avoid doing so in the general
// case, because it spawns a new local tendermint RPC client.
if config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || config.JSONRPC.EnableIndexer {
if (config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || config.JSONRPC.EnableIndexer) && tmNode != nil {
clientCtx = clientCtx.WithClient(local.New(tmNode))

app.RegisterTxService(clientCtx)
Expand Down Expand Up @@ -429,7 +443,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
apiSrv = api.New(clientCtx, ctx.Logger.With("server", "api"))
app.RegisterAPIRoutes(apiSrv, config.API)
errCh := make(chan error)

go func() {
if err := apiSrv.Start(config.Config); err != nil {
errCh <- err
Expand All @@ -441,6 +454,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
return err
case <-time.After(types.ServerStartTime): // assume server started successfully
}
defer apiSrv.Close()
}

var (
Expand All @@ -452,13 +466,60 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
if err != nil {
return err
}
defer grpcSrv.Stop()
if config.GRPCWeb.Enable {
grpcWebSrv, err = servergrpc.StartGRPCWeb(grpcSrv, config.Config)
if err != nil {
ctx.Logger.Error("failed to start grpc-web http server", "error", err)
return err
}
defer func() {
if err := grpcWebSrv.Close(); err != nil {
logger.Error("failed to close the grpcWebSrc", "error", err.Error())
}
}()
}
}

var (
httpSrv *http.Server
httpSrvDone chan struct{}
)

if config.JSONRPC.Enable {
genDoc, err := genDocProvider()
if err != nil {
return err
}

clientCtx := clientCtx.WithChainID(genDoc.ChainID)

tmEndpoint := "/websocket"
tmRPCAddr := cfg.RPC.ListenAddress
httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, &config, idxer)
if err != nil {
return err
}
defer func() {
shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
defer cancelFn()
if err := httpSrv.Shutdown(shutdownCtx); err != nil {
logger.Error("HTTP server shutdown produced a warning", "error", err.Error())
} else {
logger.Info("HTTP server shut down, waiting 5 sec")
select {
case <-time.Tick(5 * time.Second):
case <-httpSrvDone:
}
}
}()
}

// At this point it is safe to block the process if we're in query only mode as
// we do not need to start Rosetta or handle any Tendermint related processes.
if gRPCOnly {
// wait for signal capture and gracefully return
return server.WaitForQuitSignals()
}

var rosettaSrv crgserver.Server
Expand Down Expand Up @@ -496,68 +557,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
case <-time.After(types.ServerStartTime): // assume server started successfully
}
}

var (
httpSrv *http.Server
httpSrvDone chan struct{}
)

if config.JSONRPC.Enable {
genDoc, err := genDocProvider()
if err != nil {
return err
}

clientCtx := clientCtx.WithChainID(genDoc.ChainID)

tmEndpoint := "/websocket"
tmRPCAddr := cfg.RPC.ListenAddress
httpSrv, httpSrvDone, err = StartJSONRPC(ctx, clientCtx, tmRPCAddr, tmEndpoint, &config, idxer)
if err != nil {
return err
}
}

defer func() {
if tmNode.IsRunning() {
_ = tmNode.Stop()
}

if cpuProfileCleanup != nil {
_ = cpuProfileCleanup()
}

if apiSrv != nil {
_ = apiSrv.Close()
}

if grpcSrv != nil {
grpcSrv.Stop()
if grpcWebSrv != nil {
if err := grpcWebSrv.Close(); err != nil {
logger.Error("failed to close the grpcWebSrc", "error", err.Error())
}
}
}

if httpSrv != nil {
shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
defer cancelFn()

if err := httpSrv.Shutdown(shutdownCtx); err != nil {
logger.Error("HTTP server shutdown produced a warning", "error", err.Error())
} else {
logger.Info("HTTP server shut down, waiting 5 sec")
select {
case <-time.Tick(5 * time.Second):
case <-httpSrvDone:
}
}
}

logger.Info("Bye!")
}()

// Wait for SIGINT or SIGTERM signal
return server.WaitForQuitSignals()
}
Expand Down

0 comments on commit 236ca33

Please sign in to comment.