【gRPC-gateway】初探grpc网关,插件安装,默认实现,go案例

server/2025/2/6 18:18:42/

gateway_0">grpc-gateway

https://github.com/grpc-ecosystem/grpc-gateway

作用

  1. 通过反向代理的方式,将grpc server接口转为http+json api

使用场景

  1. 向后兼容
  2. 支持grpc不支持的语言或客户端
  • 单纯用grpc实现的服务端代码,只能用grpc客户端调用,(比如用 gRPC 官方提供的 Go、Python、Java 等 SDK 进行调用)现实开发中,不是所有客户端都支持 gRPC,比如:

    • 浏览器(Web 前端):大部分浏览器不支持 gRPC,虽然有 gRPC-Web 方案,但仍然有兼容性问题。
    • 传统 HTTP 客户端(如 curl、Postman、前端 AJAX 请求):这些工具一般都使用 HTTP/JSON,而不是 gRPC 的 Protobuf。
    • 外部系统(第三方 API 调用):很多外部服务只能通过 HTTP 调用,无法直接对接 gRPC。
  • gRPC 和 gRPC-Gateway 的核心区别

对比项直接使用 gRPC使用 gRPC-Gateway
协议gRPC(HTTP/2 + Protobuf)HTTP/JSON 转 gRPC
客户端支持仅限 gRPC 客户端(Go、Python、Java…)兼容 HTTP 客户端(curl、浏览器、前端)
调用方式需要 gRPC Stub(代码生成的客户端)直接使用 HTTP/JSON
网络环境需要支持 HTTP/2(可能受限于代理、网络设备)兼容 HTTP/1.1,适用于任何 HTTP 设备

什么时候不需要 gRPC-Gateway?

  • 如果你的服务只给 gRPC 客户端用(比如后端微服务之间的通信),那就没必要加 gRPC-Gateway,直接 gRPC 通信性能更好。
  • 如果你能确保所有客户端都支持 gRPC,例如你的团队只开发 gRPC 客户端,那就不需要 HTTP 网关。

总结

gRPC-Gateway 主要用于 让 gRPC 服务同时支持 HTTP/JSON 调用,方便 Web 前端、第三方系统或传统 REST 客户端对接。如果你的 gRPC 服务只在后端内部使用,不需要对外提供 REST API,那就可以不用 gRPC-Gateway。


gateway_29">安装插件 protoc-gen-grpc-gateway

go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest

检查版本

protoc-gen-grpc-gateway --version
插件的作用
  • 代码生成:根据 .proto 文件中的 HTTP 注解,生成反向代理代码 .pb.gw.go

  • 协议转换:将 HTTP 请求映射到对应的 gRPC 方法,并处理参数和响应转换。


echo.proto

syntax = "proto3";
package echo;
option go_package = "echo/proto";message User{int64 id = 1;string name = 2;int32 age = 3;string phone = 4;Addr addr = 5;
}message Addr{string province = 1;string city = 2;string county = 3;
}// 在 gRPC-Gateway 中,HTTP 方法(如 GET 和 POST)的映射是由 grpc-gateway 生成的代码和 .proto 文件中的选项配置决定的。
// 具体来说,grpc-gateway 使用 .proto 文件中的 google.api.http 选项来定义每个 gRPC 方法对应的 HTTP 方法和路径。
// 当 grpc-gateway 没有找到 google.api.http 选项时,它会根据 gRPC 方法的签名(即方法名和参数类型)生成默认的 HTTP 映射规则。
// GET 请求:如果 gRPC 方法只接收一个请求消息并且返回一个响应消息,并且请求消息中的字段可以作为 URL 路径参数或查询参数,则 grpc-gateway 会为该方法生成一个 GET 请求。
// POST 请求:对于所有其他情况,默认生成 POST 请求。// 这里则都默认生成post而不生成get
// 路径参数:适合唯一标识符,不宜包含多个字段或复杂结构。
// 查询参数:适合少量的过滤条件或附加信息,不宜包含复杂数据结构。
// User 消息:包含多个字段和嵌套结构,不适合直接映射为路径参数或查询参数,
// 因此 grpc-gateway 默认选择 POST 请求以确保完整性和灵活性。
service Echo{rpc Get(User) returns (User) {}rpc AddOrUpdate(User) returns (User) {}rpc Delete(User) returns (User) {}
}
1. 核心模块
1.1 main

