Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)

尹成發表於2018-05-20
# Fabric 1.0原始碼筆記 之 Orderer #BroadcastServer(Broadcast服務端)

## 1、BroadcastServer概述

BroadcastServer相關程式碼在protos/orderer、orderer目錄下。

protos/orderer/ab.pb.go,AtomicBroadcastServer介面定義。
orderer/server.go,go,AtomicBroadcastServer介面實現。



## 2、AtomicBroadcastServer介面定義

### 2.1、AtomicBroadcastServer介面定義

```go
type AtomicBroadcastServer interface {
    Broadcast(AtomicBroadcast_BroadcastServer) error
    Deliver(AtomicBroadcast_DeliverServer) error
}
//程式碼在protos/orderer/ab.pb.go
···

### 2.2、gRPC相關實現

```go
var _AtomicBroadcast_serviceDesc = grpc.ServiceDesc{
    ServiceName: "orderer.AtomicBroadcast",
    HandlerType: (*AtomicBroadcastServer)(nil),
    Methods: []grpc.MethodDesc{},
    Streams: []grpc.StreamDesc{
        {
            StreamName: "Broadcast",
            Handler: _AtomicBroadcast_Broadcast_Handler,
            ServerStreams: true,
            ClientStreams: true,
        },
        {
            StreamName: "Deliver",
            Handler: _AtomicBroadcast_Deliver_Handler,
            ServerStreams: true,
            ClientStreams: true,
        },
    },
    Metadata: "orderer/ab.proto",
}

func RegisterAtomicBroadcastServer(s *grpc.Server, srv AtomicBroadcastServer) {
    s.RegisterService(&_AtomicBroadcast_serviceDesc, srv)
}

func _AtomicBroadcast_Broadcast_Handler(srv interface{}, stream grpc.ServerStream) error {
    return srv.(AtomicBroadcastServer).Broadcast(&atomicBroadcastBroadcastServer{stream})
}

func _AtomicBroadcast_Deliver_Handler(srv interface{}, stream grpc.ServerStream) error {
    return srv.(AtomicBroadcastServer).Deliver(&atomicBroadcastDeliverServer{stream})
}
//程式碼在protos/orderer/ab.pb.go
```

## 3、AtomicBroadcastServer介面實現

### 3.1、server結構體

server結構體:

```go
type server struct {
    bh broadcast.Handler
    dh deliver.Handler
}

type broadcastSupport struct {
    multichain.Manager
    broadcast.ConfigUpdateProcessor
}
//程式碼在orderer/server.go
```

broadcast.Handler:

```go
type Handler interface {
    Handle(srv ab.AtomicBroadcast_BroadcastServer) error
}

type handlerImpl struct {
    sm SupportManager
}

func NewHandlerImpl(sm SupportManager) Handler {
    return &handlerImpl{
        sm: sm,
    }
}

type SupportManager interface {
    ConfigUpdateProcessor
    GetChain(chainID string) (Support, bool)
}

type ConfigUpdateProcessor interface { //處理通道配置更新
    Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error)
}
//程式碼在orderer/common/broadcast/broadcast.go
```

deliver.Handler:

```go
type Handler interface {
    Handle(srv ab.AtomicBroadcast_DeliverServer) error
}

type deliverServer struct {
    sm SupportManager
}

