Fabric Source Analysis 6--grpc Service __fabric

Source: Internet
Author: User
Tags prototype definition
Fabric Source Analysis 6–GRPC Service GRPC Introduction

GRPC is a multilingual open-source RPC technology developed by Google, which is used in fabric to implement remote calls between client and server. For example, the client defines an RPC service and generates the client code and the server-side code, and then runs the service-side code and the client-side code to realize the purpose of the client's Chaincode service after the development of the business logic. Because the GPRC is relatively complex, all also please learn by yourself. Very detailed information and examples in the GPRC website.

Extremely thick strokes of the use of GRPC, for the following foreshadowing:

1. Define an RPC service in the Xxx.proto file

Service Events {
    rpc Chat (stream signedevent) returns (Stream Event) {}
}

2. Command line uses PROTOC to generate corresponding XXX.pb.go source code

In XXX.pb.go, the clientAPI for Events service is an initialization function for the interface definition, interface instance, and interface instance used by clients . The Server API for Events service defines, registers functions for the interface used by the service side .

If either end or both ends are streaming RPC, at one end of the stream, the interface definition and interface instance are generated specifically for its flow. You can use the generated instance directly, or you can implement the interface yourself, and customize the instance. The primary method of interface definition is Send and Recv.

Protoc--GO_OUT=PLUGINS=GRPC:. Xxx.proto

3. Writing Client code

Note that since we are currently focused on peer node start, which is basically a service on the backend server,
//So the client code is not involved in this article.

    //Fill GRPC network link option
    var opts []grpc. Dialoption
    opts = append (opts, Grpc. Withinsecure ())
    //Create a GRPC Connection object conn that connects to the server side
    , err: = Grpc. Dial ("0.0.0.0:7051", opts ...)
    Defer Conn. Close ()
    ///Use Connection object to make parameters, create GRPC client objects using initialization function in XXX.pb.go
    : = neweventsclient (conn)
    //Invoke service
    Client. Chat (...)

4. Writing service-side code

    Defines a listener object, the address that the server listens to
    lis,err: = Net. Listen ("TCP", ": 7051")
    //Create GRPC server option and populate
    var serveropts []grpc. Serveroption
    //Create a standard GRPC server
    = Grpc. NewServer (serveropts ...)
    Create a service-side object that implements the service-side interface
    type eventsever{...}
    based on the interface definitions generated in XXX.pb.go. Func (e *eventsever) Chat (...) {...}
    es: = new (Eventserver)
    //Register service with the registration function in XXX.pb.go, register to GRPC server object
    registereventsserver (server,es)
    // Starts the GRPC server Object Server based on the Listener object
    . Serve (LIS)
Grpc Service interface and instance in fabric

In /fabric/core/comm/server.go , Security configuration items, gprcserver interfaces, implementation, and initialization functions are defined. By default, TLS is not used in fabric. TLS Security Configuration entries

