基于rust的,gRPC动态代理,无需proto文件自动http转gRPC

news2024/10/7 16:15:54

目录

  • 前言
  • grpc
  • 实践
    • github地址
    • 第一步
    • 第二步
    • 第三步
    • 第四步
    • 测试
  • 结构和原理
  • 尾语

前言

 沟通服务间接口内容(尤其是前后端接口),是非常让人头疼的事。极其容易扯皮。接口文档写起来也很痛苦,每个字段的改动都需要及时更新,否则就会出问题。服务端通信如果用rpc通信的话,一般会有proto或者thrift文件。这个文件很长时间里被我们当成接口文档用,用着用着发现,真tm好用。既减少了扯皮,还不用写接口文档。那可不可以用grpc和前端通信那,一开始我们的做法是用grpc-gateway。把grpc的接口映射成http接口。但这种方式需要编译gateway的pb文件,对服务也是有侵入的。后来随着我在公司的时间越来越长,接手的服务越来越多(经常需要发版的项目就有十几个),这种方式维护起来十分糟心,后一直想寻求一种一劳永逸的解决方法?
 本人之前很长一段时间从事saas,paas的开发。对于一些服务而言,既要提供grpc访问的能力,也要对外提供http访问的能力(做saas就是这么卑微)。并且这种需求通常不是一开始就提出来的,而是对一个已经稳定运行的庞大的服务做改造。而这会导致爬屎山,鉴权不一致等一系列问题。那有没有一种无侵入的协议转换能力?
  grpc是基于http2协议,而http2是长连接。这对k8s部署的服务非常不友好。在这我猜肯定有很多小伙伴说可以用linked,istio等基于Service Mesh的解决方案。一是这些技术是近两年才稳定下来的,以前问题很多,根本不敢用,当然现在istio已经流行起来了,可以很完美的做到grpc的负载均衡和很优秀的流量管理。但依然存在不满足实际需求的情况,比如对grpc流量做精细过滤,细到每个请求的精准控制。这种二次开发的需求是很难在istio上完成。尤其是对一些小公司而言。
基于很多原因的考虑,最终诞生了搞一个grpc动态代理的想法,并初步实现。

grpc

  在云原生,容器化,微服务的大背景下。rpc也彻底奠定了服务间通信协议的霸主地位。众多rpc框架中grpc和thrift是最流行最受欢迎的rpc框架。在实际开发中,我两个框架都有深入的使用过。相较而言,我更喜欢grpc的风格。背靠google大树(已经是CNCF孵化项目),多语言都支持,基于protobuf极致编码和急速传输,等等优点就不一一详述。有兴趣的可以看grpc官网,上面吹的比我吹的好。

实践

github地址

https://github.com/woshihaoren4/grpc-proxy

第一步

先将代码clone下来到本地,我这里用的mac系统
因为编译需要cargo环境,需要先安装rust,参考教程:https://www.rust-lang.org/zh-CN/ 上面有很详细的中文教程。
我安装的是:rustc 1.66.0 (69f9c33d7 2022-12-12) 版本

第二步

先进入项目根目录,运行起测试例子

./example/helloworld server

没有权限的话,需要先加权限,然后再运行
chmod +x ./example/helloworld

这个例子使用golang编写的简单的grpc服务,实现上没有啥特殊的部分,值得注意的是需要给grpc服务加上反射

//grpc的HelloWorld方法实现,就是在字符串上加一个 world
func (s *Service) HelloWorld(ctx context.Context, req *proto.HelloWorldRequest) (*proto.HelloWorldResponse, error) {
        return &proto.HelloWorldResponse{Response: req.Request + " world"}, nil
}
//这里相当于main函数
func server(ctx *wdevent.Context) error {
        ls, _ := net.Listen("tcp", ":8888")
        gs := grpc.NewServer()
        proto.RegisterHelloWorldServiceServer(gs, new(Service))
        reflection.Register(gs)
        logrus.Infoln("grpc server start workd ....")
        gs.Serve(ls)
        return nil
}

再看一下pb文件,需要注意的是在option里指明 需要映射的http的路径和方法

syntax = "proto3";

package proto;
option go_package = "./proto";
import "google/api/annotations.proto";

// HelloWorld Service
service HelloWorldService {
  rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse){
    option (google.api.http) = {
      post: "/api/v2/hello"
      body: "*"
    };
  };
}
message HelloWorldRequest {
  string request = 1;
}
message HelloWorldResponse {
  string response = 1;
}

第三步

