Grpc Golang version of the source code analysis of the client (i) __GRPC

Source: Internet
Author: User
Table of Contents1. Foreword 2. Source Directory Browse 3. Client 4. RELATED LINKS 1 Preface

GRPC is a generic RPC framework, implemented with Google, and of course, the version of the Go language. In the work of the main use of this library, so look at the source to strengthen their understanding of the framework. At present, the main analysis is to go version of the main (and no other language version). Because of the limited personal level, some of the ideas in the code is also personal speculation, inevitably some mistakes, if found wrong, also hope to help point out. 2 Source Directory browsing

Grpc use Protobuf (Google's serialization framework) as a communication protocol, the bottom of the use of HTTP2 as its transport protocol, GRPC source code to achieve its own HTTP2 server and client, and did not use Net/http package. HTTP2 has a lot of features can be efficient transmission of data, specific features can see the relevant links to learn more. Grpc directory is as follows: Look at the name can be seen in these directories are the relationship between the code, Documentation directory is to store some documents, benchmark is the test, credentials is validation, examples is an example, GRPCLB is load balancing, Grpclog is a log, health is a service health check, metadata is metadata (user clients to the server to send some special data, can see the relevant links), naming directory is to provide the name service needs to implement interface (equivalent to a DNS), stats is statistical information , Transport transport Layer implementation (mainly HTTP2 client and server implementation, not in detail this directory), there are some other relatively insignificant directories are not introduced. 3 Client

There are two simple examples in the example directory, so let's start here,

  func   main  () {//Set up a connection to the server. Create a link conn, err: = Grpc.  Dial  (address, Grpc.)  Withinsecure  ())  if  err!= nil {log.  Fatalf  ("Did not connect:%v", err)}  defer  conn.  Close  () c: = PB.  Newgreeterclient 
  (conn)//contacts the server and print out its response. Name: = DefaultName  if  len (OS. Args) > 1 {name = OS. ARGS[1]}//Call function R, err: = C.  SayHello  (context.  Background  (), &PB. Hellorequest{name:name})  if  err!= nil {log.  Fatalf  ("Could not greet:%v", err)} log.  Printf 
("Greeting:%s", R.message)} 

GRCP. The withinsecure parameter is to link the HTTPS server without checking the server's credentials (if you believe the server does not need to be checked). The dial function establishes a connection to the server, Grpc. Dial function:

func Dialcontext(CTX context.) Context, target string, opts ... Dialoption) (conn *clientconn, err error) {cc: = &clientconn{target:target, Conns:make (Map[Address]*addrconn),} cc.ctx, Cc.cancel = context.Withcancel(Context.Background())defer func() {Select{ Case<-ctx. Done(): conn, err = nil, ctx.ERR()default:
    }ifErr!= nil {cc. Close()} ()//Set various options for GRPC for_, Opt: =RangeOPTs {opt(&cc.dopts)} Set defaults.ifCc.dopts.codec = = Nil {//default Protobuf codec Cc.dopts.codec = protocodec{}}ifCc.dopts.bs = = Nil {cc.dopts.bs = defaultbackoffconfig} creds: = cc.dopts.copts.TransportCredentials//authentication informationifCreds!= Nil && creds.Info(). ServerName!= "" {cc.authority = creds.Info(). ServerName}Else{colonpos: = strings.lastindex(Target, ":")ifColonpos = = 1 {colonpos = Len (target)} cc.authority = Target[:colonpos]}varOK bool WAITC: = Make (ChanError, 1)//Start a goroutine start name server (similar to DNS) Go func() {varAddrs []addressifCc.dopts.balancer = = Nil {//Connect to target directly if Balancer is nil. If the load balancer is not set, direct connection Addrs = Append (Addrs, address{addr:target})}Else{varCredsclone credentials. TransportcredentialsifCreds!= Nil {credsclone = creds.Clone()} config: = balancerconfig{dialcreds:credsclone,}/Start load Balancing ServiceifERR: = Cc.dopts.balancer.Start(target, config); Err!= Nil {WAITC <-err returnCH: = Cc.dopts.balancer.Notify()ifch = = Nil {//There is no Name resolver installed. Addrs = Append (Addrs, address{addr:target})}Else{Addrs, OK = <-chif!ok | | Len (Addrs) = = 0 {WAITC <-errnoaddr return}
      }
    } for_, A: =RangeAddrs {//Give each address a conn, connection poolifERR: = cc.Resetaddrconn(A, false, nil); Err!= Nil {WAITC <-err return} Close (WAITC)} ()varTimeoutch <-ChanTime. TimeifCc.dopts.timeout > 0 {timeoutch = time. After(Cc.dopts.timeout)}Select{ Case<-ctx. Done(): returnNil, CTX.ERR() CaseERR: = &LT;-WAITC:ifErr!= Nil { returnNil, err} Case<-timeoutch: returnNil, errclientconntimeout}//If balancer is nil or balancer.
  Notify () is nil, ok'll be false here. The Lbwatcher Goroutine won't be created.ifOK { GoCc.Lbwatcher()
  } returnCC, NIL}

By dial this function, GRPC has established a connection to the server, starting a custom load balancing (if any). Pb. Newgreeterclient This line of code is automatically generated by the Protoc tool, which packs a GRPC connection package within a struct to facilitate invoking the generated client Grpc calling code. Next, the GRPC client calls SayHello to send an RPC request to the server.

func(c *greeterclient)SayHello(CTX context.) Context, in *hellorequest, opts ... grpc. Calloption) (*helloreply, error) {out: = new (helloreply)//Invoke the actual Send request function err: = Grpc.Invoke(CTX, "/helloworld.") Greeter/sayhello ", in, out, c.cc, opts ...)ifErr!= Nil { returnNil, err} returnOut, nil}//last mainly invoke functionfunc Invoke(CTX context.) Context, method string, args, replyInterface{}, CC *clientconn, opts ... calloption) (e error) {c: = Defaultcallinfo for_, O: =RangeOPTs {//hook before callingifERR: = O.before(&AMP;C); Err!= Nil { return Torpcerr(ERR)} }defer func() { for_, O: =RangeOPTs {//after execution of Hook O. After(&AMP;C)} } ()//trace related codeifenabletracing {c.traceinfo.tr = trace.New("Grpc.") Sent. " +methodfamily(method), method)deferc.traceinfo.tr.Finish() C.traceinfo.firstline.client = TrueifDeadline, OK: = ctx.deadline(); OK {c.traceinfo.firstline.deadline = deadline.Sub(Time. Now())} c.traceinfo.tr.Lazylog(&c.traceinfo.firstline, False)//TODO (Dsymonds): Arrange for c.traceinfo.firstline.remoteaddr to is set.defer func() {ifE!= Nil {c.traceinfo.tr.Lazylog(&fmtstringer{"%v", []Interface{}{e}}, True) c.traceinfo.tr.SetError()} ()}//Statistics related codeifStats. on() {ctx = stats.Tagrpc(CTX, &stats.) Rpctaginfo{fullmethodname:method}) Begin: = &stats. begin{Client:true, Begintime:time. Now(), Failfast:c.failfast,} stats.Handlerpc(CTX, Begin)}defer func() {//End statistics related codeifStats. on() {End: = &stats. end{

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.