Welcome to my GitHub

https://github.com/zq2599/blog_demos

Content: Classification and summary of all original articles and supporting source code, involving Java, Docker, Kubernetes, DevOPS, etc.;

Links to gRPC learning series articles

  1. deploy and set GO
  2. GO's gRPC development environment preparation
  3. first trial GO version gRPC development
  4. Four types of actual service methods
  5. gRPC-Gateway actual combat
  6. gRPC-Gateway integrated swagger

Overview of this article

  • This article is the fifth chapter of the "gRPC Learning" series. gRPC is often used for mutual calls between servers. If you want to expose the service to the front end, although you can modify the server by hand, it seems to increase a lot of work. You can also choose gRPC-Gateway to quickly expose gRPC services in http;
  • The principle of gRPC-Gateway is shown in the figure below. With the help of the grpc-gateway plug-in, you can generate reverse proxy (Reverse Proxy) code based on the proto file. After this reverse proxy runs, it provides RESTful services to the outside world. After receiving the RESTful request, you can call the original through gRPC GRPC service:

在这里插入图片描述

  • This article shows the entire process of building, developing, and verifying the gRPC-Gateway environment, which consists of the following steps:
  • Build gRPC-Gateway environment extremely fast;
  • Write proto file;
  • Generate gRPC and gRPC-Gateway source code according to the proto file;
  • Add business code;
  • Compile, run, and verify;

Specify files and directories in advance

  • In this actual combat, a new folder <font color="red">helloworld</font> is added under the <font color="blue">$GOPATH/src</font> directory, which contains the following contents in total:
[golang@centos7 src]$ tree helloworld/
helloworld/
├── gateway
│   └── helloworld.gw.go
├── helloworld.pb.go
├── helloworld.pb.gw.go
├── helloworld.proto
├── helloworld.swagger.json
└── server
    └── server.go
  • The preparation work is completed, and then the development will officially start;

Prerequisites

Quickly build gRPC-Gateway environment

  • The so-called <font color="blue">build gRPC-Gateway environment</font> actually accomplishes the following three things:

在这里插入图片描述

  1. When setting up the environment, I referred to some online articles, but I encountered various problems and have not been successful (of course I don’t think there is a problem with the article, I must realize that it is caused by my lack of ability);
  2. After repeated tossing and finally succeeding, I made all the operations into a shell script, and executed the following commands to complete all the operations in the above picture:
curl -o install-grpc-gateway.sh \
https://raw.githubusercontent.com/zq2599/blog_demos/master/files/install-grpc-gateway.sh \
&& chmod a+x ./install-grpc-gateway.sh \
&& ./install-grpc-gateway.sh
  1. Enter the <font color="blue">$GOPATH/bin</font> directory, you can see two new files <font color="red">protoc-gen-grpc-gateway</font> and <font color=" blue">protoc-gen-swagger</font>:
[golang@centos7 ~]$ cd $GOPATH/bin
[golang@centos7 bin]$ ls -al
总用量 26708
drwxrwxr-x. 2 golang golang      98 12月 19 08:59 .
drwxrwxr-x. 5 golang golang      39 12月 19 08:21 ..
-rwxr-x---. 1 golang golang 5253272 12月 19 08:20 protoc
-rwxrwxr-x. 1 golang golang 8461147 12月 19 08:21 protoc-gen-go
-rwxrwxr-x. 1 golang golang 6717463 12月 19 08:59 protoc-gen-grpc-gateway
-rwxrwxr-x. 1 golang golang 6908535 12月 19 08:59 protoc-gen-swagger
  • Now that the environment is ready, start development;

Write proto file

  • In the <font color="blue">$GOPATH/src</font> directory, create a new folder <font color="blue">helloworld</font>, and create a new file <font color="red">helloworld. proto</font>, the content is as follows, there are several points to be noted later:
// 协议类型
syntax = "proto3";

// 包名
package helloworld;

import "google/api/annotations.proto";

// 定义的服务名
service Greeter {
  // 具体的远程服务方法
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/helloworld"
      body: "*"
    };
  }
}

// SayHello方法的入参,只有一个字符串字段
message HelloRequest {
  string name = 1;
}

// SayHello方法的返回值,只有一个字符串字段
message HelloReply {
  string message = 1;
}
  • The above proto file has the following points to pay attention to:
  • The whole file is actually "GRPC Development of Initial GO Version" , with two additions;
  • The first addition is to use the keyword <font color="blue">import</font> to import <font color="red">google/api/annotations.proto</font>;
  • The second place added is the declaration of the <font color="blue">SayHello</font> method, and the <font color="red">option</font> configuration is added to configure the <font color=" blue">The information of the RESTful interface exposed by the SayHello</font> method;
  • When using <font color="blue">protoc-gen-grpc-gateway</font>, the above two configurations will be recognized and the corresponding code will be generated;

Generate gRPC and gRPC-Gateway source code according to the proto file

  1. The proto file is written, and the next step is to generate the source code of gRPC and gRPC-Gateway;
  2. The command to generate gRPC source code has been used in the previous article, as follows:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
