0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

搞一个grpc动态代理的想法,并初步实现

jf_wN0SrCdH 来源:Rust语言中文社区 2023-02-08 16:13 次阅读

前言

 沟通服务间接口内容(尤其是前后端接口),是非常让人头疼的事。极其容易扯皮。接口文档写起来也很痛苦,每个字段的改动都需要及时更新,否则就会出问题。服务端通信如果用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 服务启动后会打印如下日志,说明服务启动成功f79e9010-a787-11ed-bfe3-dac502259ad0.png

测试

发起一个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"}并且在代理服务上产生访问日志:f7b5da68-a787-11ed-bfe3-dac502259ad0.png 到这里一个简单的演示就成功了

结构和原理

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

尾语

当前版本还只是一个比较初级的版本,功能还很初级。还有很多功能需要完善,架构也可能会有大的变动,所有上一节并没有详细描述。作者预计但不承诺会继续完成下面的内容。
  • restful支持:这个功能是P0级,在我go版本的grpc动态代理服务中经常被用到,在可预计的规划里一定会实现。
  • 事件系统:该功能是为了方便二次开发,很有必要。也有可能用中间件模式,类似traefik
  • 负载均衡/sidecar:负载均衡是为了用在服务网关上,sidecar是用在pod里,二者会选一个实现,我倾向于前者,和我之前写的rust-ingress联动上。这里自荐一波rust-ingress项目:https://gitee.com/yutiandou/rust-ingress
  • 性能优化,这个会一直持续做下去,欢迎有性能极致追求的小伙伴能够共同前进
  • 实时反射:目前是通过配置文件,在启动的时候加载服务源。好的(懒人)方案是proto文件变化后能够实时监控到,下一步会完成这个功能。
欢迎有兴趣的小伙伴提出建议,并热烈欢迎大家参与进来。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 通信协议
    +关注

    关注

    28

    文章

    739

    浏览量

    39746
  • HTTP
    +关注

    关注

    0

    文章

    466

    浏览量

    30316
  • 编码
    +关注

    关注

    6

    文章

    835

    浏览量

    54457

原文标题:尾语

文章出处:【微信号:Rust语言中文社区,微信公众号:Rust语言中文社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    GRPC的基础使用方法

    语言的 gRPC 客户端和服务器实现,它提供了一个简单易用的 API,可以方便地创建和使用 gRPC 服务。 基础用法 创建 gRPC 服务器 在 Rust 语言
    的头像 发表于 09-19 16:08 507次阅读

    JDK动态代理的原理

    在Java中,动态代理是一种机制,允许在运行时动态地创建代理对象来代替某个实际对象,从而在其前后执行额外的逻辑。 为什么JDK动态
    的头像 发表于 09-30 10:51 313次阅读

    关于智能小车交替领跑的实现方法~大家有什么想法交流下~

    ,区别就在与软件的算法设计。希望论坛里有想法的朋友可以交流下哈~3、绝无作弊之嫌哦~只求简短的想法~不求具体分析,具体代码~
    发表于 09-01 09:14

    智能家居网络系统的研究及初步实现

    智能家居网络系统的研究及初步实现
    发表于 09-16 21:34

    java的动态代理机制和作用

    的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。 在java的动态
    发表于 09-27 14:37 0次下载

    java动态代理分析

    定义:为其他对象提供一种代理以控制对这个对象的访问。 动态代理使用 java动态代理机制以巧妙的方式实现
    发表于 09-27 15:14 0次下载

    java动态代理机制详解的类和接口描述

    的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。 在java的动态
    发表于 09-28 13:33 0次下载

    java的动态代理

    ,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 按照代理的创建时期,
    发表于 03-12 14:12 0次下载

    基于JDK和CGLB分别实现动态代理

    本文档内容介绍了基于JDK和CGLB分别实现动态代理及源代码
    发表于 03-12 14:56 0次下载

    什么是动态ip代理电脑软件?

    动态IP代理计算机软件是计算机浏览器和Web群集服务器之间的网络服务器。如果使用动态IP代理计算机软件访问Internet,则计算机浏览器不会立即转到Web网络服务器来检索网页,而是仅
    发表于 01-14 18:06 652次阅读
    什么是<b class='flag-5'>动态</b>ip<b class='flag-5'>代理</b>电脑软件?

    IP知识百科之什么是gRPC

    gRPC Google远程过程调用(Google Remote Procedure Call,gRPC)协议是谷歌发布的高性能、通用的开源RPC软件框架。gRPC提供了多种编程语言,同时gRP
    的头像 发表于 11-16 15:13 2816次阅读

    gRPC-Nebula微服务框架

    ./oschina_soft/grpc-nebula.zip
    发表于 06-22 14:59 0次下载
    <b class='flag-5'>gRPC</b>-Nebula微服务框架

    gRPC-Web访问gRPC服务的Web客户端

    ./oschina_soft/grpc-web.zip
    发表于 06-22 09:25 0次下载
    <b class='flag-5'>gRPC</b>-Web访问<b class='flag-5'>gRPC</b>服务的Web客户端

    mybatis接口动态代理原理

    MyBatis是一款轻量级的Java持久化框架,它通过XML或注解配置的方式,将数据库操作与SQL语句解耦,提供了一种简单、灵活的数据访问方式。在MyBatis中,使用动态代理技术来实现接口的
    的头像 发表于 12-03 11:52 436次阅读

    使用go语言实现一个grpc拦截器

    在开发grpc服务时,我们经常会遇到一些通用的需求,比如:日志、链路追踪、鉴权等。这些需求可以通过grpc拦截器来实现。本文使用go语言来实现一个
    的头像 发表于 12-18 10:13 242次阅读
    使用go语言<b class='flag-5'>实现</b>一个<b class='flag-5'>grpc</b>拦截器