type SupportManager interface {
    GetChain(chainID string) (Support, bool)
}
//程式碼在orderer/common/deliver/deliver.go
```

### 3.2、server結構體相關方法

```go
//構建server結構體
func NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.AtomicBroadcastServer
//s.bh.Handle(srv)
func (s *server) Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error
//s.dh.Handle(srv)
func (s *server) Deliver(srv ab.AtomicBroadcast_DeliverServer) error
//程式碼在orderer/server.go
```

func NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.AtomicBroadcastServer程式碼如下:

```go
func NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.AtomicBroadcastServer {
    s := &server{
        dh: deliver.NewHandlerImpl(deliverSupport{Manager: ml}),
        bh: broadcast.NewHandlerImpl(broadcastSupport{
            Manager: ml,
            ConfigUpdateProcessor: configupdate.New(ml.SystemChannelID(), configUpdateSupport{Manager: ml}, signer),
        }),
    }
    return s
}
//程式碼在orderer/server.go
```

### 3.3、Broadcast服務端Broadcast處理流程

Broadcast服務端Broadcast處理流程,即broadcast.handlerImpl.Handle方法。

#### 3.3.1、接收Envelope訊息,並獲取Payload和ChannelHeader

```go
msg, err := srv.Recv() //接收Envelope訊息
payload, err := utils.UnmarshalPayload(msg.Payload) //反序列化獲取Payload
chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) //反序列化獲取ChannelHeader
//程式碼在orderer/common/broadcast/broadcast.go
```

#### 3.3.2、如果訊息型別為channel配置或更新,則使用multichain.Manager處理訊息

```
if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) { //如果是channel配置或更新
    msg, err = bh.sm.Process(msg) //configupdate.Processor.Process方法
}
//程式碼在orderer/common/broadcast/broadcast.go
```

msg, err = bh.sm.Process(msg)程式碼如下:

```go
func (p *Processor) Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) {
    channelID, err := channelID(envConfigUpdate) //獲取ChannelHeader.ChannelId
    //multichain.Manager.GetChain方法,獲取chainSupport,以及chain是否存在
    support, ok := p.manager.GetChain(channelID)
    if ok {
        //已存在的channel配置,調取multichain.Manager.ProposeConfigUpdate方法
        return p.existingChannelConfig(envConfigUpdate, channelID, support)
    }
    //新channel配置,調取multichain.Manager.NewChannelConfig方法
    return p.newChannelConfig(channelID, envConfigUpdate)
}
//程式碼在orderer/configupdate/configupdate.go
```

#### 3.3.3、其他訊息型別或channel訊息處理後,接受訊息並加入排序

```go
support, ok := bh.sm.GetChain(chdr.ChannelId) //獲取chainSupport
_, filterErr := support.Filters().Apply(msg) //filter.RuleSet.Apply方法
//調取Chain.Enqueue方法,接受訊息,加入排序
support.Enqueue(msg)
//程式碼在orderer/common/broadcast/broadcast.go
```

#### 3.3.4、向客戶端傳送響應資訊

```go
err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS})
//程式碼在orderer/common/broadcast/broadcast.go
```

### 3.4、Broadcast服務端Deliver處理流程

Broadcast服務端Deliver處理流程,即deliver.deliverServer.Handle方法。

```go
func (ds *deliverServer) Handle(srv ab.AtomicBroadcast_DeliverServer) error {
    for {
        //接收客戶端查詢請求
        envelope, err := srv.Recv()
        payload, err := utils.UnmarshalPayload(envelope.Payload)
        chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
        chain, ok := ds.sm.GetChain(chdr.ChannelId)

        erroredChan := chain.Errored()
        select {
        case <-erroredChan:
            return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE)
        default:

        }

        lastConfigSequence := chain.Sequence()

        sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager())
        result, _ := sf.Apply(envelope)

        seekInfo := &ab.SeekInfo{}
        err = proto.Unmarshal(payload.Data, seekInfo)

        cursor, number := chain.Reader().Iterator(seekInfo.Start)
        var stopNum uint64
        switch stop := seekInfo.Stop.Type.(type) {
        case *ab.SeekPosition_Oldest:
            stopNum = number
        case *ab.SeekPosition_Newest:
            stopNum = chain.Reader().Height() - 1
        case *ab.SeekPosition_Specified:
            stopNum = stop.Specified.Number
            if stopNum < number {
                return sendStatusReply(srv, cb.Status_BAD_REQUEST)
            }
        }

        for {
            if seekInfo.Behavior == ab.SeekInfo_BLOCK_UNTIL_READY {
                select {
                case <-erroredChan:
                    return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE)
                case <-cursor.ReadyChan():
                }
            } else {
                select {
                case <-cursor.ReadyChan():
                default:
                    return sendStatusReply(srv, cb.Status_NOT_FOUND)
                }
            }

            currentConfigSequence := chain.Sequence()
            if currentConfigSequence > lastConfigSequence {
                lastConfigSequence = currentConfigSequence
                sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager())
                result, _ := sf.Apply(envelope)

            }

            block, status := cursor.Next()
            err := sendBlockReply(srv, block)
            if stopNum == block.Header.Number {
                break
            }
        }

        err := sendStatusReply(srv, cb.Status_SUCCESS)
    }
}
```





網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN





網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN

相關文章