github.com/aergoio/aergo@v1.3.1/cmd/aergosvr/aergosvr.go (about)

     1  /**
     2   *  @file
     3   *  @copyright defined in aergo/LICENSE.txt
     4   */
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"net/http"
    10  	_ "net/http/pprof"
    11  	"os"
    12  	"strconv"
    13  	"strings"
    14  
    15  	"github.com/aergoio/aergo/p2p/p2pkey"
    16  
    17  	"github.com/aergoio/aergo-lib/log"
    18  	"github.com/aergoio/aergo/account"
    19  	"github.com/aergoio/aergo/chain"
    20  	"github.com/aergoio/aergo/config"
    21  	"github.com/aergoio/aergo/consensus"
    22  	"github.com/aergoio/aergo/consensus/impl"
    23  	"github.com/aergoio/aergo/internal/common"
    24  	"github.com/aergoio/aergo/mempool"
    25  	"github.com/aergoio/aergo/p2p"
    26  	"github.com/aergoio/aergo/pkg/component"
    27  	polarisclient "github.com/aergoio/aergo/polaris/client"
    28  	"github.com/aergoio/aergo/rpc"
    29  	"github.com/aergoio/aergo/syncer"
    30  	"github.com/opentracing/opentracing-go"
    31  	zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing"
    32  	"github.com/spf13/cobra"
    33  )
    34  
    35  var (
    36  	gitRevision, gitBranch string
    37  )
    38  
    39  func main() {
    40  	if err := rootCmd.Execute(); err != nil {
    41  		os.Exit(1)
    42  	}
    43  }
    44  
    45  var (
    46  	rootCmd = &cobra.Command{
    47  		Use:   "aergosvr",
    48  		Short: "Aergo Server",
    49  		Long:  "Aergo Server Full-node implementation",
    50  		PersistentPreRun: func(cmd *cobra.Command, args []string) {
    51  			if homePath != "" && configFilePath != "" && verbose {
    52  				fmt.Println("ignore home path if given config file has valid configuration")
    53  			}
    54  		},
    55  		Run: rootRun,
    56  	}
    57  	homePath       string
    58  	configFilePath string
    59  	enableTestmode bool
    60  	useTestnet     bool
    61  
    62  	verbose bool
    63  
    64  	svrlog *log.Logger
    65  
    66  	cfg *config.Config
    67  )
    68  
    69  func init() {
    70  	cobra.OnInitialize(initConfig)
    71  
    72  	localFlags := rootCmd.Flags()
    73  	localFlags.SortFlags = false
    74  	localFlags.BoolVar(&useTestnet, "testnet", false, "use Aergo TestNet; this only affects if there's no genesis block")
    75  	localFlags.BoolVar(&enableTestmode, "testmode", false, "enable unsafe test mode (skips certain validations); can NOT use with --testnet")
    76  
    77  	fs := rootCmd.PersistentFlags()
    78  	fs.StringVar(&homePath, "home", "", "path of aergo home")
    79  	fs.StringVar(&configFilePath, "config", "", "path of configuration file")
    80  	fs.BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
    81  
    82  }
    83  
    84  func initConfig() {
    85  	serverCtx := config.NewServerContext(homePath, configFilePath)
    86  	cfg = serverCtx.GetDefaultConfig().(*config.Config)
    87  	err := serverCtx.LoadOrCreateConfig(cfg)
    88  	if err != nil {
    89  		fmt.Printf("Fail to load configuration file %v: %v", serverCtx.Vc.ConfigFileUsed(), err.Error())
    90  		os.Exit(1)
    91  	}
    92  	if enableTestmode {
    93  		cfg.EnableTestmode = true
    94  	}
    95  	if useTestnet {
    96  		cfg.UseTestnet = true
    97  	}
    98  	if cfg.EnableTestmode && cfg.UseTestnet {
    99  		fmt.Println("Turn off test mode for Aergo Public Chains")
   100  		os.Exit(1)
   101  	}
   102  }
   103  
   104  func configureZipkin() {
   105  	protocol := cfg.Monitor.ServerProtocol
   106  	endpoint := cfg.Monitor.ServerEndpoint
   107  	var collector zipkin.Collector
   108  	var err error
   109  	if "http" == protocol || "https" == protocol {
   110  		zipkinURL := fmt.Sprintf("%s://%s/api/v1/spans", protocol, endpoint)
   111  		collector, err = zipkin.NewHTTPCollector(zipkinURL)
   112  		if err != nil {
   113  			panic("Error connecting to zipkin server at " + zipkinURL + ". Error: " + err.Error())
   114  		}
   115  	} else if "kafka" == protocol {
   116  		endpoints := strings.Split(endpoint, ",")
   117  		collector, err = zipkin.NewKafkaCollector(endpoints)
   118  		if err != nil {
   119  			panic("Error connecting to kafka endpoints at " + endpoint + ". Error: " + err.Error())
   120  		}
   121  	}
   122  
   123  	if nil != collector {
   124  		myEndpoint := cfg.RPC.NetServiceAddr + ":" + strconv.Itoa(cfg.RPC.NetServicePort)
   125  		tracer, err := zipkin.NewTracer(zipkin.NewRecorder(collector, false, myEndpoint, "aergosvr"))
   126  		if err != nil {
   127  			panic("Error starting new zipkin tracer. Error: " + err.Error())
   128  		}
   129  		opentracing.InitGlobalTracer(tracer)
   130  	}
   131  }
   132  
   133  func rootRun(cmd *cobra.Command, args []string) {
   134  
   135  	svrlog = log.NewLogger("asvr")
   136  	svrlog.Info().Str("revision", gitRevision).Str("branch", gitBranch).Msg("AERGO SVR STARTED")
   137  
   138  	configureZipkin()
   139  
   140  	if cfg.EnableProfile {
   141  		svrlog.Info().Msgf("Enable Profiling on localhost: %d", cfg.ProfilePort)
   142  		go func() {
   143  			err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", cfg.ProfilePort), nil)
   144  			svrlog.Info().Err(err).Msg("Run Profile Server")
   145  		}()
   146  	}
   147  
   148  	if cfg.EnableTestmode {
   149  		svrlog.Warn().Msgf("Running with unsafe test mode. Turn off test mode for production use!")
   150  	}
   151  
   152  	p2pkey.InitNodeInfo(&cfg.BaseConfig, cfg.P2P, githash, svrlog)
   153  
   154  	compMng := component.NewComponentHub()
   155  
   156  	chainSvc := chain.NewChainService(cfg)
   157  
   158  	mpoolSvc := mempool.NewMemPoolService(cfg, chainSvc)
   159  	rpcSvc := rpc.NewRPC(cfg, chainSvc, githash)
   160  	syncSvc := syncer.NewSyncer(cfg, chainSvc, nil)
   161  	p2pSvc := p2p.NewP2P(cfg, chainSvc)
   162  	pmapSvc := polarisclient.NewPolarisConnectSvc(cfg.P2P, p2pSvc)
   163  
   164  	var accountSvc component.IComponent
   165  	if cfg.Personal {
   166  		accountSvc = account.NewAccountService(cfg, chainSvc.SDB())
   167  	}
   168  
   169  	// Register services to Hub. Don't need to do nil-check since Register
   170  	// function skips nil parameters.
   171  	if !cfg.Blockchain.VerifyOnly {
   172  		compMng.Register(chainSvc, mpoolSvc, rpcSvc, syncSvc, p2pSvc, accountSvc, pmapSvc)
   173  	} else {
   174  		compMng.Register(chainSvc, mpoolSvc, rpcSvc)
   175  	}
   176  
   177  	consensusSvc, err := impl.New(cfg, compMng, chainSvc, p2pSvc, rpcSvc)
   178  	if err != nil {
   179  		svrlog.Error().Err(err).Msg("Failed to start consensus service.")
   180  		os.Exit(1)
   181  	}
   182  
   183  	// All the services objects including Consensus must be created before the
   184  	// actors are started.
   185  	compMng.Start()
   186  
   187  	if cfg.Consensus.EnableBp {
   188  		// Warning: The consensus service must start after all the other
   189  		// services.
   190  		consensus.Start(consensusSvc)
   191  	}
   192  
   193  	var interrupt = common.HandleKillSig(func() {
   194  		consensus.Stop(consensusSvc)
   195  		compMng.Stop()
   196  	}, svrlog)
   197  
   198  	// Wait main routine to stop
   199  	<-interrupt.C
   200  }