前言

使用 grpc-gateway 将 rpc API 转成 Http 接口
库:github.com/grpc-ecosystem/grpc-gateway/v2


一、grpc-gateway是什么?

gRPC-Gateway 是 Google 协议缓冲区编译器 protoc 的插件。它读取 protobuf 服务定义并生成一个反向代理服务器,该服务器将 RESTful HTTP API 转换为 gRPC。该服务器是根据google.api.http您的服务定义中的注释生成的。

这有助于您同时提供 gRPC 和 HTTP/JSON 格式的 API。
在这里插入图片描述

二、使用步骤

先看我的目录结构
在这里插入图片描述

1.proto 文件编写

代码如下(示例):

syntax = "proto3";

package helloworld;
option go_package="./hello";

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;
}

2.使用 buf 生成 相应.go 文件

buf 安装连接

  1. buf.yaml 文件:
    version: v1
    deps:
      - buf.build/googleapis/googleapis
    
  2. buf.gen.yaml
    version: v1
    plugins:
     - name: go
       out: ../pkg
       opt: paths=source_relative
     - name: go-grpc
       out: ../pkg
       opt: paths=source_relative
     - name: grpc-gateway
       out: ../pkg
       opt: paths=source_relative
    
  3. 使用buf 生成
     buf generate
    
    这里我使用的是Makefile 如下:
    generate:
    	cd proto; buf generate
    run:
    	cd cmd; go run main.go
    clean:
    	rm -rf pkg
    

3.grpc及http 路由注册

main.go:

实现proto 文件定义的rpc 接口

type server struct{
	hello.UnimplementedGreeterServer
}

func NewServer() *server {
	return &server{}
}

func (s *server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) {
	return &hello.HelloReply{Message: in.Name + " world"}, nil
}

注册 grpc 与 http

// 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
	hello.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.WithTransportCredentials(insecure.NewCredentials()),
	)
	if err != nil {
		log.Fatalln("Failed to dial server:", err)
	}

	// 注册http 接口
	gwmux := runtime.NewServeMux()
	// Register Greeter
	err = hello.RegisterGreeterHandler(context.Background(), gwmux, conn)
	if err != nil {
		log.Fatalln("Failed to register gateway:", err)
	}

	gwServer := &http.Server{
		Addr:    ":8090",
		Handler: gwmux,
	}

	log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
	log.Fatalln(gwServer.ListenAndServe())


总结

本文仅仅介绍了 grpc-gateway 简单用法,就是将grpc 接口转成http,既保证了微服务之间的调用, 也让前端能够直接调用,不需要再去写一个http接口或者 使用nodejs 作为中间层去请求后段的grpc 。后面将继续推进 多路复用 mux 中的拦截器以及注册进gin路由中。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