修改配置文件如下,路径:./src/config/config.toml。当前项目中的配置文件已经写好了这些内容,不需要再配置什么了。当然不放心也可以查看一下。

[[proxy_sink]]
name = "hello"
addr = "127.0.0.1:8888"
  • 需要在addr中指明上面服务的地址和端口。

第四步

另起终端,编译并运行项目

cargo run -- run

国内没有科学上网的话会有些慢,主要是下载包比较慢,可以用清华源或者其他的,教程参考:https://www.w3cschool.cn/cargo_guide/cargo_guide-uxdg3l62.html
服务启动后会打印如下日志,说明服务启动成功
在这里插入图片描述

测试

发起一个http请求

curl --location --request POST 'http://127.0.0.1:6789/api/v2/hello' \
--header 'Content-Type: application/json' \
--data-raw '{
    "request": "hello"
}'

可以看到返回内容:{"response": "hello world"}
并且在代理服务上产生访问日志:
在这里插入图片描述
到这里一个简单的演示就成功了

结构和原理

主要是根据grpc的反射的描述,生成http路由,并动态完成json和proto的映射。
更进一步的原理和结构,未完待续~

尾语

当前版本还只是一个比较初级的版本,功能还很初级。
还有很多功能需要完善,架构也可能会有大的变动,所有上一节并没有详细描述。
作者预计但不承诺会继续完成下面的内容。

  • restful支持:这个功能是P0级,在我go版本的grpc动态代理服务中经常被用到,在可预计的规划里一定会实现。
  • 事件系统:该功能是为了方便二次开发,很有必要。也有可能用中间件模式,类似traefik
  • 负载均衡/sidecar:负载均衡是为了用在服务网关上,sidecar是用在pod里,二者会选一个实现,我倾向于前者,和我之前写的rust-ingress联动上。这里自荐一波rust-ingress项目:https://gitee.com/yutiandou/rust-ingress
  • 性能优化,这个会一直持续做下去,欢迎有性能极致追求的小伙伴能够共同前进
  • 实时反射:目前是通过配置文件,在启动的时候加载服务源。好的(懒人)方案是proto文件变化后能够实时监控到,下一步会完成这个功能。

欢迎有兴趣的小伙伴提出建议,并热烈欢迎大家参与进来。

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

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

相关文章

链表(初学)

n个结点由指针链组成一个链表。链表的结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。链表的每一个结点有两个区域,分别是数据域和指针域。数据域存储的是当前结点的数据值,而指针域存储的是下一个结点的存储地址。…

URL的正则表达式(js代码)

在WWW上,每一信息资源都有统一的且在网上的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位器),它是WWW的统一资源定位标志,就是指网络地址。语法URL由三部分组成:资源类型、存放资源…

2022财年业绩增长乏力渐显,AR电商是Snap下一个突破口吗?

北京时间2月1日,Snap公布了2022财年第四季度和全年财务业绩,财报发布后,Snap盘后股价大幅下跌,最终收跌14.97%。 这并非Snap首次出现公布业绩后股价暴跌的情况,不可否认的是市场的敏锐度十分迅捷。那么,20…

数据结构——栈

一、栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表。 允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表,简称LIFO结构。 栈的插入操作,叫作进栈,也称压栈…

不固定版式文档的OCR模型自主开发流程及技术应用实例

随着各行业数字化、智能化建设的脚步加快,OCR得到了普及应用。当前,OCR技术主要应用于标准证件、票据识别,通过自动检测并识别、提取文字,减少人工录入信息的工作量,提升业务效率。目前,企业对OCR的识别精度…

java 分布式缓存 redis持久化 redis主从 Redis哨兵 Redis分片集群

-- 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题: 数据丢失问题 :Redis是内存存储,服务重启可能会丢失数据 并发能力问题 :单节点Redis并发能力虽然不错,但也无法满足如618这样的高并发场景 故障…

flink学习35:flinkSQL查询mysql