Type secureserverconfig struct {
    //whether or not to use TLS for communication
    usetls bool//pem-encoded
    X509 The public key to is used by the server for TLS communication
    ///specified in Core.yaml, where the Server.cert file data is stored
    in the Read TLS directory servercertificate []byte
    //pem-encoded private key to is used by the server for TLS communication
    //specified in Core.yaml, The Server.key file data in the Read TLS directory is stored in this
    serverkey []byte//set of pem-encoded X509 certificate to authorities
    Send
    //as part of the server handshake
    //specified in Core.yaml, CA.CRT file data in the Read TLS directory is stored in this
    Serverrootcas [][]byte
    //whether or not TLS client must present certificates for authentication
    requireclientcert bool
    //set of pem-encoded X509 Certificate authorities to use when verifying//client certifi
    Cates
    Clientrootcas [][]byte
}
Grpcserver Interface
Type Grpcserver Interface {
    //return Grpcserver Listener Address
    () string//
    start Lower grpc. Server
    Start () error
    //stop Lower GRPC. Server
    Stop ()
    //Return Grpcserver Instance Object
    Server () *grpc. Server
    //Returns the network Listener instance Object
    Listener () net used by Grpcserver. Listener
    //return GRPC. Certificate
    servercertificate () TLS used by the server. Certificate
    //identifies whether the Grpcserver instance uses TLS
    tlsenabled () bool
    //Increase pem-encoded X509 certificate authorities to
    //Authorities list
    for validating client certificates Appendclientrootcas (clientroots [][]byte) Error
    //To verify Client Certificates authorities list
    //delete pem-encoded X509 Certificate Authorities
    Removeclientrootcas (clientroots [][]byte) error
    //based on a pem-encoded X509 Certificate Authorities list
    //Set authorities list for authenticating client certificates
    setclientrootcas (clientroots [][]byte) Error
}
Grpcserver Implementation Example
type grpcserverimpl struct {//server specified listener address format: Hostname:port address string//listener AD A dress listener that handles network requests listener net. Listener//Standard GRPC server to perform various GRPC service operation server *GRPC through this object. Server//certificate presented by the server for TLS communication Servercertificate TLS. Certificate//key used by the server for TLS communication Serverkeypem []byte//list of certificate Authoriti Es to optionally the client during//the TLS handshake Serverrootcas []tls. Certificate//lock to protect concurrent access to Append/remove lock *sync. Mutex//set of pem-encoded X509 Certificate authorities used to populate//the Tlsconfig.clientcas-indexed by SUBJ ECT Clientrootcas map[string]*x509. Certificate//TLS configuration used by the GRPC server Tlsconfig.
    Config//is TLS enabled? tlsenabled BOOL} The Newgrpcserverfromlistener function in the same file is the Grpcserverimpl initialization function, where the TLS-related code is used to the TLS, X509 Tool Library under crypto. 
Peer node start GRPC service

In the serve function in start.go , there are two Grpcserver service objects created: Peerserver globaleventsserver

Peer Server peerserver, defined in /fabric/core/peer/peer.go . Event Server Globaleventsserver, is a global single case, defined in /fabric/events/producer/producer.go . Peerserver Create Peerserver

Tracing the creation of Peerserver objects in the serve function, the code eventually uses the Newgrpcserverfromlistener in /fabric/core/comm/server.go function creates a Grpcserverimpl instance object that is in the object.

In the serve function
peerserver, err: = Peer. Createpeerserver (listenaddr, Secureconfig)

//Peerserver in the Createpeerserver function
, err = Comm. Newgrpcserver (listenaddress, Secureconfig)

//In the Newgrpcserver function
, lis, err: = Net. Listen ("TCP", address)
Newgrpcserverfromlistener (LIS, secureconfig)

//In the Newgrpcserverfromlistener function, The GRPC Standard server is eventually established and returned to Grpcserverimpl
grpcserver.server = Grpc. NewServer (serveropts ...)
Return Grpcserver
Registration Service

Register chaincodesupport Service

This is the first time we have encountered chaincodesupport this object, divided into chaincodesupport service prototypes and corresponding definitions of Chaincodesupport objects . As can be seen from the name, it is to provide a series of chaincode of fabric. Naturally, this support service is required for chaincode operations in the peer Grpc service. And the Chaincodesupport object itself is more complex, in/fabric/core/chaincode/chaincode_ Support.go, provides a dry configuration value member and Chaincode runtime Environment, as well as a number of interfaces, such as the register function required by the service mentioned in the branch. Because of this focus on GRPC services, the details are not expanded.

Service prototype definition:

The Chaincodesupport service prototype is defined in /fabric/protos/peer/chaincode_shim.proto and generates chaincode_shim.pb.go source code accordingly, Only the service-side definitions that are generated here are shown here.

Service prototypes
Service Chaincodesupport {
RPC Register (Stream chaincodemessage) returns (Stream chaincodemessage) {}
}
Generate server-side interfaces and registration functions
Type Chaincodesupportserver Interface {
Register (chaincodesupport_registerserver) error
}
Func Registerchaincodesupportserver (S *grpc. Server, SRV chaincodesupportserver) {
S.registerservice (&_chaincodesupport_servicedesc, SRV)
}
interface definitions, interface instances for generated service-side flows
Type Chaincodesupport_registerserver Interface {
Send (*chaincodemessage) error
Recv () (*chaincodemessage, error)
Grpc. Serverstream
}//interface
Type Chaincodesupportregisterserver struct {
Grpc. Serverstream
}//Interface Real Port

Registration Service:

Complete the registration using Registerchaincodesupport (Peerserver.server ()) in the Serve function. In this function:

A Chaincodesupport object is created, basically reading the configuration value fill member
The Chaincodesupport object implements the Register method in the generated service-side interface Chaincodesupportserver
Ccsrv: = Chaincode. Newchaincodesupport (...)
Use the generated registration function to complete the registration
Pb. Registerchaincodesupportserver (Grpcserver, Ccsrv)

In Registerchaincodesupport, there is also a SCC.REGISTERSYSCCS () implementation of the system chain registration, will be in the system chain theme articles in detail.

Register Implementation:

Will be detailed in the Chaincodesupport theme article.

Other registered Services

About the services registered by Peerserver, as well as the adminserver,endorserserver,gossipservice, registration method and registration Chaincodesupport Service, after all, is the use of GPRC, or same. What each service is responsible for, and what it does, will be detailed in the corresponding topic article. Globaleventsserver

Define//
Global Single example
var globaleventsserver *eventsserver
//definition and chat implementation in/fabric/events/producer/producer.go
type eventsserver struct {
}
func (P *eventsserver) Chat (stream PB. Events_chatserver) Error {...}
initialization function
func neweventsserver (buffersize uint, timeout int) *eventsserver {...}

Event Server This global single example has no members, only a dedicated initialization function Neweventsserver, a Chat implementation. It all looks very simple, but a initializeevents (buffersize, timeout) in a dedicated initialization function also involves a paragraph of text. Originally globaleventsserver itself is just an event server representative, the actual doing thing is initializeevents (buffersize, timeout) initializes and runs the eventprocessor object , as described below.

In the serve function, use ehubgrpcserver, err: = Createeventhubserver (Secureconfig) to complete the creation and registration of the event server, Ehubgrpcserver to undertake is globaleventsserver this global single example. Create Globaleventsserver

In Createeventhubserver
//Create Grpcserverimpl object, which contains GRPC standard server
lis, err = net. Listen ("TCP", Viper.) GetString ("peer.events.address"))
grpcserver, err: = Comm. Newgrpcserverfromlistener (LIS, secureconfig)

