fabric源码解读:Peer节点启动

fabric源码解读:Peer节点启动

fabric源码解读:Peer节点启动_第1张图片

命令

peer node start

peer/mian.go中调用mainCmd.Execute()

func main() {
	...
	// 执行具体子命令
	if mainCmd.Execute() != nil {
		os.Exit(1)
	}
	logger.Info("Exiting.....")
}
fabric源码解读:Peer节点启动_第2张图片

peer/node/start.go

var nodeStartCmd = &cobra.Command{
	Use:   "start",
	Short: "Starts the node.",
	Long:  `Starts a node that interacts with the network.`,
	RunE: func(cmd *cobra.Command, args []string) error {
        // 执行serve方法
		return serve(args)
	},
}

peer节点启动流程:

  • 获取msp类型

  • 注册资源访问策略 aclmgmt.RegisterACLProvider(nil)

  • 初始化本地账本管理器 ledgermgmt.Initialize(peer.ConfigTxProcessors)

  • 创建grpc服务①:PeerServer 端口 7051

  • 创建grpc服务②:Eventhub,端口7053

  • 创建grpc服务③:DeliverEvents,注册到peerServer上,端口7051

  • 创建grpc服务④:链码管理服务

  • 创建grpc服务 ⑤: Admin注册到PeerServer上 端口7051

  • 隐私数据处理: 使用goosip协议进行分发

  • 创建grpc服务⑥:背书服务 端口7051

  • 初始化goosip连接与加密组件

  • 安装系统连码 initSysCCs并初始化peer.Initialize(func(cid string) {}

  • 开启PeerServer Grpc服务

  • 设置日志模块

func serve(args []string) error {
  // 获取msp类型,分为idemix类型和fabric 。v1.1 只支持fabric,
	mspType := mgmt.GetLocalMSP().GetType()
	if mspType != msp.FABRIC {
		panic("Unsupported msp type " + msp.ProviderTypeToString(mspType))
	}

	logger.Infof("Starting %s", version.GetInfo())

	//注册资源策略
	aclmgmt.RegisterACLProvider(nil)

	//初始化本地账本管理器
	ledgermgmt.Initialize(peer.ConfigTxProcessors)

	// Parameter overrides must be processed before any parameters are
	// cached. Failures to cache cause the server to terminate immediately.
	// 设置开发模式
	if chaincodeDevMode {
		logger.Info("Running in chaincode development mode")
		logger.Info("Disable loading validity system chaincode")

		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)

	}
	//缓存配置信息:peer地址、节点
	if err := peer.CacheConfiguration(); err != nil {
		return err
	}
	// 获取缓存的EndPoint节点信息
	peerEndpoint, err := peer.GetPeerEndpoint()
	if err != nil {
		err = fmt.Errorf("Failed to get Peer Endpoint: %s", err)
		return err
	}
	var peerHost string
	// 获取peer地址
	peerHost, _, err = net.SplitHostPort(peerEndpoint.Address)
	if err != nil {
		return fmt.Errorf("peer address is not in the format of host:port: %v", err)
	}

	listenAddr := viper.GetString("peer.listenAddress")


	serverConfig, err := peer.GetServerConfig()
	if err != nil {
		logger.Fatalf("Error loading secure config for peer (%s)", err)
	}
	// 创建grpc服务① Peer7051
	peerServer, err := peer.CreatePeerServer(listenAddr, serverConfig)
	if err != nil {
		logger.Fatalf("Failed to create peer server (%s)", err)
	}
	// 检查TLS认证
	if serverConfig.SecOpts.UseTLS {
		logger.Info("Starting peer with TLS enabled")
		// set up credential support
		cs := comm.GetCredentialSupport()
		// 设置服务器跟证书
		cs.ServerRootCAs = serverConfig.SecOpts.ServerRootCAs

		// set the cert to use if client auth is requested by remote endpoints
		// 获取证书用户grpc链接
		clientCert, err := peer.GetClientCertificate()
		if err != nil {
			logger.Fatalf("Failed to set TLS client certficate (%s)", err)
		}
		// 设置证书
		comm.GetCredentialSupport().SetClientCertificate(clientCert)
	}

	//TODO - do we need different SSL material for events ?
	// 创建grpc服务②:Eventhub,端口7053
	ehubGrpcServer, err := createEventHubServer(serverConfig)
	if err != nil {
		grpclog.Fatalf("Failed to create ehub server: %v", err)
	}

	mutualTLS := serverConfig.SecOpts.UseTLS && serverConfig.SecOpts.RequireClientCert
	policyCheckerProvider := func(resourceName string) deliver.PolicyChecker {
		return func(env *cb.Envelope, channelID string) error {
			return aclmgmt.GetACLProvider().CheckACL(resourceName, channelID, env)
		}
	}

	// 创建grpc服务③: DeliverEvents,注册到peerServer上,端口7051
	abServer := peer.NewDeliverEventsServer(mutualTLS, policyCheckerProvider, &peer.DeliverSupportManager{})
	pb.RegisterDeliverServer(peerServer.Server(), abServer)

	// enable the cache of chaincode info
	ccprovider.EnableCCInfoCache()

	// Create a self-signed CA for chaincode service
	ca, err := accesscontrol.NewCA()
	if err != nil {
		logger.Panic("Failed creating authentication layer:", err)
	}
	// 创建grpc服务④:链码管理服务
	ccSrv, ccEndpoint, err := createChaincodeServer(ca, peerHost)
	if err != nil {
		logger.Panicf("Failed to create chaincode server: %s", err)
	}
	registerChaincodeSupport(ccSrv, ccEndpoint, ca)
	// 启动循环处理
	go ccSrv.Start()

	logger.Debugf("Running peer")

	// Register the Admin server
	// 创建grpc服务 ⑤: Admin注册到PeerServer上 端口7051
	pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer())

	//隐私数据处理: 使用goosip协议进行分发
	privDataDist := func(channel string, txID string, privateData *rwset.TxPvtReadWriteSet) error {
		return service.GetGossipService().DistributePrivateData(channel, txID, privateData)
	}

	//创建=grpc服务:背书服务 端口7051
	serverEndorser := endorser.NewEndorserServer(privDataDist, &endorser.SupportImpl{})
	libConf := library.Config{}
	if err = viperutil.EnhancedExactUnmarshalKey("peer.handlers", &libConf); err != nil {
		return errors.WithMessage(err, "could not load YAML config")
	}
	authFilters := library.InitRegistry(libConf).Lookup(library.Auth).([]authHandler.Filter)
	auth := authHandler.ChainFilters(serverEndorser, authFilters...)
	// Register the Endorser server
	pb.RegisterEndorserServer(peerServer.Server(), auth)

	// Initialize gossip component 初始化goosip连接点
	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")

	// 获取本地msp前面者身份的序列号参数
	serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
	if err != nil {
		logger.Panicf("Failed serializing self identity: %v", err)
	}
	// gossip加密服务组件
	messageCryptoService := peergossip.NewMCS(
		peer.NewChannelPolicyManagerGetter(),
		localmsp.NewSigner(),
		mgmt.NewDeserializersManager())
	secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager())

	// callback function for secure dial options for gossip service
	// gossip 拨号
	secureDialOpts := func() []grpc.DialOption {
		var dialOpts []grpc.DialOption
		// set max send/recv msg sizes
		dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize()),
			grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize())))
		// set the keepalive options
		kaOpts := comm.DefaultKeepaliveOptions()
		if viper.IsSet("peer.keepalive.client.interval") {
			kaOpts.ClientInterval = viper.GetDuration("peer.keepalive.client.interval")
		}
		if viper.IsSet("peer.keepalive.client.timeout") {
			kaOpts.ClientTimeout = viper.GetDuration("peer.keepalive.client.timeout")
		}
		dialOpts = append(dialOpts, comm.ClientKeepaliveOptions(kaOpts)...)

		if comm.TLSEnabled() {
			dialOpts = append(dialOpts, grpc.WithTransportCredentials(comm.GetCredentialSupport().GetPeerCredentials()))
		} else {
			dialOpts = append(dialOpts, grpc.WithInsecure())
		}
		return dialOpts
	}

	// 检查是否启用TSL
	var certs *common2.TLSCertificates
	if peerServer.TLSEnabled() {
		serverCert := peerServer.ServerCertificate()
		clientCert, err := peer.GetClientCertificate()
		if err != nil {
			return errors.Wrap(err, "failed obtaining client certificates")
		}
		certs = &common2.TLSCertificates{}
		certs.TLSServerCert.Store(&serverCert)
		certs.TLSClientCert.Store(&clientCert)
	}

	// 初始化gossip服务
	err = service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(), certs,
		messageCryptoService, secAdv, secureDialOpts, bootstrap...)
	if err != nil {
		return err
	}
	// 停止获取goosipserver
	defer service.GetGossipService().Stop()

	// 安装系统连码
	initSysCCs()

	//peer 初始化系统连码
	peer.Initialize(func(cid string) {
		logger.Debugf("Deploying system CC, for chain <%s>", cid)
		scc.DeploySysCCs(cid)
	})

	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]",
		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)

	// Start the grpc server. Done in a goroutine so we can deploy the
	// genesis block if needed.
	serve := make(chan error)

	sigs := make(chan os.Signal, 1)
	// 结束启动进程监听
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		sig := <-sigs
		logger.Debugf("sig: %s", sig)
		serve <- nil
	}()

	// 启动grpc 7051
	go func() {
		var grpcErr error
		if grpcErr = peerServer.Start(); grpcErr != nil {
			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
		} else {
			logger.Info("peer server exited")
		}
		serve <- grpcErr
	}()

	if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
		return err
	}

	// Start the event hub server
	if ehubGrpcServer != nil {
		go ehubGrpcServer.Start()
	}

	// Start profiling http endpoint if enabled
	if viper.GetBool("peer.profile.enabled") {
		go func() {
			profileListenAddress := viper.GetString("peer.profile.listenAddress")
			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
				logger.Errorf("Error starting profiler: %s", profileErr)
			}
		}()
	}

	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]",
		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)

	// set the logging level for specific modules defined via environment
	// variables or core.yaml
	// 设置日志
	overrideLogModules := []string{"msp", "gossip", "ledger", "cauthdsl", "policies", "grpc", "peer.gossip"}
	for _, module := range overrideLogModules {
		err = common.SetLogLevelFromViper(module)
		if err != nil {
			logger.Warningf("Error setting log level for module '%s': %s", module, err.Error())
		}
	}
	//设置日志
	flogging.SetPeerStartupModulesMap()

	// 阻塞启动,如果读取到则启动完成
	return <-serve
}