总览: import org.apache.flink.streaming.api.scala._ import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment import org.apache.flink.table.api.EnvironmentSettings import org.apache.flink.table.api.bridge.scala.{StreamTableEnvi…

day 23 贪心

P4447 [AHOI2018初中组]分组要求分成的每个小组的队员实力值连续,同时,一个队不需要两个实力相同的选手满足所有人都恰好分到一个小组,使得人数最少的组人数最多,输出人数最少的组人数的最大值。注意:实力值可能是负数…

【软件测试】 MySQL数据库总结,表的一系列操作,你看的都用得到......

目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 MySQL中的数据类型 …

ROS小车研究笔记2/2/2023 激光雷达建图

1 启动激光雷达建图节点 roslaunch turn_on_wheeltec_robot mapping.launch 2 启动rviz使建图可视化 rviz 在rviz中如果出现小车坐标错误,如小车坐标倾斜,可以按单片机上的RESET键使里程计复位。 我在测试中还出现启动mapping.launch后持续显示无法启动…

2023牛客寒假算法基础集训营5 -- C - 小沙の不懂

题目如下&#xff1a; 题目描述 输入描述: 输入两个整数 a, b, 0≤a,b<101050 \le a, b < 10^{10^5}0≤a,b<10105 输出描述: 如果在每一种情况中 a>ba>ba>b, 则输出">“。 如果在每一种情况中 a<ba<ba<b, 则输出”<“。 如果在每一种…

KT6368A双模蓝牙芯片功能 参数 应用 等等介绍

目录 一、KT6368A蓝牙芯片的基本介绍 二、KT6368A的功能介绍 三、KT6368A应用场景介绍 四、KT6368A的扩展说明 一、KT6368A蓝牙芯片的基本介绍 先看看官网的简单介绍&#xff1a; KT6368A芯片是一款支持蓝牙双模的纯数据芯片&#xff0c;蓝牙5.1版本。芯片的亮点在超小尺…

2022年重回王座,通用汽车电气化前景几何?

北京时间1月31日&#xff0c;美国汽车巨头通用汽车发布2022财年年报&#xff0c;第四度业绩超预期。 据通用汽车财报显示&#xff0c;其2022年Q4实现营收431.08亿美元&#xff0c;市场预期为406.5亿美元&#xff0c;摊薄调整后每股收益为2.12美元&#xff0c;市场预期为1.69美…

开学礼物送什么给孩子有意义?盘点最好的开学礼物之护眼台灯

即将开学啦&#xff0c;很多家长会给孩子准备开学的礼物&#xff0c;鼓励孩子春季新学期好好学习。 那么在开学送哪些礼物能显现出家长的良苦用心呢&#xff1f;也是随着这几年儿童近视率逐渐上升&#xff0c;近视成为许多家长担忧的问题&#xff0c;能更好的预防近视&#xf…

mongodb副本集部署及springboot集成

一、mongodb应用安装1、官网下载mongodb的社区版https://www.mongodb.com/try/download/community2、离线安装将下载好的mongodb安装包上传至服务器指定目录病解压&#xff08;1&#xff09;配置环境变量export MONGO_HOME/home/master/mongodb/mongo export PATH$MONGO_HOME/b…

自定义注解

如何实现自定义注解在我们实际开发过程中如果能合理的运用自定义注解&#xff0c;则会大大减少我们代码的开发量。那怎么才能实现自定义注解呢&#xff1f;废话不多说&#xff0c;直接上干货&#xff01;一、创建注解这一步呢&#xff0c;我们可以理解成对应的实体类&#xff0…

BetaFlight统一硬件资源抽象设计

BetaFlight统一硬件资源抽象设计1. 源由2. 资源配置注意事项3. 资源配置文件修改验证步骤Step 1&#xff1a;确认硬件修改内容Step 2&#xff1a;资源配置文件修改Step 3&#xff1a;验证配置文件Step 4&#xff1a;提交资源配置文件PR4. 参考资料就笔者接触嵌入式设计以来&…

ESP32设备驱动-MAX44009环境光传感器驱动

MAX44009环境光传感器驱动 文章目录 MAX44009环境光传感器驱动1、MAX44009介绍2、硬件准备3、软件准备4、驱动实现1、MAX44009介绍 MAX44009 环境光传感器具有 IC 数字输出,非常适合智能手机、笔记本电脑和工业传感器等多种便携式应用。 它的工作电流小于 1A,是业内功耗最低…

Springboot——Swagger

Swagger2 的 maven 依赖使用 Swagger2 工具&#xff0c;必须要导入 maven 依赖&#xff0c;当前官方最高版本是 2.8.0&#xff0c;我尝试了一下&#xff0c;个人感觉页面展示的效果不太好&#xff0c;而且不够紧凑&#xff0c;不利于操作。另外&#xff0c;最新版本并不一定是最…

Redux toolkit

Redux 是 JavaScript 应用的状态容器&#xff0c;提供可预测的状态管理。 Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法 入门 Redux | Redux 中文官网 本案例是一个加&#xff0c;减的计算器&#xff0c;从零到壹 1、创建一个react的项目 Create-react-app react-too…