Apinto 网关: Go语言实现 HTTP 转 gRPC

news2025/1/1 10:56:12

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/bash

OUT_DIR=demo_service

set -e

mkdir -p $OUT_DIR

protoc --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 main

import (
 "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 main

import (
  "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.ServerOption
  if 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 Server
  s := grpc.NewServer(opts...)
  ser := NewServer()
  // 注册HelloService
  service.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 地址icon-default.png?t=N7T8https://github.com/eolinker/apinto

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/999790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你真的会设计测试用例吗?

前言 最近干的最多的事情就是设计测试用例、评审测试用例了,于是我不禁又想到了一个经典的问题:如何设计出优秀的测试用例? 可能有些童鞋看到这个问题会有些不以为然,这有什么好想的?干个测试谁还不会设计测试用例&a…

IDEA插件的在线离线安装

插件的使用 插件的设置 在 IntelliJ IDEA 的安装讲解中我们其实已经知道,IntelliJ IDEA 本身很多功能也都是通过插件的方式来实现的,只是 IntelliJ IDEA 本身就是它自己的插件平台最大的开发者而已,开发了很多优秀的插件。 官网插件库&…

pdf怎么转换成ppt?可以试试这三种方法

pdf怎么转换成ppt?PDF和PPT是我们工作、学习中最为常见的文档格式之一,特别是PPT,几乎成为了商务汇报和学术演示的标配。有时候,我们需要将PDF文档转换成PPT格式以方便编辑和演示。那么,PDF怎么转换成PPT呢&#xff1f…

信息化建设第三方验收测试报告要求

信息化建设是企业未来高质量发展的必由之路,也是企业法治的必要手段。 信息化建设指品牌利用现代信息技术来支撑品牌管理的手段和过程。随着计算机技术、网络技术和通信技术的发展和应用,企业信息化已成为品牌实现可持续化发展和提高市场竞争力的重要保…

【UE 材质】力场护盾和冲击波效果

目录 效果 步骤 一、制作力场护盾材质 二、制作冲击波材质效果 三、制作冲击波粒子效果 四、制作震动效果 效果 步骤 一、制作力场护盾材质 1. 首先新建一个第一人称角色游戏模板 2. 新建一个材质,用于作为力场护盾的材质,这里命名为“Mat_for…

释放数据的潜力:用梯度上升法解锁主成分分析(PCA)的神奇

文章目录 🍀引言🍀什么是主成分分析(PCA)?🍀传统PCA vs 梯度上升PCA🍀PCA的优化目标🍀代码实现🍀求解第一主成分🍀求解第二主成分 🍀在sklearn中封…

数据结构:线性表之-循环双向链表(万字详解)

目录 基本概念 1,什么是双向链表 2,与单向链表的区别 双向链表详解 功能展示: 1. 定义链表 2,创建双向链表 3,初始化链表 4,尾插 5,头插 6,尾删 判断链表是否被删空 尾删代码 7&a…

怎么用excel管理固定资产

在当今的数字时代,我们已经习惯了使用各种电子工具来提高我们的生产力。其中,Excel无疑是一个强大的工具,它不仅可以帮助我们处理数据,还可以用来进行复杂的计算和分析。然而,你可能不知道的是,Excel也可以…

【已解决】src/spt_python.h:14:20: 致命错误:Python.h:没有那个文件或目录

src/spt_python.h:14:20: 致命错误:Python.h:没有那个文件或目录 问题 其中重点的报错信息 src/spt_python.h:14:20: fatal error: Python.h: No such file or directory 思路 sudo yum install python-devel然后重新安装需要的依赖。 解决 成功。…

DBeaver使用

一、导出表结构 二、导出数据CSV 导出数据时DBeaver并没有导出表结构,所以表结构需要额外保存; 导入数据CSV 导入数据时会因外键、字段长度导致失败;

4. HBase必知必会理论基础篇

HBase必知必会理论基础篇 1.1 HBase简介1.2 HBase 数据模型1.3 HBase整体架构1.4 HBase 读写流程1.4.1 客户端读取流程1.4.2 客户端写入流程 1.5 HBase 客户端常用的方法1.5.1 scan查询1.5.2 get查询1.5.3 put查询1.5.4 delete 查询1.5.5 append 查询1.5.6 increment查询 1.6 H…

从零开始在树莓派上搭建WordPress博客网站并实现公网访问

文章目录 序幕概述1. 安装 PHP2. 安装MySQL数据库3. 安装 Wordpress4. 设置您的 WordPress 数据库设置 MySQL/MariaDB创建 WordPress 数据库 5. WordPress configuration6. 将WordPress站点发布到公网安装相对URL插件修改config.php配置 7. 支持好友链接样式8. 定制主题 序幕 …

今天给大家分享一个绘图的 RGB COLOR TABLE

如果大家觉得有用,就点个赞让更多的人看到吧~

微信支付上新的“分分捐”很暖心,一起吗?

今天在买东西付款后发现,在付款页面发现下方出现了一个公益项目,名为“为乡村儿童送鸡蛋 去捐 0.01元”的提示。去查了一下才知道该功能名叫“分分捐”。 微信分分捐是什么? 当微信支付金额超过 5 元且为非整数的订单(红包、转账…

如何激励员工?

如何激励员工?激励就是发现员工的需求,并满足它。 今天想给大家介绍下“马斯洛需求理论”,毕竟想要更好的激励下属创造价值,你首先需要了解他想要什么。对吧。 马斯洛需求理论是美国心理学家马斯洛在上世纪四十年代年提出的。他…

钢建筑模板和木建筑模板的优缺点?

当涉及到建筑模板材料时,钢模板和木模板都是常见的选择。它们各自具有一些优点和缺点,下面是钢模板和木模板的介绍: 钢模板的优点: 强度和稳定性:钢模板具有高强度和稳定性,能够承受较大的荷载和压力&…

人大女王金融硕士——不要成为群羊中盲从的羊,别人疯狂你要冷静

随着社会经济的迅速发展,经济全球化不断扩大,教育体系的完善。越来越多的人追求高学历,通过系统的学习来提升自己的知识储备,增长见识。这也导致每年考研成人逐年增加,录取率也逐年下降。很多选择考研的人,…

做游戏开发需要读研吗?

主观建议版 【是否要读研再工作——不建议】 游戏行业不太看重研究生上学就是为了更好的进入工作,许多人考研就是为了拿到工作的敲门砖。而你现在已经一脚迈入门里面了。对于游戏开发从业者而言,走企业路线的,工作中的经验远比课堂上的知识…

适合小企业的CRM客户管理系统

对于小企业而言,选择一款适合自己的CRM系统可以帮助他们更好地管理客户关系,提高销售业绩,加强市场营销和客户服务等方面的能力。但是,由于市面上CRM系统品牌众多,功能各异,价格不一,小企业适合…

vulnhub靶机Brainpan

主机发现 arp-scan -l 端口扫描 nmap --min-rate 10000 -p- 192.168.21.156 服务扫描 nmap -sV -sT -O -p9999,10000 192.168.21.156 这个地方感到了有点不对劲,python起来的一个web端口 漏洞扫描 nmap --scriptvuln -p9999,10000 192.168.21.156 意料之中&…