//Create Event server, Neweventsserver return is Globaleventsserver
ehserver: = producer. Neweventsserver (
        uint) (Viper. GetInt ("Peer.events.buffersize")),
        Viper. GetInt ("Peer.events.timeout"))
Registering Event Services

Event Service prototype definition:

The Event Service prototype is defined in /fabric/protos/peer/events.proto and generates events.pb.go source code, showing only the service-side definitions that are generated here.

Service prototypes
Service Events {
RPC Chat (Stream signedevent) returns (Stream Event) {}
}
Generate server-side interfaces and registration functions
Type Eventsserver Interface {
Chat (events_chatserver) error
}
Func Registereventsserver (S *grpc. Server, SRV eventsserver) {
S.registerservice (&_events_servicedesc, SRV)
}
interface definitions, interface instances for generated service-side flows
Type Events_chatserver Interface {
Send (*event) error
Recv () (*signedevent, error)
Grpc. Serverstream
}//interface
Type Eventschatserver struct {
Grpc. Serverstream
}//Interface Instance

Registration Service:

or in a createeventhubserver.
Ehserver object realizes the chat method of generating service-end interface Eventsserver
Use the generated registration function to complete the registration
Pb. Registereventsserver (Grpcserver.server (), Ehserver)

Chat Implementation:

Chat's operation is very clear, the loop receives the data then processes the data, namely processing client's chat call, this also naturally is grpc the service end to do. Handler, Err: = Neweventhandler (Stream), creates a handler based on the service-side stream interface stream to handle the signedevent type data sent by the receiving client. Handler in detail in the following article. In, err: = stream. RECV (), which receives the signedevent type of data, is also the standard use of GPRC bidirectional flows. Err = handler. Handlemessage (in), using handler to process data, Handlemessage is the actual data processing function.

