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

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。


安装插件 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) {}
}
1.4 gateway

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

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.rhkb.cn/news/10535.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

反射、枚举以及lambda表达式

一.反射 1.概念&#xff1a;Java的反射&#xff08;reflection&#xff09;机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff0c;既然能拿到那么&am…

【Proteus仿真】【51单片机】简易计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后&#xff0c;LCD1602显示数据&#xff0c;通过矩阵按键…

HarmonyOS简介:HarmonyOS核心技术理念

核心理念 一次开发、多端部署可分可合、自由流转统一生态、原生智能 一次开发、多端部署 可分可合 自由流转 自由流转可分为跨端迁移和多端协同两种情况 统一生态 支持业界主流跨平台开发框架&#xff0c;通过多层次的开放能力提供统一接入标准&#xff0c;实现三方框架快速…

(即插即用模块-特征处理部分) 十九、(NeurIPS 2023) Prompt Block 提示生成 / 交互模块

文章目录 1、Prompt Block2、代码实现 paper&#xff1a;PromptIR: Prompting for All-in-One Blind Image Restoration Code&#xff1a;https://github.com/va1shn9v/PromptIR 1、Prompt Block 在解决现有图像恢复模型时&#xff0c;现有研究存在一些局限性&#xff1a; 现有…

Day24-【13003】短文,数据结构与算法开篇,什么是数据元素?数据结构有哪些类型?什么是抽象类型?

文章目录 13003数据结构与算法全书框架考试题型的分值分布如何&#xff1f; 本次内容概述绪论第一节概览什么是数据、数据元素&#xff0c;数据项&#xff0c;数据项的值&#xff1f;什么是数据结构&#xff1f;分哪两种集合形式&#xff08;逻辑和存储&#xff09;&#xff1f…

使用 MSYS2 qemu 尝鲜Arm64架构国产Linux系统

近期&#xff0c;我的师弟咨询我关于Arm64架构的国产CPU国产OS开发工具链问题。他们公司因为接手了一个国企的单子&#xff0c;需要在这类环境下开发程序。说实在的我也没有用过这个平台&#xff0c;但是基于常识&#xff0c;推测只要基于C和Qt&#xff0c;应该问题不大。 1. …

unity学习21:Application类与文件存储的位置

目录 1 unity是一个跨平台的引擎 1.1 使用 Application类&#xff0c;去读写文件 1.2 路径特点 1.2.1 相对位置/相对路径&#xff1a; 1.2.2 固定位置/绝对路径&#xff1a; 1.3 测试方法&#xff0c;仍然挂一个C#脚本在gb上 2 游戏数据文件夹路径&#xff08;只读&…

【Redis】hash 类型的介绍和常用命令

1. 介绍 Redis 中存储的 key-value 本身就是哈希表的结构&#xff0c;存储的 value 也可以是一个哈希表的结构 这里每一个 key 对应的一个 哈希类型用 field-value 来表示 2. 常用命令 命令 介绍 时间复杂度 hset key field value 用于设置哈希表 key 中字段 field 的值为…

基于51单片机和WS2812B彩色灯带的流水灯

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码四、主函数总结 系列文章目录 前言 用彩色灯带按自己想法DIY一条流水灯&#xff0c;谁不喜欢呢&#xff1f; 所用单片机&#xff1a;STC15W204S &#xff08;也可以用其他1T单片机&#xff0c;例如&#xff0c;S…

力扣017_最小覆盖字串题解----C++

题目描述 我们可以用滑动窗口的思想解决这个问题。在滑动窗口类型的问题中都会有两个指针&#xff0c;一个用于「延伸」现有窗口的 r 指针&#xff0c;和一个用于「收缩」窗口的 l 指针。在任意时刻&#xff0c;只有一个指针运动&#xff0c;而另一个保持静止。我们在 s 上滑动…

如何从客观角度批判性阅读分析博客

此文仅以个人博客为例&#xff0c;大量阅读朋友反馈给我的交流让我得知他们所理解我的博客所表达的意思并非我所想表达的&#xff0c;差异或大或小&#xff0c;因人而异。 观点与事实 只有从客观角度反复批判性阅读和分析&#xff0c;才能逐渐清晰观点和事实。 观点不等于事实…

深入理解MySQL 的 索引

索引是一种用来快速检索数据的一种结构, 索引使用的好不好关系到对应的数据库性能方面, 这篇文章我们就来详细的介绍一下数据库的索引。 1. 页面的大小: B 树索引是一种 Key-Value 结构&#xff0c;通过 Key 可以快速查找到对应的 Value。B 树索引由根页面&#xff08;Root&am…

Spring Boot项目如何使用MyBatis实现分页查询及其相关原理

写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油&#xff0c;冲鸭&#x…

LabVIEW温度修正部件测试系统

LabVIEW温度修正部件测试系统 这个基于LabVIEW的温度修正部件测试系统旨在解决飞行器温度测量及修正电路的测试需求。该系统的意义在于提供一个可靠的测试平台&#xff0c;用于评估温度修正部件在实际飞行器环境中的性能表现&#xff0c;从而确保飞行器的安全性和可靠性。 系统…

动态规划每日一练(四)

一、day1——最长数对链 题目链接&#xff1a; 646. 最长数对链 - 力扣&#xff08;LeetCode&#xff09;646. 最长数对链 - 给你一个由 n 个数对组成的数对数组 pairs &#xff0c;其中 pairs[i] [lefti, righti] 且 lefti < righti 。现在&#xff0c;我们定义一种 跟随…

对比category_encoders库和sklearn库中的OrdinalEncoder

OrdinalEncoder 是用来对数据中的分类特征进行编码、转换为整数标签的函数。 category_encoders库 from category_encoders import OrdinalEncoder 安装&#xff1a;pip install category_encoders --trusted-host pypi.tuna.tsinghua.edu.cn&#xff08;记得关闭代理&#x…

【PLL】杂散生成和调制

时钟生成 --》 数字系统 --》峰值抖动频率生成 --》无线系统 --》 频谱纯度、 周期信号的相位不确定性 随机抖动&#xff08;random jitter, RJ&#xff09;确定性抖动&#xff08;deterministic jitter,DJ&#xff09; 时域频域随机抖动积分相位噪声确定性抖动边带 杂散生成和…

理解神经网络:Brain.js 背后的核心思想

温馨提示 这篇文章篇幅较长,主要是为后续内容做铺垫和说明。如果你觉得文字太多,可以: 先收藏,等后面文章遇到不懂的地方再回来查阅。直接跳读,重点关注加粗或高亮的部分。放心,这种“文字轰炸”不会常有的,哈哈~ 感谢你的耐心阅读!😊 欢迎来到 brain.js 的学习之旅!…

Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成

Ubuntu下的DoxygenVScode实现C/C接口文档自动生成 Chapter1 Ubuntu下的DoxygenVScode实现C/C接口文档自动生成1、 Doxygen简介1. 安装Doxygen1&#xff09;方法一&#xff1a;2&#xff09;方法二&#xff1a;2. doxygen注释自动生成插件3. doxygen注释基本语法4. doxygen的生成…

Java内存模型 volatile 线程安全

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 认识JMM认识volatile关键字&#xff1a;可见性和顺序性理解线程安全的概念 目录 Java内存模型可见性例子和volatilevolatile如何保证可见性原子性与单例模式…