• 一个简单的go使用grpc的案例


    今日学习grpc通信,做一个简单的小demo来验证效果

    一,默认已经装好了环境

    如果没有装环境,简单的装一下

    1,装protocol Buffer

    https://juejin.cn/post/7137709231624421412

    2,装go的grpc包,其实就是go get 引入

    go get github.com/golang/protobuf/protoc-gen-go

    二,写一个A服务作为被调用方,B服务去调用A服务

    新建一个A项目
    在这里插入图片描述
    建立一个目录用于存proto文件,并新建一个proto文件,这个随便命名
    在这里插入图片描述
    AService.proto

    // 指定当前proto版本
    // proto的语法注意分号,写go写习惯的话,会经常遗漏分号
    syntax = "proto3";
    // 指定生成proto生成的go文件的目录和包名,本身是一个路径,如果没有配置包名,最后的一个目录会被当做包名
    option go_package = "../service";
    
    // 定义request model,假设A服务有个User的一些操作的model
    // 假设当前功能是传入userName 和 userPassword
    message UserRequest{
      string user_name = 1; // 这里“=”后面的数字代表顺序,与真实值无关
      string user_password = 2;
    }
    // 定义response model
    // 假设当前功能是返回userID和Token
    message UserResponse{
      string user_id = 1;
      string user_token= 2;
    }
    // 定义服务能提供的服务
    service UserService{
      // 定义具体的方法,此定义更像一个接口(interface),他不做具体实现,只是声明该Grpc能调用的方法
      rpc GetUserToken(UserRequest) returns(UserResponse);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    进入到protobufFile目录下(cd protobufFile),执行生成
    protoc --go_out=plugins=grpc:./ .\AServer.proto

    这时候可以看到已经生成了service目录和一个pb.go文件
    在这里插入图片描述
    这个文件里可以看到刚才我们定义的service UserService,连proto文件里的注释也一并被拿了进来

    在这里插入图片描述

    所以下一部就是按照这个“接口”进行方法实现,当然,真正的业务拆分环境当中,都是先实现了方法,然后按服务拆分的时候做响应的接口编写,通常,我们称之为“暴露”,就是给其他服务暴露出来某某方法以供调用。

    2,方法编写

    在根目录下新建目录model,并新建user.go

    package model
    
    import (
       "context"
       "errors"
       "go-grpc-test-A/service"
    )
    
    var UserServiceServer = &userServiceServer{}
    
    type userServiceServer struct {
    }
    
    func (u userServiceServer) GetUserToken(ctx context.Context, request *service.UserRequest) (*service.UserResponse, error) {
       // 模拟过程
       if request.UserName != "" && request.UserPassword != "" {
          response := service.UserResponse{
             UserId: "123",
             // 验证请求是否成功瞎写的,请不要在意
             UserToken: "你传入的名字和密码是:" + request.UserName + "," + request.UserPassword,
          }
          return &response, nil
       } else {
          err := errors.New("参数不对")
          return &service.UserResponse{}, err
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    3,编写main方法
    package main
    
    import (
       "go-grpc-test-A/model"
       "go-grpc-test-A/service"
       "google.golang.org/grpc"
       "log"
       "net"
    )
    
    func main() {
       grpcServer := grpc.NewServer()
       // 这里第二个参数写我们已经实现接口的model包下的UserServiceServer
       service.RegisterUserServiceServer(grpcServer, model.UserServiceServer)
       listener, err := net.Listen("tcp", ":8001")
       if err != nil {
          log.Fatal("服务监听失败", err)
       }
       _ = grpcServer.Serve(listener)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    4,编写调用方服务,命名为B

    新建项目后,把A项目的service目录和pb.go文件一起copy过来,保持两个项目一致(真实工程当中当然不是手动保持一致),记得运行一下 go mod tidy 把依赖都拉上

    在这里插入图片描述

    编写B服务的main方法

    package main
    
    import (
       "context"
       "fmt"
       "go-grpc-test-B/service"
       "google.golang.org/grpc"
       "google.golang.org/grpc/credentials/insecure"
       "log"
    )
    
    func main() {
       // 建立一个链接,请求A服务
       // 真实项目里肯定是通过配置中心拿服务名称,发给注册中心请求真实的A服务地址,这里都是模拟
       // 第二个参数是配置了一个证书,因为没有证书会报错,但是我们目前没有配置证书,所以需要insecure.NewCredentials()返回一个禁用传输安全的凭据
       connect, err := grpc.Dial(":8001", grpc.WithTransportCredentials(insecure.NewCredentials()))
       if err != nil {
          log.Fatal(err)
       }
       // 记得关闭链接
       defer connect.Close()
       // 调用ASerer.pb.go里面的NewUserServiceClient
       client := service.NewUserServiceClient(connect)
       // 直接调用 A服务中的GetUserToken方法,注意,这是B服务,本地并没有该方法的实现
       response, err := client.GetUserToken(context.Background(), &service.UserRequest{UserName: "我是萝卜", UserPassword: "123456"})
       if err != nil {
          log.Fatal("调用gRPC方法错误: ", err)
       }
    
       fmt.Printf("调用gRPC方法成功,user_id = %s, user_token = %s", response.UserId, response.UserToken)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    5,启动验证

    先启动A服务,启动成功后,启动B服务来调用A服务


    B服务已经能成功访问A服务下的GetToken方法,至此,Grpc调用成功
    在这里插入图片描述

  • 相关阅读:
    GBJ2510-ASEMI电机专用25A整流桥GBJ2510
    Java设计模式之外观模式
    Centos7的yum使用国内源阿里源163源等提高下载速度
    CSS笔记(黑马程序员pink老师前端)定位
    SPI接口协议的学习3
    PLC中ST编程的起保停
    【序列召回推荐】(task3)GNN召回之SR-GNN
    Java ~ Reference ~ WeakReference
    Jmeter性能测试:高并发分布式性能测试
    关于事务的一点思考
  • 原文地址:https://blog.csdn.net/kina100/article/details/126668409