In the Handlemessage function, the client sends the signed signedevent type of data, checks the validity, registers or logs out the event if it registers or logs off, and returns the event type data, and if other types of events, prints an error message and returns. EVT, err: = Validateeventmessage (msg), uses the local MSP to verify the validity of the data. The local MSP will be detailed in the corresponding topic article. Switch evt. Event. (type) {...}, to determine the type of event, and to register or unregister an event or logoff event. If err: = D.chatstream.send (evt), Err!= nil{...}, if you register an event or unregister an event, return the event data to the client after performing the appropriate action, The data is obtained in the validation function Validateeventmessage. Start the Event service

In the back of the serve function, if ehubgrpcserver!= nil {go Ehubgrpcserver.start ()} starts the GPRC service side of the service. The GRPC server-initiated standard function Server.serve (LIS) is called inside start. Event actual processor Eventprocessor

Event handlers are also a global single instance that receives different types of events for processing. Defined in /fabric/events/events.go , the structure is as follows:

Among the members of the Eventprocessor:

eventconsumers

According to event type classification of event processing chain, processing chain handlerlist interface has two kinds of concrete implementation: General processing chain generichandlerlist and chaincode special processing chain Chaincodehandlerlist. Taking the general processing chain as an example, it realizes three operations on handlers :Add,del,foreach. Where the traversal operation foreach executes the action specified by the parameter for each handler in the handlers. Here the handlers maps the handler with the bool value, and the bool value should play a role similar to the switch .

handler is defined in /fabric/events/handle.go , whose member Chatstream is generated in a events.pb.go events_ The Chatserver type GPRC flow interface for sending streaming data. Handler mounts a series of operation functions, such as register,handlemessage,sendmessage,Stop.

Eventchannel

An event channel with a cached and specialized handling of event type data, all events are distributed through this channel. The cache size is defined by the Core.yaml as 100 and is brought in and set by the parameters of the initializeevents. The event type is defined in the Events.proto and corresponds to the build events.pb.go .

Timeout

The time that the channel waits when Eventchannel Jorai, set in Core.yaml and have explanation.

We will analyze the event handler Eventprocessor from its initialization function, which is the initializeevents mentioned above. Event Type

Initializeevents's first two sentences are easy to understand, if Geventprocessor!= nil{...} Only to ensure the geventprocessor of the single case, Geventprocessor = &eventprocessor{...} The object instance is created for Geventprocessor and the memory space is allocated. Addinternaleventtypes (), which called Addeventtype 4 times in essence, adds the internal event type and assigns each of these types to their own processing chain handlerlist.

The

Known event types added are defined by/fabric/protos/peer/events.proto and correspond to four of the generated Events.pb.go: Eventtype_block-Block events, Corresponds to Generichandlerlist eventtype_chaincode-chaincode event, corresponding to Chaincodehandlerlist eventtype_register- Addinternaleventtypes has but Addeventtype does not handle eventtype_rejection-Reject event, corresponds to Generichandlerlist start function

Initializeevents the last sentence is the Go Geventprocessor.start (), which is a start function that runs a goroutine global single instance geventprocessor. The start function is a dead loop that continuously receives data event type data from the Eventchannel and processes it. The process is as follows: E: = <-ep.eventchannel, get an event e. EType: = Getmessagetype (E), gets the type eTypeof event E. If HL, _ = Ep.eventconsumers[etype]; hl = nil {...}, according to etype get the event type of the processing chain HL, and to determine whether the type exists, if it does not exist will be ignored this event and continue continue to process the next event. Hl.foreach (...), calls the HL's foreach function , foreach traverses each handler in the Hl.handlers, and executes the action specified by the second argument for each handler. The action is func (H *handler) {if e.event!= nil{h.sendmessage (E)}}, which calls the handler of each SendMessage to send event e. The SendMessage is to send the event e:err: = D.chatstream.send (msg) by using the generated GRPC streaming service interface of the handler Chatstream .

The flowchart is as follows:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.