- 1. 前言
- 2. 工作机制
- 3. 新建用户
- 4. 安装工具
- 5. 开始创建helloworld
- 6. 测试
- 7. 总结
本文的主要目的是让读者能够跟着一步一步成功使用grpc-gateway,只有很少的理论知识。2. 工作机制
这是官方给出的一张图片,从上面我们可以得到以下信息:
- 我们需要从 profile-service.proto 文件生成两部分代码
- grpc service代码,stubs代码;
- grpc-gateway 反向代理的代码,即插件stubs代码;
- 接口调用方面,API客户端使用RESTful API直接访问反向代理即可,它会帮你访问gRPC服务;
[test@oyk-test ~]$ useradd test # 新建 test 用户 [test@oyk-test ~]$ passwd test # 修改密码 [test@oyk-test ~]$ sudo vim /etc/sudoers # 为 test 用户增加 sudo 权限,使用wq!保存 # 省略前面部分 ... ## Allow root to run any commands anywhere root ALL=(ALL) ALL test ALL=(ALL) ALL # 省略后面部分 ... [test@oyk-test ~]$ su - test # 切换至 test 用户4. 安装工具
- 安装golang
[test@oyk-test ~]$ sudo yum install golang -y [test@oyk-test ~]$ go version go version go1.13.3 linux/amd64
- 安装protoc
[test@oyk-test ~]$ if [ `arch` == "aarch64" ];then wget https://github.com/protocolbuffers/protobuf/releases/download/v3.10.1/protoc-3.10.1-linux-aarch_64.zip ;elif [ `arch` == 'x86_64' ];then wget https://github.com/protocolbuffers/protobuf/releases/download/v3.10.1/protoc-3.10.1-linux-x86_64.zip ;else echo "暂时没有找别的架构" ;fi [test@oyk-test ~]$ unzip protoc-3.10.1-linux-aarch_64.zip # x86_64 使用 unzip protoc-3.10.1-linux-x86_64.zip [test@oyk-test ~]$ sudo ln -s ~/bin/protoc /bin/protoc [test@oyk-test ~]$ protoc --version libprotoc 3.10.1
- 安装protoc-gen-go
[test@oyk-test ~]$ echo "export GOPROXY=https://goproxy.cn" >> ~/.bashrc && source ~/.bashrc [test@oyk-test ~]$ echo "export GOPATH=~/go" >> ~/.bashrc && source ~/.bashrc [test@oyk-test ~]$ mkdir helloworld && cd helloworld [test@oyk-test helloworld]$ go mod init github.com/test/myrepo # 初始化模块 [test@oyk-test helloworld]$ go install google.golang.org/protobuf/cmd/protoc-gen-go
- 安装protoc-gen-go-grpc
[test@oyk-test helloworld]$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
- 安装protoc-gen-grpc-gateway
[test@oyk-test helloworld]$ go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
- 安装grpc-gateway
[test@oyk-test helloworld]$ mkdir -p $GOPATH/src/github.com/grpc-ecosystem [test@oyk-test helloworld]$ pushd !$ # 需要注意v2.3.0(包含)之后的版本没有third_party, # 也就是没有annotations.proto和http.proto; # v2.3.0之后使用的是buf命令生成stubs源码; [test@oyk-test grpc-ecosystem]$ wget https://github.com/grpc-ecosystem/grpc-gateway/archive/v2.0.0.zip -O grpc-gateway.zip [test@oyk-test grpc-ecosystem]$ unzip grpc-gateway.zip && rm -f grpc-gateway.zip [test@oyk-test grpc-ecosystem]$ mv grpc-gateway-2.0.0 grpc-gateway [test@oyk-test grpc-ecosystem]$ popd
- 添加到PATH
[test@oyk-test helloworld]$ echo "PATH=$PATH:$(go env GOPATH)/bin" >> ~/.bashrc && source ~/.bashrc5. 开始创建helloworld
- 生成stubs文件
[test@oyk-test helloworld]$ mkdir -p proto/helloworld/ # 新建 proto 文件夹 # 然后创建helloworld原型文件 [test@oyk-test helloworld]$ cat > proto/helloworld/helloworld.proto <
- 修改 proto/helloworld/helloworld.proto 如下,并生成反向代理stubs
[test@oyk-test helloworld]$ cat proto/helloworld/helloworld.proto syntax = "proto3"; option go_package = "./;__"; package helloworld; import "google/api/annotations.proto"; // + // Here is the overall greeting service definition where we define all our endpoints service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { // + post: "/v1/example/echo" // + body: "*" // + }; // + } } // The request message containing the user's name message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } // 增加了5行 [test@oyk-test helloworld]$ go mod tidy && go mod download # 更新依赖和安装依赖 [test@oyk-test helloworld]$ mkdir -p proto/google/api/ [test@oyk-test helloworld]$ sudo cp $(go env GOPATH)/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api/{annotations.proto,http.proto} proto/google/api/ [test@oyk-test helloworld]$ protoc -I ./proto --go_out ./proto --go_opt paths=source_relative --go-grpc_out ./proto --go-grpc_opt paths=source_relative --grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative ./proto/helloworld/helloworld.proto # 生成grpc-gateway stubs [test@oyk-test helloworld]$ ls proto/helloworld/ helloworld_grpc.pb.go helloworld.pb.go helloworld.pb.gw.go helloworld.proto # 生成了 helloworld.pb.gw.go
- 写主程序main.go文件
- 编写普通grpc程序
[test@oyk-test helloworld]$ cat main.go package main import ( "context" "log" "net" "google.golang.org/grpc" helloworldpb "github.com/test/myrepo/proto/helloworld" ) type server struct{ helloworldpb.UnimplementedGreeterServer } func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { return &helloworldpb.HelloReply{Message: in.Name + " world"}, nil } func main() { // Create a listener on TCP port lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("Failed to listen:", err) } // Create a gRPC server object s := grpc.NewServer() // Attach the Greeter service to the server helloworldpb.RegisterGreeterServer(s, &server{}) // Serve gRPC Server log.Println("Serving gRPC on 0.0.0.0:8080") log.Fatal(s.Serve(lis)) }
- 改写普通grpc程序,增加代理代码,使用8081端口代理8080
[test@oyk-test helloworld]$ cat main.gopackage main import ( "context" "log" "net" "net/http" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" helloworldpb "github.com/test/myrepo/proto/helloworld" ) type server struct{ helloworldpb.UnimplementedGreeterServer } func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { return &helloworldpb.HelloReply{Message: in.Name + " world"}, nil } func main() { // Create a listener on TCP port lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("Failed to listen:", err) } // Create a gRPC server object s := grpc.NewServer() // Attach the Greeter service to the server helloworldpb.RegisterGreeterServer(s, &server{}) // Serve gRPC server log.Println("Serving gRPC on 0.0.0.0:8080") go func() { log.Fatalln(s.Serve(lis)) }() // Create a client connection to the gRPC server we just started // This is where the gRPC-Gateway proxies the requests conn, err := grpc.DialContext( context.Background(), "0.0.0.0:8080", grpc.WithBlock(), grpc.WithInsecure(), ) if err != nil { log.Fatalln("Failed to dial server:", err) } gwmux := runtime.NewServeMux() // Register Greeter err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn) if err != nil { log.Fatalln("Failed to register gateway:", err) } gwServer := &http.Server{ Addr: ":8081", Handler: gwmux, } log.Println("Serving gRPC-Gateway on http://0.0.0.0:8081") log.Fatalln(gwServer.ListenAndServe()) }6. 测试在本机上执行:
[root@localhost proto]# curl -X POST -k http://localhost:8081/v1/example/echo -d '{"name": " hello"}' {"message":" hello world"}7. 总结以上就是本文的全部内容,有任何问题请指出,包括错别字。