安装初始化系统连码

peer启动时,initSysCCS初始化系统连码时,链id为空

func initSysCCs() {
   //deploy system chaincodes
   scc.DeploySysCCs("")
   logger.Infof("Deployed system chaincodes")
}

fabric/core/scc/importsysccs.go

func DeploySysCCs(chainID string) {
	for _, sysCC := range systemChaincodes {
		deploySysCC(chainID, sysCC)
	}
}

系统连码使用go程并非docker容器进行运行管理,其中包括:

  • cscc:配置系统(加入通道、获取配置、获取通道列表等)

  • lscc:连码生命周期系统(安装、实例化、部署、获取连码数据等)

  • qscc: 查询系统连码(获取区块链信息)

  • escc:对模拟执行结果背书

  • vscc:检查签名信息

var systemChaincodes = []*SystemChaincode{
   {
      Enabled:           true,
      Name:              "cscc",
      Path:              "github.com/hyperledger/fabric/core/scc/cscc",
      InitArgs:          [][]byte{[]byte("")},
      Chaincode:         &cscc.PeerConfiger{},
      InvokableExternal: true, // cscc is invoked to join a channel
   },
   {
      Enabled:           true,
      Name:              "lscc",
      Path:              "github.com/hyperledger/fabric/core/scc/lscc",
      InitArgs:          [][]byte{[]byte("")},
      Chaincode:         lscc.NewLifeCycleSysCC(),
      InvokableExternal: true, // lscc is invoked to deploy new chaincodes
      InvokableCC2CC:    true, // lscc can be invoked by other chaincodes
   },
   {
      Enabled:   true,
      Name:      "escc",
      Path:      "github.com/hyperledger/fabric/core/scc/escc",
      InitArgs:  [][]byte{[]byte("")},
      Chaincode: &escc.EndorserOneValidSignature{},
   },
   {
      Enabled:   true,
      Name:      "vscc",
      Path:      "github.com/hyperledger/fabric/core/scc/vscc",
      InitArgs:  [][]byte{[]byte("")},
      Chaincode: &vscc.ValidatorOneValidSignature{},
   },
   {
      Enabled:           true,
      Name:              "qscc",
      Path:              "github.com/hyperledger/fabric/core/chaincode/qscc",
      InitArgs:          [][]byte{[]byte("")},
      Chaincode:         &qscc.LedgerQuerier{},
      InvokableExternal: true, // qscc can be invoked to retrieve blocks
      InvokableCC2CC:    true, // qscc can be invoked to retrieve blocks also by a cc
   },
}

