hyperledger fabric0.6 结构分析(三)

来源:互联网 发布:怎样走网络群众路线 编辑:程序博客网 时间:2024/06/01 23:34

本文解决的问题是:本Peer节点如何接收其他节点的数据,接到数据如何处理?


之前两节的分析是命令来源是CLI client,如何连接到Devops服务器、如何发送给Consensus模块、如何发送给ChainCodeSupportClient等。

接下来分析本文要讨论的问题

1)在进行网络初始化的过程中执行以下内容,在创建节点Engine过程中该节点作为客户端的身份连接到其他Peer

[cpp] view plain copy
  1. peerServer, err = peer.NewPeerWithEngine(secHelperFunc, helper.GetEngine)  
[cpp] view plain copy
  1. </pre><pre name="code" class="cpp" style="font-size: 15px;">func (p *Impl) chatWithPeer(address string) error {  
  2.     peerLogger.Debugf("Initiating Chat with peer address: %s", address)  
  3.     conn, err := NewPeerClientConnectionWithAddress(address)  
  4.     if err != nil {  
  5.         peerLogger.Errorf("Error creating connection to peer address %s: %s", address, err)  
  6.         return err  
  7.     }  
  8.     serverClient := pb.NewPeerClient(conn)  
  9.     ctx := context.Background()  
  10.     stream, err := serverClient.Chat(ctx)  
  11.     if err != nil {  
  12.         peerLogger.Errorf("Error establishing chat with peer address %s: %s", address, err)  
  13.         return err  
  14.     }  
  15.     peerLogger.Debugf("Established Chat with peer address: %s", address)  
  16.     err = p.handleChat(ctx, stream, true)  
  17.     stream.CloseSend()  
  18.     if err != nil {  
  19.         peerLogger.Errorf("Ending Chat with peer address %s due to error: %s", address, err)  
  20.         return err  
  21.     }  
  22.     return nil  
  23. }  

2.在handleChat执行过程中,建立消息循环,而这里的handler.HandleMessage。这个handler之前介绍过,是Engine的消息响应句柄,该消息响应处理来自于Consensus模块

[cpp] view plain copy
  1. func (p *Impl) handleChat(ctx context.Context, stream ChatStream, initiatedStream bool) error {  
  2.     deadline, ok := ctx.Deadline()  
  3.     peerLogger.Debugf("Current context deadline = %s, ok = %v", deadline, ok)  
  4.     handler, err := p.handlerFactory(p, stream, initiatedStream, nil)  
  5.     if err != nil {  
  6.         return fmt.Errorf("Error creating handler during handleChat initiation: %s", err)  
  7.     }  
  8.     defer handler.Stop()  
  9.     for {  
  10.         in, err := stream.Recv()  
  11.         if err == io.EOF {  
  12.             peerLogger.Debug("Received EOF, ending Chat")  
  13.             return nil  
  14.         }  
  15.         if err != nil {  
  16.             e := fmt.Errorf("Error during Chat, stopping handler: %s", err)  
  17.             peerLogger.Error(e.Error())  
  18.             return e  
  19.         }  
  20.         err = handler.HandleMessage(in)  
  21.         if err != nil {  
  22.             peerLogger.Errorf("Error handling message: %s", err)  
  23.             //return err  
  24.         }  
  25.     }  
  26. }  
3.HandleMessage函数consenterChan 这个channel比较重要,该写入操作会触发engine.consensusFan的消息循环

[cpp] view plain copy
  1. func (handler *ConsensusHandler) HandleMessage(msg *pb.Message) error {  
  2.     if msg.Type == pb.Message_CONSENSUS {  
  3.         senderPE, _ := handler.To()  
  4.         select {  
  5.         case handler.consenterChan <- &util.Message{  
  6.             Msg:    msg,  
  7.             Sender: senderPE.ID,  
  8.         }:  
  9.             return nil  
  10.         default:  
  11.             err := fmt.Errorf("Message channel for %v full, rejecting", senderPE.ID)  
  12.             logger.Errorf("Failed to queue consensus message because: %v", err)  
  13.             return err  
  14.         }  
  15.     }  
  16.   
  17.     if logger.IsEnabledFor(logging.DEBUG) {  
  18.         logger.Debugf("Did not handle message of type %s, passing on to next MessageHandler", msg.Type)  
  19.     }  
  20.     return handler.MessageHandler.HandleMessage(msg)  
  21. }  

4.看到RecvMsg这个函数是不是有点眼熟,这个操作和  hyperledger fabric 结构分析 最后一个流程是一样的。

[cpp] view plain copy
  1. func GetEngine(coord peer.MessageHandlerCoordinator) (peer.Engine, error) {  
  2.     var err error  
  3.     engineOnce.Do(func() {  
  4.         engine = new(EngineImpl)  
  5.         engine.helper = NewHelper(coord)  
  6.         engine.consenter = controller.NewConsenter(engine.helper)  
  7.         engine.helper.setConsenter(engine.consenter)  
  8.         engine.peerEndpoint, err = coord.GetPeerEndpoint()  
  9.         engine.consensusFan = util.NewMessageFan()  
  10.   
  11.         go func() {  
  12.             logger.Debug("Starting up message thread for consenter")  
  13.   
  14.             // The channel never closes, so this should never break  
  15.             for msg := range engine.consensusFan.GetOutChannel() {  
  16.                 engine.consenter.RecvMsg(msg.Msg, msg.Sender)  
  17.             }  
  18.         }()  
  19.     })  
  20.     return engine, err  
  21. }  
5.再往下的流程与 hyperledger fabric 结构分析(三)中的一致。