功能:应用程序的入口点,负责启动 gRPC 服务器和 gRPC-Gateway。

1.1.1 main.go

功能:启动 gRPC 服务器和 gRPC-Gateway,并处理信号以优雅地关闭服务器。
关键点

  • 并发启动:使用两个 goroutine 分别启动 gRPC 服务器和 gRPC-Gateway。
  • gRPC 服务器:通过 run() 函数创建并启动 gRPC 服务器,监听在 :50051 端口。
  • gRPC-Gateway:通过 gateway.Run() 启动 HTTP 服务器,监听在 :8081 端口。
  • 信号处理:使用 signal.NotifyContext 监听中断信号(如 Ctrl+C),以便优雅地关闭服务器。
func main() {go func() {if err := run(); err != nil {log.Fatalln(err)}}()time.Sleep(time.Second)go func() {if err := gateway.Run(); err != nil {log.Fatalln(err)}}()ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)defer stop()<-ctx.Done()
}func run() error {lis, err := net.Listen("tcp", ":50051")if err != nil {log.Fatalln(err)}s := grpc.NewServer()userServiceServer := server.NewServer()proto.RegisterEchoServer(s, userServiceServer)return s.Serve(lis)
}
1.2 server

功能:实现了 gRPC 服务的具体逻辑。

1.2.1 server.go

功能:定义了 echoServer 结构体及其方法实现。
关键点

  • echoServer 结构体:嵌套了 UnimplementedEchoServer,确保未实现的方法不会导致 panic。通过值嵌入而不是指针嵌入,避免 nil 指针解引用问题。
  • NewServer 函数:创建并返回一个新的 EchoServer 实例。
  • 方法实现Get, AddOrUpdate, Delete 方法简单地打印传入的 User 对象并返回它。
type echoServer struct {proto.UnimplementedEchoServer
}func NewServer() proto.EchoServer {return &echoServer{}
}func (s *echoServer) Get(ctx context.Context, in *proto.User) (*proto.User, error) {fmt.Printf("#{in}\n")return in, nil
}func (s *echoServer) AddOrUpdate(ctx context.Context, in *proto.User) (*proto.User, error) {fmt.Printf("#{in}\n")return in, nil
}func (s *echoServer) Delete(ctx context.Context, in *proto.User) (*proto.User, error) {fmt.Printf("#{in}\n")return in, nil
}
1.3 proto

功能:定义了 gRPC 服务的消息格式和服务接口。

1.3.1 echo.proto

功能:定义了 UserAddr 消息以及 Echo 服务。
关键点

  • 消息定义UserAddr 消息定义了用户和地址的数据结构。
  • 服务定义Echo 服务定义了三个 RPC 方法:Get, AddOrUpdate, Delete,每个方法接收和返回 User 消息。
  • HTTP 映射规则:默认情况下,由于 User 消息包含多个字段和嵌套结构,不适合直接映射为路径参数或查询参数,因此 grpc-gateway 默认选择 POST 请求以确保完整性和灵活性。
syntax = "proto3";
package echo;
option go_package = "echo/proto";message User {int64 id = 1;string name = 2;int32 age = 3;string phone = 4;Addr addr = 5;
}message Addr {string province = 1;string city = 2;string county = 3;
}service Echo {rpc Get(User) returns (User) {}rpc AddOrUpdate(User) returns (User) {}rpc Delete(User) returns (User) {}
}
gateway__200">1.4 gateway