初始化本地通道账本

// peer/node/start.go
peer.Initialize(func(cid string) {
		logger.Debugf("Deploying system CC, for chain <%s>", cid)
		scc.DeploySysCCs(cid)
	})

core/peer/peer.go

初始化完成后调用 scc.DeploySysCCs(cid)部署系统连码到指定cid

func Initialize(init func(string)) {
   // 获取并设置并发量
   nWorkers := viper.GetInt("peer.validatorPoolSize")
   if nWorkers <= 0 {
      nWorkers = runtime.NumCPU()
   }
   validationWorkersSemaphore = semaphore.NewWeighted(int64(nWorkers))

   chainInitializer = init

   var cb *common.Block
   var ledger ledger.PeerLedger
   //初始化账本管理器
   ledgermgmt.Initialize(ConfigTxProcessors)
   //获取账本id
   ledgerIds, err := ledgermgmt.GetLedgerIDs()
   if err != nil {
      panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err))
   }
   // 循环处理账本id
   for _, cid := range ledgerIds {
      peerLogger.Infof("Loading chain %s", cid)
      //创建本地账本
      if ledger, err = ledgermgmt.OpenLedger(cid); err != nil {
         peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err)
         peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
         continue
      }
      //获取当前配置区块
      if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil {
         peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err)
         peerLogger.Debugf("Error while looking for config block on ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
         continue
      }
      // Create a chain if we get a valid ledger with config block
      //创建链结构
      if err = createChain(cid, ledger, cb); err != nil {
         peerLogger.Warningf("Failed to load chain %s(%s)", cid, err)
         peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err)
         continue
      }
      // 初始化通道,
      InitChain(cid)
   }
}

// InitChain takes care to initialize chain after peer joined, for example deploys system CCs
// 初始化完成后调用chainInitializer方法
func InitChain(cid string) {
   if chainInitializer != nil {
      // Initialize chaincode, namely deploy system CC
      peerLogger.Debugf("Init chain %s", cid)
      chainInitializer(cid)
   }
}

你可能感兴趣的:(区块链)