Apinto 网关: Go语言实现 HTTP 转 gRPC
gRPC
是由 Google 开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于 HTTP/2
协议标准而设计,同时支持大多数流行的编程语言。
gRPC
基于 HTTP/2
协议传输, HTTP/2
相比 HTTP1.x
有以下优势:
-
采用二进制格式传输协议,支持多路复用。
-
支持通过同一个连接发送多个并发的请求,支持流式传输。
-
服务器可以对客户端的一个请求发送多个响应。
-
对消息头进行压缩传输,节省消息头占用的网络流量。gRPC使用Protocol Buffers 作为序列化协议。
但同时,gRPC 也有自身的局限性:
浏览器支持有限
当下,不可能直接从浏览器调用 gRPC 服务。gRPC 大量使用HTTP/2 功能,没有浏览器提供支持 gRPC 客户机的 Web 请求所需的控制级别。例如,浏览器不允许调用者要求使用的 HTTP/2,或者提供对底层 HTTP/2 框架的访问。
不是人类可读的
HTTP API 请求以文本形式发送,可以由人读取和创建。默认情况下,gRPC 消息使用 protobuf 编码。虽然 protobuf 的发送和接收效率很高,但它的二进制格式是不可读的
protobuf 需要在 *.proto 文件中指定的消息接口描述才能正确反序列化。需要额外的工具来分析线路上的Protobuf 有效负载,并手工编写请求。
若需要将内部 gRPC 作为接口开放给外部用户或浏览器调用,则需要有第三方代理解决 HTTP 协议转换成 gRPC 协议的问题。
为此,我们在 Apinto 多协议支持的基础上,发布了 HTTP 转 gRPC 插件
(📌eolinker.com:apinto:http_to_grpc)
Apinto 通过插件的方式支持 HTTP协议转换成gRPC协议请求,在http_to_grpc 插件中完成了 HTTP 客户端 与 gRPC Server 通讯时的协议转换及数据编解码工作,其通讯的过程如下:
接下来通过一个完整的示例向大家演示怎样构建一个 HTTP 请求,并通过 Apinto 进行 HTTP协议 转换成 gRPC 协议请求。在以下的示例中,我们会将 Go 作为 gRPC Server 服务端处理程序,使用 Eolink 作为 HTTP 客户端,发起 HTTP 请求。
以下示例可以在 Apinto 仓库中获取。
配置 Protocol Buffer
1. 创建示例文件 msg.proto
syntax = "proto3";option go_package = "github.com/eolinker/apinto/example/grpc/demo_service";package Service;// HelloRequest 请求
message HelloRequest {string name = 1;
}// HelloResponse 响应,成功消息时,msg为json数据
message HelloResponse {string msg = 1;string err = 2;
}
该文件定义了示例消息类型,我们在这里定义了一个 HelloRequest
和 HelloResponse
的 message
。
2. 创建示例文件 service.proto
syntax = "proto3";option go_package = "github.com/eolinker/apinto/example/grpc/demo_service";
import "msg.proto";package Service;service Hello {rpc Hello(HelloRequest) returns (HelloResponse){};rpc StreamRequest(stream HelloRequest) returns (HelloResponse){};rpc StreamResponse(HelloRequest) returns (stream HelloResponse) {};rpc AllStream(stream HelloRequest)returns (stream HelloResponse) {};
}
该文件定义了服务 Hello,引入了第一步创建的文件 msg.proto
,定义了四个方法,包含了一元 RPC、客户端流、服务端流、双向流四种 gRPC 通信模式。
配置服务端程序
1. 创建自动生成 gRPC 文件脚本(grpc.sh)
#!/bin/bashOUT_DIR=demo_serviceset -emkdir -p $OUT_DIRprotoc --grpc-gateway_opt logtostderr=true \--grpc-gateway_opt paths=source_relative \--grpc-gateway_opt generate_unbound_methods=true \--grpc-gateway_out=$OUT_DIR \--go_out=$OUT_DIR --go_opt=paths=source_relative \--go-grpc_out=$OUT_DIR --go-grpc_opt=paths=source_relative *.proto
该脚本将生成 gRPC 客户端/服务端调用相关代码,并将其存储到 demo_service
目录下。
执行 grpc.sh
,生成服务端 Go 原始消息和服务/客户端存根。
./grpc.sh
2. 实现服务端处理程序接口
package mainimport ("fmt"service "github.com/eolinker/apinto/example/grpc/demo_service""google.golang.org/grpc/metadata""google.golang.org/grpc""golang.org/x/net/context"
)var _ service.HelloServer = (*Server)(nil)type Server struct {service.UnimplementedHelloServer
}func NewServer() *Server {return &Server{}
}func (s *Server) Hello(ctx context.Context, request *service.HelloRequest) (*service.HelloResponse, error) {trailingMD, ok := metadata.FromIncomingContext(ctx)if ok {grpc.SetTrailer(ctx, trailingMD)}return &service.HelloResponse{Msg: fmt.Sprintf("hello,%s", request.Name),}, nil
}
上述代码重新定义了Hello方法:
-
将
HelloRequest 中
的name
字段通过HelloResponse
的msg
字段封装成hello,%s
的结果返回 -
将请求的 Header 作为 gRPC 响应的
Trailer
头部返回
3. 定义 gRPC 服务端入口文件
package mainimport ("fmt""net""google.golang.org/grpc/reflection"service "github.com/eolinker/apinto/example/grpc/demo_service""google.golang.org/grpc/credentials""google.golang.org/grpc""google.golang.org/grpc/grpclog"
)func main() {Parse()err := listen()if err != nil {fmt.Println(err)return}
}func listen() error {address := fmt.Sprintf("%s:%d", BindIP, ListenPort)l, err := net.Listen("tcp", address)if err != nil {grpclog.Fatalf("Failed to listen: %v", err)}var opts []grpc.ServerOptionif TlsKey != "" && TlsPem != "" {creds, err := credentials.NewServerTLSFromFile(TlsPem, TlsKey)if err != nil {grpclog.Fatalf("Failed to generate credentials %v", err)}opts = append(opts, grpc.Creds(creds))}// 实例化grpc Servers := grpc.NewServer(opts...)ser := NewServer()// 注册HelloServiceservice.RegisterHelloServer(s, ser)// 开启grpc反射reflection.Register(s)fmt.Println("Listen on " + address)return s.Serve(l)
}
在此处,gRPC 服务端开启了 gRPC 反射,配置 Apinto 网关时,可选择绑定具体的 Protobuf 资源,也可以直接启用反射,动态获取 gRPC 服务端的 Protobuf 信息。
4. 编译 gRPC 服务器程序
cd server && go build -o grpcServer
5. 启动gRPC服务
./grpcServer
配置 Apinto HTTP 转 gRPC 插件
Apinto 提供了可视化界面工具 Apinto-Dashboard,降低初学者的使用成本,以下操作均在 Apinto-Dashboard 中进行配置。
为了让使用者快速上手,我们此处演示的教程使用 Apinto 可视化项目 Apinto-Dashboard 进行演示。项目仓库地址请按需点击:
-
Apinto 项目地址:https://github.com/eolinker/apinto
-
Apinto-Dashboard 项目地址:https://github.com/eolinker/apinto-dashboard
1.新增节点插件
在左侧导航栏中,点击 基础设施
> 节点插件
,进入节点插件列表。点击 添加插件
点击 拓展ID
单选框,在下拉选项后选中 http_to_grpc
插件,填写插件名称信息,点击 保存
2. 发布节点插件
在左侧导航栏中,点击 基础设施
> 集群
,进入集群列表。选中需要发布节点插件的集群,点击进入
点击 节点插件
选项卡,选中插件后方的扳手按钮
在弹出框中,将状态改成 启用
,点击 提交
。
在节点插件列表,点击 发布
在弹出框中点击 提交
注意:该步骤非必需,仅在节点插件有改动时(新增、删除、修改节点插件顺序等),才需要重新在集群中发布上线。
3. 新增 API 操作模版,绑定 http_to_grpc 插件
在左侧导航栏中,点击 公共配置
> API 操作模版
,进入操作模版列表后,点击 新建模版
。
点击 添加插件
在弹出框中选中 http_to_grpc
,填写插件配置
配置参数说明:
-
当服务名称不填时,则默认使用
HTTP
请求路径的第一个/和第二个/之间的值作为服务名 -
当方法名称不填时,则默认使用
HTTP
请求路径的第二个/和第三个/之间的值作为服务名 -
即:若
HTTP
请求路径上/Service.Hello/Hello
,则此时服务名称为Service.Hello
,方法名称为Hello
示例配置
由于 gRPC
服务端示例中,我们开启了 gRPC
反射,因此,在配置插件时,reflect
设置为 true
{"authority": "","format": "json","headers": {},"method": "","reflect": true,"service": ""}
填写完成后点击 保存
。
点击保存成功的插件模版,进入到 上线管理
页面,点击 上线
按钮
4. 新增上游服务,填写 gRPC 服务地址
在左侧导航栏中,点击 上游
,进入上游列表。点击新建 上游服务
填写上游服务信息,目标节点支持多个地址,此处填写上面启动的 gRPC 服务地址。
保存后,点击 上线管理
选中需要上线的集群,点击 上线
5. 新增 API,绑定 API 操作模版,绑定 gRPC 上游服务
在左侧导航栏中,点击 API
,进入API列表后,点击 新建 API
,选中 HTTP
。
填写接口的基本信息,绑定上游,绑定插件模版。
保存后,点击 API 后方的 上线管理
按钮,将 API 上线到对应的集群即可。
求 Service.Hello 服务的 Hello 方法
在上文中,我们定义了 Hello
方法的功能:
-
将
HelloRequest
中的name
字段通过HelloResponse
的msg
字段封装成hello,%s
的结果返回。 -
将请求的
Header
作为gRPC
响应的Trailer
头部返回。
调用结果如下:
目前 Apinto 及其周边项目已经开源,我们希望通过 Apinto 强大的插件拓展能力,用户可像乐高积木一样根据需要自行拓展 Apinto 的插件,以满足不同的业务市场需求。
Apinto 目前属于萌芽阶段,我们希望集合广大开源爱好者的力量,与大家一起讨论方案,接受大家的批评指正,一起将产品打磨完善,做下一个端与端间的Traffic Middleware。这是一个开放和积极的项目,我们诚挚地邀请您一起参与到我们的项目开源工作中。每一个贡献都是有意义的,包括但不限于:
·查找 bugs,取得性能上的提升
·帮助完善文档,提供用户操作体验
·提交你们的 issue,让我们知道您的奇思妙想
·参与自定义插件的开发,丰富 Apinto 的能力
...
欢迎各位开源爱好者参与到 Apinto 项目中,和我们一起为开源事业贡献自己的力量!
Apinto GitHub 地址https://github.com/eolinker/apinto
相关文章:
Apinto 网关: Go语言实现 HTTP 转 gRPC
gRPC 是由 Google 开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于 HTTP/2 协议标准而设计,同时支持大多数流行的编程语言。 gRPC 基于 HTTP/2 协议传输, HTTP/2 相比 HTTP1.x有以下优势: 采用二进制格式传输协议ÿ…...
【管理运筹学】第 7 章 | 图与网络分析(4,最大流问题)
系列文章目录 【管理运筹学】第 7 章 | 图与网络分析(1,图论背景以及基本概念、术语、矩阵表示) 【管理运筹学】第 7 章 | 图与网络分析(2,最小支撑树问题) 【管理运筹学】第 7 章 | 图与网络分析…...
linux学习总结
shell 1.在文本环境下,shell作为命令解释器,建立了用户和操作系统之间的接口。当用户键入一个命令时,shell将对该命令进行解释,并调用相应的程序。2.Linux下有多个shell,最常用的3个shell: bash tcsh zsh3.shell …...
【API 管理】什么是 API 管理,为什么它很重要?
当今复杂的数字生态系统由许多相互关联的部分组成。API 作为看门人和连接器在其中发挥着关键作用——提供了许多最终用户甚至没有注意到的自动化机会和效率。 企业密切关注 API。它们对于应用程序、数据和各种客户交互的功能至关重要。 这使得 API 管理成为几乎每个部门的组织…...
基于人体呼出气体的电子鼻系统的设计与实现
基于人体呼出气体的电子鼻系统的设计与实现 摘要 电子鼻技术是通过模式识别技术对传感器采集的人体呼出气体进行分类训练的方法。本文研究实现的电子鼻系统包括下面几个部分:首先搭建以Arduino为控制核心的气路采集装置,包括MOS传感器和双阀储气袋构建的传感器阵列和…...
OPC发展历程
目录 1 opc 发展历程 1.1 OPC产生的背景 1.2 经典OPC 1.3 OPC UA 2 OPC DA简介 2.1 OPC Server/Client 2.2 OPC Server 2.3 OPC数据更新 2.4 读取数据方式 3 OPC XML简介 3.1 诞生由来 3.2 功能服务 1 opc 发展历程 OPC是英文“OLE for Process Control”的缩写&am…...
第69步 时间序列建模实战:ARIMA建模(R)
基于WIN10的64位系统演示 一、写在前面 这一期,我们使用R进行SARIMA模型的构建。 同样,这里使用这个数据: 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Re…...
【多线程】CountDownLatch
CountDownLatch 同时等待 N 个任务执行结束. 好像跑步比赛,10个选手进行比赛, 所有选手都通过终点,才能公布成绩。 代码示例: 构造 CountDownLatch 实例, 初始化 10 表示有 10 个任务需要完成.每个任务执行完毕, 都调用 latch.countDown() . 在 Count…...
使用 docker buildx 构建跨平台镜像 (QEMU/buildx/build)
目录 1. 使用 buildx 构建跨平台镜像1.1. 简介1.2. 安装1.3. 构建跨平台镜像1.4. 跨平台镜像构建策略1.4.1. 在内核中使用 QEMU 仿真支持1.4.2. 使用相同的构建器实例在多个本机节点上构建。1.4.3. 使用 Dockerfile 中的多阶段构建, 交叉编译到不同的平台架构中。 1.5. 创建 bu…...
算法|Day49 动态规划17
LeetCode 647- 回文子串 题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 题目描述:给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子…...
Linux nohup命令
nohup命令 no hang up 在后台启动命令,终端关闭 程序依然可以执行 1.在后台启动命令 命令 nohup COMMAND2.使用nohup命令在后台启动COMMAND, 并将所有标准输出都重定向到fileA nohup COMMAND > /path/fileA 2>&1 &# COMMAND 需要运行的命令 # &g…...
SQL Server 跨库/服务器查询
这里写目录标题 1 SQL Server 跨库/服务器查询1.1 跨库查询1.2 跨服务器查询1.2.1 创建链接服务器1.2.2 跨库查询 1.3 拓展:SQL Server 中所有权和用户与架构的分离 1 SQL Server 跨库/服务器查询 1.1 跨库查询 在同一服务器下的跨库查询较为简单,示例…...
word转PDF文件变小,图片模糊
word论文29M,文件——另存为——只有1.5M左右,图片压缩严重,图片看不清。 word中很多大图,5M一张的图,所以word很大。 找了很多方法,转换后都在2M左右,勉强可以。 直到找到了这个,…...
被删除并且被回收站清空的文件如何找回
文件的意外删除和回收站清空是许多用户面临的普遍问题。这种情况下,很多人会感到无助和焦虑,担心自己的重要文件永远丢失。然而,幸运的是,依然存在一些有效的方法能够帮助我们找回被删除并且被回收站清空的文件。 ▌被删除文件在…...
每日两题 131分割回文串 784字母大小写全排列(子集模版)
131 131 题目 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1: 输入:s “aab” 输出:[[“a”,“a”,“b”]…...
Java面试八股文宝典:初识数据结构-数组的应用扩展之HashMap
前言 除了基本的数组,还有其他高级的数据结构,用于更复杂的数据存储和检索需求。其中,HashMap 是 Java 集合框架中的一部分,用于存储键值对(key-value pairs)。HashMap 允许我们通过键来快速查找和检索值&…...
ES6 特性
一、ES6 1.1 ES6 概念 1.1.1 什么是 ES ES 全称 EcmaScript 是脚本语言的规范JavaScript 是 EcmaScript 的一种实现ES 新特性就是指 JavaScript 的新特性 1.1.2 为什么要使用 ES 语法简单,功能丰富框架开发应用前端开发职位要求 1.1.3 为什么要学习 ES6 ES6 …...
重拾html5
新增的position: sticky; 基于用户的滚动位置来定位,粘性定位的元素是依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。ie15以上的低版本不支持,Safari 需要使用 -webkit- prefix; vertical-align: midd…...
递归学习——记忆化搜索
目录 编辑 一,概念和效果 二,题目 1.斐波那契数 1.题目 2.题目接口 3.解题思路 2.不同的路径 1.题目 2.题目接口 3.解题思路 3.最长增长子序列 1.题目 2.题目接口 3.解题思路 4.猜数字游戏II 1.题目 2.题目接口 3.解题思路 总结&a…...
ChatGPT帮助一名儿童确诊病因,之前17位医生无法确诊
9月13日,Today消息,一位名叫Alex的4岁儿童得了一种浑身疼痛的怪病,每天需要服用Motrin(美林)才能止痛。3年的时间,看了17名医生无法确诊病因。(新闻地址:https://www.today.com/heal…...
Laf 云开发平台及其实现原理
Laf 产品介绍 自我介绍 大家好,我是来自 Laf 团队的王子俊,很高兴今天能在这里给大家分享我们 Laf 云开发平台及其实现原理。本来想说一点什么天气之类的话作为开头,但主持人都说完啦,我就不多说了,还是直接开始今天…...
浅谈STL|STL函数对象篇
一.函数对象概念 概念: 重载函数调用操作符的类,其对象常称为函数对象 函数对象使用重载的()时,行为类似函数调用,也叫仿函数 本质: 函数对象(仿函数)是一个类,不是一个函数 特点 函数对象在使用时,可以像普通函数那…...
自建私人图床方案:使用Cpolar+树洞外链轻松部署超轻量级图床,实现高效图片存储
文章目录 1.前言2. 树洞外链网站搭建2.1. 树洞外链下载和安装2.2 树洞外链网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道(云端设置)3.3 Cpolar稳定隧道(本地设置) 4.公网访问测试5.结语…...
从零基础到精通Flutter开发:一步步打造跨平台应用
💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 导言 Flutter是一种流行…...
SpringBoot整合WebSocket【代码】
系列文章目录 一、SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】 二、SpringBoot连接Redis与Redisson【代码】 三、SpringBoot整合WebSocket【代码】 四、SpringBoot整合ElasticEearch【代码示例】 文章目录 系列文章目录代码下载地址一、效果演示二、引入依赖…...
微服务 第一章 Java线程池技术应用
系列文章目录 第一章 Java线程池技术应用 文章目录 系列文章目录[TOC](文章目录) 前言1、Java创建线程方式回顾1.1、继承Thread类(只运行一次)1.1.1、改造成主线程常驻,每秒开启新线程运行1.1.2、匿名内部类1.1.3、缺点1.1.4、扩展知识:Java内部类1.1.4…...
行业追踪,2023-09-14
自动复盘 2023-09-14 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
传输层协议--UDP
引入 传输层负责数据能够从发送端传输到接收端。 端口号(Port) 端口号标识了一个主机上进行通信的一个进程。 两个问题: 1. 一个进程可以绑定多个端口号吗?--可以 2.一个端口号可以绑定多个进程吗?--不可以 我们…...
微信会员卡开发流程
功能需求: 通过微信第三方平台创建的模板小程序,想要实现用户在小程序支付一定金额后领取会员卡,领取会员卡后可给用户下发一定数量的优惠券,并且实现用户在小程序消费享受商品折扣。 开发流程: 一、了解微信的3个平…...
《算法竞赛·快冲300题》每日一题:“点灯游戏”
《算法竞赛快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 点…...
烟台电商网站建设/培训课程表
常用于长按录音等场景! 属性 属性简介默认step步长100smstart触发时长10*step事件 事件简介ngPress长按开始ngRelease长按释放ngPressing长按中,返回长按时长installyarn add iwe7-on-press 复制代码implements: [Iwe7OnPressModule] 复制代码<button (ngPress)&…...
深入浅出wordpress pdf/站长工具日本
Element-ui 在你的项目所在的文件中,上方面包屑目录上输入cmd,然后回车,打开小黑框 在小黑框中输入 npm install element-ui -s命令,(cnpm是比较快),回车 到这步,说明element-ui…...
可信的大连网站建设/地推接单平台
centos7全面升级了引导程序和系统管理程序,使用grub2替代了grub来引导操作系统,使用systemd替换了init管理系统程序,systemd的升级比较激进,从架构上变更init管理程序。微服务docker却希望使用docker domean管理微服务中的进程&am…...
电商app开发多少钱/广州关于进一步优化疫情防控措施
>>> CentOS 7.0默认使用的是firewall作为防火墙,使用iptables必须重新设置一下1、直接关闭防火墙systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service #禁止firewall开机启动 2、设置 iptables serviceyum…...
怎么用vs做网站开发/免费的推广平台
本篇文章帮大家学习ant删除任务,包含了Ant删除任务使用方法、操作技巧、实例演示和注意事项,有一定的学习价值,大家可以用来参考。此任务用于删除单个文件,目录或子目录。 还可以通过指定文件集来删除文件集。 默认情况下它不会删…...
打开一张图片后点击跳转到网站怎么做的/seo优化报价
这段时间学习boost库的使用,撰文一方面留以备用,另一方面就是shared精神。 format主要是用来格式化std::string字符串以及配合std::cout代替C语言printf() 使用format需要#include"boost/format.hpp" boost::format的格式一般为: b…...