功能:配置并启动 gRPC-Gateway,将 HTTP 请求转换为 gRPC 调用。

gatewaygo_203">1.4.1 gateway.go

功能:配置并启动 gRPC-Gateway,将 HTTP 请求转发给 gRPC 服务器。
关键点

  • 多路复用器:使用 runtime.NewServeMux() 创建一个 HTTP 处理多路复用器。
  • 连接选项:使用 grpc.WithTransportCredentials(insecure.NewCredentials()) 表示使用不安全的连接(仅用于开发环境)。
  • 注册处理程序:使用 gw.RegisterEchoHandlerFromEndpoint 将 gRPC 方法映射为 HTTP 请求,连接到 gRPC 服务器(默认端口 :50051)。
  • HTTP 服务器:启动 HTTP 服务器,监听在 :8081 端口。
func Run() error {ctx := context.Background()ctx, cancel := context.WithCancel(ctx)defer cancel()mux := runtime.NewServeMux()opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}err := gw.RegisterEchoHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts)if err != nil {return err}return http.ListenAndServe(":8081", mux)
}

总结

  1. main:应用程序的入口点,负责启动 gRPC 服务器和 gRPC-Gateway,并处理信号以优雅地关闭服务器。
  2. server:实现了 gRPC 服务的具体逻辑,提供了 Get, AddOrUpdate, Delete 方法。
  3. proto:定义了 gRPC 服务的消息格式和服务接口,确保客户端和服务器之间的通信协议一致。
  4. gateway:配置并启动 gRPC-Gateway,将 HTTP 请求转换为 gRPC 调用,提供 RESTful API 接口。

https://github.com/0voice


http://www.ppmy.cn/server/165479.html

相关文章

服务器虚拟化实战:架构、技术与最佳实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 服务器虚拟化是现代 IT 基础设施的重要组成部分&#xff0c;通过虚拟化技术可以提高服务器资源利用率、降低硬件成本&am…

fastadmin加密生成token

安装git sudo yum install git 在项目中安装 firebase/php-jwt composer require firebase/php-jwt 注意&#xff1a;PHP7.4以上&#xff0c;安装fileinfo 如果还有问题在PHP配置里禁止&#xff1a; ;disable_functions passthru,exec,system,putenv,chroot,chgrp,chown,s…

大语言模型轻量化:知识蒸馏的范式迁移与工程实践

大语言模型轻量化&#xff1a;知识蒸馏的范式迁移与工程实践 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 摘要 在大型语言模型&#xff…

Java 中 LinkedList 的底层源码

在 Java 的集合框架中&#xff0c;LinkedList是一个独特且常用的成员。它基于双向链表实现&#xff0c;与数组结构的集合类如ArrayList有着显著差异。深入探究LinkedList的底层源码&#xff0c;有助于我们更好地理解其工作原理和性能特点&#xff0c;以便在实际开发中做出更合适…

GWO优化SVM回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;&#xff0c;是由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出的群智能优化算法。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想是对灰狼社会的结构与行为模式进行模仿。 …

基于机器学习鉴别中药材的方法

基于机器学习鉴别中药材的方法 摘要 由于不同红外光照射药材时会呈现不同的光谱特征,所以本文基于中药材的这一特点来判断其产地和种类。 针对问题一&#xff1a;要对附件一中所给数据对所给中药材进行分类&#xff0c;并就其特征和差异性进行研究。首先&#xff0c;我们读…

Python在线编辑器

from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…

当WebGIS遇到智慧文旅-以长沙市不绕路旅游攻略为例

目录 前言 一、旅游数据组织 1、旅游景点信息 2、路线时间推荐 二、WebGIS可视化实现 1、态势标绘实现 2、相关位置展示 三、成果展示 1、第一天旅游路线 2、第二天旅游路线 3、第三天旅游路线 4、交通、订票、住宿指南 四、总结 前言 随着信息技术的飞速发展&…