接下来重点讲如何创建并通过http 使用rpc接口 。 proto代码
syntax = "proto3"; package proto.web.web.proto; option go_package = "pb;pb"; // 进入 message ComeIn { string name = 1; // 名称 string trait = 2; // ip } // 离开 message GetOut { string name = 1; // 名称 string ip = 2; // ip } service Web { rpc WebService(ComeIn) returns (GetOut); }生成web.pb.go文件 需要下载可运行的exe文件,根据提示下载即可
protoc --go_out=plugins=grpc:. proto/web/*.protoweb_server.go代码 服务端代码
var _ pb.WebServer = &Server{} type Server {} func (s *Server) WebService(ctx context.Context, c*pb.ComeIn) (*pb.GetOut, error) { return &pb.GetOut{Name:c.Name,Ip:c.Ip}, nil } func main (){ web := grpc.NewServer() pb.RegisterWebServer(web, &Server{}) lis, err := net.Listen("tcp", ":8089") if err != nil { panic(err) } // 协程启动 go func() { if err := web.Serve(lis); err != nil {panic(err)} }() // 自动优雅停止,tpc避免占用资源 c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) for { s := <-c switch s { case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: web.GracefulStop() return } } }web_client.go 客户端代码
type Server struct { engine *gin.Engine webClient pb.WebServerClient } // 创建一个rpc 客户端启动器 func InitWebServer(addr string) pb.WebServerClient{ ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second)) defer cancel() conn, err := grpc.DialContext(ctx, addr, []grpc.DialOption{ grpc.WithInsecure(), grpc.WithInitialWindowSize(grpcInitialWindowSize), grpc.WithInitialConnWindowSize(grpcInitialConnWindowSize), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(grpcMaxCallMsgSize)), grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(grpcMaxSendMsgSize)), grpc.WithBackoffMaxDelay(grpcBackoffMaxDelay), grpc.WithKeepaliveParams(keepalive.ClientParameters{ Time: grpcKeepAliveTime, Timeout: grpcKeepAliveTimeout, PermitWithoutStream: true, }), grpc.WithBalancerName(roundrobin.Name), }...) if err != nil { panic(err) } return pb.NewWebServerClient(conn) } // 使用rpc接口 func (s *Server) CallWeb(txt *gin.Context){ var in *pb.ComeIn{} if err := txt.BindJSON(&in);err != nil {// 接收到的值赋值给 ComeIn中,如果字段错误会报无法给name为:xxx字段赋值 panic(err.Error()) } out,err := s.webClient.WebService(context.Background(),in) // 此处调用rpc if err != nil { panic(err.Error()) } txt.JSON(http.StatusOK,out) // 成功响应 } // http 服务,使用gin包 func NewHttp(httpAddr string,rpcAddr string){ h := gin.Default() go func(){ if err := r.Run(httpAddr); err != nil {panic(err)} }() s := Server{ engine: h webClient: InitWebServer(rpcAddr) // 端口要一致,否则报错 rpc 没有注册 } s.engine.Get(/hello,s.CallWeb)// 注册http路由 } func main (){ NewHttp(":4399",":8089") }通过浏览器输入 ip+:端口?name=xxx&ip=xxx 就可以看到响应了