packagemainimport("context""fmt""log""net"pb"github.com/lixd/grpc-go-example/features/proto/echo""google.golang.org/grpc")constaddr="localhost:50051"typeecServerstruct{pb.UnimplementedEchoServeraddrstring}func(s*ecServer)UnaryEcho(ctxcontext.Context,req*pb.EchoRequest)(*pb.EchoResponse,error){return&pb.EchoResponse{Message:fmt.Sprintf("%s (from %s)",req.Message,s.addr)},nil}funcmain(){lis,err:=net.Listen("tcp",addr)iferr!=nil{log.Fatalf("failed to listen: %v",err)}s:=grpc.NewServer()pb.RegisterEchoServer(s,&ecServer{addr:addr})log.Printf("serving on %s\n",addr)iferr:=s.Serve(lis);err!=nil{log.Fatalf("failed to serve: %v",err)}}
packagemainimport("context""fmt""log""time"pb"github.com/lixd/grpc-go-example/features/proto/echo""google.golang.org/grpc""google.golang.org/grpc/resolver")const(myScheme="17x"myServiceName="resolver.17x.lixueduan.com"backendAddr="localhost:50051")funccallUnaryEcho(cpb.EchoClient,messagestring){ctx,cancel:=context.WithTimeout(context.Background(),time.Second)defercancel()r,err:=c.UnaryEcho(ctx,&pb.EchoRequest{Message:message})iferr!=nil{log.Fatalf("could not greet: %v",err)}fmt.Println(r.Message)}funcmakeRPCs(cc*grpc.ClientConn,nint){hwc:=pb.NewEchoClient(cc)fori:=0;i<n;i++{callUnaryEcho(hwc,"this is examples/name_resolving")}}funcmain(){passthroughConn,err:=grpc.Dial(// passthrough 也是gRPC内置的一个schemefmt.Sprintf("passthrough:///%s",backendAddr),// Dial to "passthrough:///localhost:50051"grpc.WithInsecure(),grpc.WithBlock(),)iferr!=nil{log.Fatalf("did not connect: %v",err)}deferpassthroughConn.Close()fmt.Printf("--- calling helloworld.Greeter/SayHello to \"passthrough:///%s\"\n",backendAddr)makeRPCs(passthroughConn,10)fmt.Println()ctx,cancel:=context.WithTimeout(context.Background(),time.Second*3)defercancel()exampleConn,err:=grpc.DialContext(ctx,fmt.Sprintf("%s:///%s",myScheme,myServiceName),// Dial to "17x:///resolver.17x.lixueduan.com"grpc.WithInsecure(),grpc.WithBlock(),)iferr!=nil{log.Fatalf("did not connect: %v",err)}deferexampleConn.Close()fmt.Printf("--- calling helloworld.Greeter/SayHello to \"%s:///%s\"\n",myScheme,myServiceName)makeRPCs(exampleConn,10)}
// Following is an example name resolver. It includes a// ResolverBuilder(https://godoc.org/google.golang.org/grpc/resolver#Builder)// and a Resolver(https://godoc.org/google.golang.org/grpc/resolver#Resolver).//
// A ResolverBuilder is registered for a scheme (in this example, "example" is// the scheme). When a ClientConn is created for this scheme, the// ResolverBuilder will be picked to build a Resolver. Note that a new Resolver// is built for each ClientConn. The Resolver will watch the updates for the// target, and send updates to the ClientConn.// exampleResolverBuilder is a// ResolverBuilder(https://godoc.org/google.golang.org/grpc/resolver#Builder).typeexampleResolverBuilderstruct{}func(*exampleResolverBuilder)Build(targetresolver.Target,ccresolver.ClientConn,optsresolver.BuildOptions)(resolver.Resolver,error){r:=&exampleResolver{target:target,cc:cc,addrsStore:map[string][]string{myServiceName:{backendAddr},},}r.ResolveNow(resolver.ResolveNowOptions{})returnr,nil}func(*exampleResolverBuilder)Scheme()string{returnmyScheme}// exampleResolver is a// Resolver(https://godoc.org/google.golang.org/grpc/resolver#Resolver).typeexampleResolverstruct{targetresolver.Targetccresolver.ClientConnaddrsStoremap[string][]string}func(r*exampleResolver)ResolveNow(oresolver.ResolveNowOptions){// 直接从map中取出对于的addrListaddrStrs:=r.addrsStore[r.target.Endpoint]addrs:=make([]resolver.Address,len(addrStrs))fori,s:=rangeaddrStrs{addrs[i]=resolver.Address{Addr:s}}r.cc.UpdateState(resolver.State{Addresses:addrs})}func(*exampleResolver)Close(){}funcinit(){// Register the example ResolverBuilder. This is usually done in a package's// init() function.resolver.Register(&exampleResolverBuilder{})}
lixd@17x:~/17x/projects/grpc-go-example/features/name_resolving/client$ go run main.go
--- calling helloworld.Greeter/SayHello to "passthrough:///localhost:50051"this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)--- calling helloworld.Greeter/SayHello to "17x:///resolver.17x.lixueduan.com"this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)this is examples/name_resolving (from localhost:50051)
funcinit(){// Register the example ResolverBuilder. This is usually done in a package's// init() function.resolver.Register(&exampleResolverBuilder{})}funcRegister(bBuilder){m[b.Scheme()]=b}
// clientconn.go 312行// Build the resolver.rWrapper,err:=newCCResolverWrapper(cc,resolverBuilder)iferr!=nil{returnnil,fmt.Errorf("failed to build resolver: %v",err)}// resolver_conn_wapper.go 48行// newCCResolverWrapper uses the resolver.Builder to build a Resolver and// returns a ccResolverWrapper object which wraps the newly built resolver.funcnewCCResolverWrapper(cc*ClientConn,rbresolver.Builder)(*ccResolverWrapper,error){ccr:=&ccResolverWrapper{cc:cc,done:grpcsync.NewEvent(),}varcredsClonecredentials.TransportCredentialsifcreds:=cc.dopts.copts.TransportCredentials;creds!=nil{credsClone=creds.Clone()}rbo:=resolver.BuildOptions{DisableServiceConfig:cc.dopts.disableServiceConfig,DialCreds:credsClone,CredsBundle:cc.dopts.copts.CredsBundle,Dialer:cc.dopts.copts.Dialer,}varerrerrorccr.resolverMu.Lock()deferccr.resolverMu.Unlock()// 调用resolverBuilder的Build方法构建Resolverccr.resolver,err=rb.Build(cc.parsedTarget,ccr,rbo)iferr!=nil{returnnil,err}returnccr,nil}