helloworld.proto
  1. After the execution is complete, the <font color="blue">helloworld.pb.go</font> file will be generated in the current directory;
  2. Execute the command to generate gRPC-Gateway source code:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
helloworld.proto
  1. After the execution is completed, the <font color="blue">helloworld.pb.gw.go</font> file will be generated in the current directory;
  2. Execute the command to generate the swagger file:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--swagger_out=logtostderr=true:. \
helloworld.proto
  1. After the execution is completed, the <font color="blue">helloworld.swagger.json</font> file will be generated in the current directory;
  2. So far, there are these contents under the helloworld directory:
[golang@centos7 src]$ tree helloworld/
helloworld/
├── helloworld.pb.go
├── helloworld.pb.gw.go
├── helloworld.proto
└── helloworld.swagger.json

0 directories, 4 files
  1. Next, start coding and complete the code required to run the entire service;
  2. Due to space limitations, this article does not mention swagger-related development and verification for the time being, so the generated <font color="blue">helloworld.swagger.json</font> file is not available for this article and will be used in the next article;

Write server code server.go and start

  1. Next, write the server code server.go, which is the same as the content of "Initial GO version gRPC development" 160c2ae9537761;
  2. Create a new folder <font color="red">server</font> in the <font color="blue">$GOPATH/src/helloworld</font> directory, and create a new <font color="red under this folder ">server.go</font>, the content is as follows, detailed notes have been added:
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "helloworld"
)

const (
    port = ":50051"
)

// 定义结构体,在调用注册api的时候作为入参,
// 该结构体会带上SayHello方法,里面是业务代码
// 这样远程调用时就执行了业务代码了
type server struct {
    // pb.go中自动生成的,是个空结构体
    pb.UnimplementedGreeterServer
}

// 业务代码在此写,客户端远程调用SayHello时,
// 会执行这里的代码
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    // 打印请求参数
    log.Printf("Received: %v", in.GetName())
    // 实例化结构体HelloReply,作为返回值
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
    // 要监听的协议和端口
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    // 实例化gRPC server结构体
    s := grpc.NewServer()

    // 服务注册
    pb.RegisterGreeterServer(s, &server{})

    log.Println("开始监听,等待远程调用...")

    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}
  1. Execute <font color="blue">go run server.go</font> in the directory where server.go is located, and the console prompt is as follows:
[golang@centos7 server]$ go run server.go 
2020/12/13 08:20:32 开始监听,等待远程调用...
  1. At this point, the gRPC server has been started and can respond to remote calls. Next, develop a reverse proxy (Reverse Proxy);

Write Reverse Proxy code helloworld.gw.go and start

package main

import (
    "flag"
    "fmt"
    "net/http"
    gw "helloworld"

    "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

var (
    echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "endpoint of YourService")
)

func run() error {

    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    mux := runtime.NewServeMux()
    opts := []grpc.DialOption{grpc.WithInsecure()}
    err := gw.RegisterGreeterHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)

    if err != nil {
        return err
    }

    return http.ListenAndServe(":9090", mux)
}

func main() {
    if err := run(); err != nil {
        fmt.Print(err.Error())
    }
}
  1. The first place to pay attention to is to call <font color="blue">http.ListenAndServe</font> to monitor port 9090<font color="blue"></font>, which is the port for externally providing RESTful services;
  2. The second place to pay attention to is that <font color="blue">echoEndpoint</font> is configured to forward external RESTful requests to the entrance where server.go provides gRPC services;
  3. The third place to pay attention to is that the RegisterGreeterHandlerFromEndpoint method in the automatically generated code is called to complete the binding of upstream and downstream calls;
  4. Execute <font color="blue">go run hellowworld.gw.go</font> in the directory where <font color="blue">hellowworld.gw.go</font> is located, and start monitoring web requests on port 9090;

verification

  1. To verify on this machine, use curl to send a request:
curl \
-X POST \
-d '{"name": "will"}' \
192.168.133.203:9090/helloworld
  1. The response received is as follows. This is the content from server.go. It can be seen that the http request reaches the real gRPC service provider through Reserve Proxy and is returned to the caller smoothly:
{"message":"Hello will"}
  1. Look at the log of server.go as follows:
[golang@centos7 server]$ go run server.go 
2020/12/19 14:16:47 开始监听,等待远程调用...
2020/12/19 14:24:35 Received: will
  1. You can also pass the <font color="blue">postman</font> verification on other machines, remember to turn off the firewall of the machine where the service is located, the request and response are as follows, pay attention to the numerical order setting and observation:

在这里插入图片描述

You are not lonely, Xinchen is with you all the way

  1. Java series
  2. Spring series
  3. Docker series
  4. kubernetes series
  5. database + middleware series
  6. DevOps series

Welcome to pay attention to the public account: programmer Xin Chen

Search "Programmer Xin Chen" on WeChat, I am Xin Chen, and I look forward to traveling the Java world with you...
https://github.com/zq2599/blog_demos

程序员欣宸
147 声望24 粉丝

热爱Java和Docker