gRPC-Gateway(1)实现一个HTTP服务

0. 简介

gRPC-Gateway是一个protoc的插件,其读取gRPC的服务定义,并且生成一个反向代理的服务器,用于将外界的RESTful JSON API转换为gRPC请求。

为什么有个gRPC,还需要gRPC-Gateway

gRPC-Gateway作为gRPC服务的反向代理,充当了客户端的Restful应用程序,使得相同的代码库同时支持Restful/JSON和gRPC的可能,在以下两个场景中,gRPC-Gateway是必要的:

  • 旧版本的客户端可能只支持Restful/JSON接口;
  • 浏览器并不支持gRPC,因此要想与Web互动,需要gRPC-Gateway。

1. 服务定义

我们以gRPC-Go基础(3)基础gRPC服务的一元RCP为例子,在其中的服务定义中加上google.api.http,更多参考the source file documentation.

proto 复制代码
message SimpleResponse {
  int32 code = 1;
  string data = 2;
}

message StreamRequest{
  int32 id = 1;
  string stream_data = 2;
}

service Route {
  rpc RouteList(StreamRequest) returns (SimpleResponse){
    option (google.api.http) = {
      get: "/v1/simple/{id}"
    };
  };
}

然后再生成代码:

bash 复制代码
protoc -I./proto \
--go_out=./genproto --go_opt paths=source_relative \
--go-grpc_out=./genproto --go-grpc_opt paths=source_relative \
--grpc-gateway_out=./genproto --grpc-gateway_opt paths=source_relative \
./proto/*/*.proto

2. 逻辑代码

go 复制代码
package handler

import (
    "context"
    "grpc-gateway-demo/api/demopb"
)

type SimpleHandler struct {
    demopb.UnimplementedSimpleServer
}

func NewSimpleHandler() *SimpleHandler {
    return &SimpleHandler{}
}

func (s SimpleHandler) Get(ctx context.Context, request *demopb.SimpleRequest) (*demopb.SimpleResponse, error) {
    return &demopb.SimpleResponse{
       Code: 0,
       Data: "simple",
    }, nil
}

main函数:

go 复制代码
func main() {
    // 起grpc
    lis, err := net.Listen("tcp", ":8080")
    if err != nil {
       log.Fatal(err)
    }
    
    s := grpc.NewServer()
    demopb.RegisterSimpleServer(s, handler.NewSimpleHandler())
    log.Printf("Serve Grpc on %s", ":8080")
    go func() {
       if err := s.Serve(lis); err != nil {
          log.Fatal(err)
       }
    }()

    // 起grpc-gateway
    gwMux := runtime.NewServeMux()
    err = demopb.RegisterSimpleHandlerFromEndpoint(context.Background(),
       gwMux,
       ":8080",
       []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
    if err != nil {
       log.Fatal(err)
    }
    gwServer := &http.Server{
       Addr:    ":8081",
       Handler: gwMux,
    }
    log.Printf("Serve Gateway on %s", ":8081")
    if err = gwServer.ListenAndServe(); err != nil {
       log.Fatal(err)
    }
}

可以看出,grpc-gateway是起了一个tcp链接(":8080"端口)指向grpc服务,并且在本地起一个http的服务(":8081"端口),从而实现反向代理。

起服务后,可以在本地浏览器输入:http://localhost:8081/v1/simple/1,会出现以下回应:

bash 复制代码
{
     "code": 0,
     "data": "simple"
}

这就使用grpc-gateway实现了一个简单的HTTP的服务!

相关推荐
许野平11 天前
Rust:设计 gRPC 客户端
开发语言·后端·rust·grpc·tonic
钢铁小狗侠18 天前
如何在windows上下载和编译grpc
grpc
寒烟说1 个月前
用 Go 语言实现一个最简单的 gRPC 服务端
开发语言·后端·golang·grpc
陈亦康1 个月前
Armeria gPRC 高级特性 - 装饰器、无框架请求、阻塞处理器、Nacos集成、负载均衡、rpc异常处理、文档服务......
kotlin·grpc·armeria
假装我不帅2 个月前
asp.net core grpc快速入门
后端·asp.net·grpc
cci2 个月前
Rust gRPC---Tonic教程
后端·rust·grpc
磐石区2 个月前
gRPC etcd 服务注册与发现、自定义负载均衡
服务发现·负载均衡·etcd·grpc·picker
Mindfulness code2 个月前
使用 gRPC
开发语言·grpc
crossoverJie2 个月前
OpenTelemetry 实战:gRPC 监控的实现原理
grpc·opentelemetry
czl3893 个月前
gRPC golang开发实践
golang·grpc·protobuf