入口
src: peer/main.go
...
mainCmd.AddCommand(version.Cmd())
mainCmd.AddCommand(node.Cmd())
mainCmd.AddCommand(network.Cmd())
mainCmd.AddCommand(chaincode.Cmd())
...
if mainCmd.Execute() != nil {
os.Exit(1)
}
main函数主要添加需要执行的命令,然后调用mainCmd.Excute()执行。
其中:
version.Cmd():主要打印版本信息:metadata.Version,由Makefile传入。
node.Cmd(): 本地节点搭建,加入网络,开启peerServer, grpcServer,
httpServer等。
network.Cmd(): 登录devopsServer,查询网络上peer,包括NP和NVP。
chaincode.Cmd(): deploy, invoke, querry操作。
下面着重分析node模块,从start.go入手。
node/start.go
主要是serve这个函数,开启需要的服务,下面结合代码进行分析添加注释说明。
func serve(args []string) error {
}
1、core/peer/config.go:设置缓存数据,包括peer.address,peer.endpoint
if err := peer.CacheConfiguration(); err != nil {
return err
}
2、设置服务器地址,创建服务器实例
listenAddr := viper.GetString("peer.listenAddress")
if "" == listenAddr {
logger.Debug("Listen address not specified, using peer endpoint address")
listenAddr = peerEndpoint.Address
}
lis, err := net.Listen("tcp", listenAddr)
if err != nil {
grpclog.Fatalf("Failed to listen: %v", err)
}
3、createEventHubServer创建事件Hub服务器(创建线程运行),同时为该服务器创建监听实例,调用RegisterEventsServer 函数将EventHubServer注册到
grpcService上。
ehubLis, ehubGrpcServer, err := createEventHubServer()
if err != nil {
grpclog.Fatalf("Failed to create ehub server: %v", err)
}
4、启动数据库,/core/db/db.go
db.Start()
5、加密模块,主要涉及到秘钥,证书等
grpcServer := grpc.NewServer(opts...)
secHelper, err := getSecHelper()
if err != nil {
return err
}
secHelperFunc := func() crypto.Peer {
return secHelper
}
6、该函数主要作用是将系统chaincode部署到Docker上,同时根据第一个参数
chainname创建ChainCodeSupport 实例,该实例包括 chaincode路径、超时时间、chainname等数据信息。将得到的ChainCodeSupport实例注册到grpcServer。其中比较重要两个函数为:
- RegisterSysCCs 该函数注册部署系统chaincode
- RegisterChaincodeSupportServer
该函数向grpcServer注册chainCodeSupport实例,同时传入
服务注册到grpcServer,grpcServer为该服务器生成stream,
的HandleMessage的数据处理,chainCodeSupport的stream是与docker的
chainCode通讯的媒介。
func RegisterChaincodeSupportServer(s *grpc.Server, srv ChaincodeSupportServer) {
s.RegisterService(&_ChaincodeSupport_serviceDesc, srv)
}
func _ChaincodeSupport_RegisterGrpc_Handler(srv interface{},
stream grpc.ServerStream) error {
(ChaincodeSupportServer).RegisterGrpc(&chaincodeSupportRegist
erGrpcServer{stream})
}
var _ChaincodeSupport_serviceDesc = grpc.ServiceDesc{
ServiceName: "protos.ChaincodeSupport",
HandlerType: (*ChaincodeSupportServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{
{
StreamName: "RegisterGrpc",
Handler: _ChaincodeSupport_RegisterGrpc_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: fileDescriptor2,
}
func registerChaincodeSupport(chainname chaincode.ChainName, grpcServer *grpc.Server, secHelper crypto.Peer) {
//get user mode
userRunsCC := false
if viper.GetString("chaincode.mode") == chaincode.DevModeUserRunsChaincode {
userRunsCC = true
}
//get chaincode startup timeout
tOut, err := strconv.Atoi(viper.GetString("chaincode.startuptimeout"))
if err != nil {
fmt.Printf("could not retrive timeout var...setting to 5secs\n")
tOut = 5000
}
ccStartupTimeout := time.Duration(tOut) * time.Millisecond
rpc := viper.GetString("vm.rpc")
if rpc == "thrift" {
chaincode.NewChaincodeSupport(chainname, peer.GetPeerEndpoint, userRunsCC, ccStartupTimeout, secHelper)
} else if rpc == "grpc" {
ccSrv := chaincode.NewChaincodeSupport(chainname, peer.GetPeerEndpoint, userRunsCC,
ccStartupTimeout, secHelper)
//Now that chaincode is initialized, register all system chaincodes.
system_chaincode.RegisterSysCCs()
pb.RegisterChaincodeSupportServer(grpcServer, ccSrv)
} else {
panic("vm.rpc should be set grpc or thrift in core.yaml")
}
}
7、注册peerServer, adminServer, DevOpsServer, ServerOpenchain, OpenchainServer, RESTservice等
// Register the Peer server
pb.RegisterPeerServer(grpcServer, peerServer)
// Register the Admin server
pb.RegisterAdminServer(grpcServer, core.NewAdminServer())
// Register Devops server
serverDevops := core.NewDevopsServer(peerServer)
pb.RegisterDevopsServer(grpcServer, serverDevops)
// Register the ServerOpenchain server
pb.RegisterOpenchainServer(grpcServer, serverOpenchain)
// Create and register the REST service if configured
if viper.GetBool("rest.enabled") {
go rest.StartOpenchainRESTServer(serverOpenchain, serverDevops)
}
8、 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
fmt.Println()
fmt.Println(sig)
serve <- nil
}()
go func() {
var grpcErr error
if grpcErr = grpcServer.Serve(lis); grpcErr != nil {
grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
} else {
logger.Info("grpc server exited")
}
serve <- grpcErr
}()
if err := writePid(viper.GetString("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
return err
}
9、 Start the event hub server
if ehubGrpcServer != nil && ehubLis != nil {
go ehubGrpcServer.Serve(ehubLis)
}
10、调试分析服务,go pprof等
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)
}
}()
}