目前公司对外的 api 都要经过统一 http 网关,但一些内部的 rpc 服务想要对外服务的话,我们得专门写个 http 接口暴暴露给网关,但这样要维护两套代码有点麻烦,我想在网关这层做一道转换,把外部的 http 的 json 报文转换成内部的 rpc 调用。现在有两种方案:
第一种方法:在 grpc 服务的容器内起个 http 服务,这个 http 服务跟容器内的 grpc 服务通信,然后把容器内的这个 http 服务暴露给网关。相似方案的实现者有 grpc-gateway
第二种方式:grpc 服务在编译 proto 文件时生成 descriptorSet 描述文件,并上传的网关,网关解析这个文件能知道怎么组装 protobuf 消息,用 DynamicMessage 方式泛型调用内部 grpc 服务。相似方案的实现有 apisix 和 consul 的 grpc-transcoder
想知道下大厂是不是也有在网关层 json 转 rpc 的需求,你们是怎么做的呢?这两种方案你哪个好一些,有啥坑吗

strings.Contains(r.Header.Get("Content-Type"), "application/grpc") 用 content-type 判断一下

外面直接发 grpc 请求

也是个法子🥹

grpc 是 http2 的,他这网关看起来就不支持的样子

grpc 本来就是 h2 直接透传。谁不接住解析谁就是孙子就完事了。。。

看你们的网关支持啥啊。已有网关是个不支持 h2 的,你这传了有啥用。 看别的网关有啥,是准备切换别的网关了?

还可以用 json 作为 grpc 的传输协议,http 网关不需要了解 pb 的内容。 最好要在网关做一个映射配置列表,不然全自动映射把内部重要接口泄漏了就 G 了

想让外部调用者直接能用 http json 报文调用。或者我可以把 proto 文件他们,让外部调用方用 grpc 方式调网关,这样,,也行

实际这种不是应该 两个么,一个外部的网关 流量出口,一个内部的网关 or 路由 作为 soa 的编排。

像 k8s 的 ingress-nginx 代理 http 和 grpc 服务?如果是的话,用路径匹配,分别指向不同的服务

grpc 用 http2 传输的,让我看看哪家网关还不支持 http2 ……

分开也可以,放在一起也可以。

实现过第二种,不过只在内部做定时调用使用过。做法是将 proto 文件内容上传到一个地方,然后网关处解析。不过这样的问题是每次 proto 更新,都要重新上传。想法是可以直接暴露接口给网关,网关自动获取 pb 内容。

第一个就错了吧, 不需要在 rpc 容器内启动 HTTP 服务, 你就另起服务作为 gateway, 然后穿透给 rpc 就好了. 就是你说的 grpc-gateway 不就挺好?

结合注册中心,搞个统一网关管理平台,由网关负责转发 http 请求就可以了

github.com/grpc-ecosystem/grpc-gateway.git你是说这个吗

对的

敝司是写了个简单的 HTTP bridge 给一些作 gRPC 调用比较麻烦的 client 用,大概就是 header 里传 service 和 method 名,payload 和 response 都转 JSON 。

感觉你们网关还是不健全,网关一个很重要的基础能力就是协议转换,对外统一都是 http(s),但是内部服务有 springcloud,dubbo,grpc 等,不可能让内部服务再封装 http 再在网关注册,这样所有接入方的工作量会大上不少,而且也浪费资源

大点的公司会分流量网关和业务网关,但是一般公司不会拆分这么细

GRPC 记得有一个功能是 Server Reflection ,是把自己支持的接口暴露出来,具体参考 github.com/fullstorydev/grpcurl 的文档

但是感觉这个 Server Reflection 直接对外的话,有点不安全。。。如果 GRPC 只对 gateway 开放应该还好

协议转换这块是 cpu 密集型场景,apisix 等 nginx+lua 的方案,目前的实现方案性能最差(基于 lua 做的协议转换)根据这边的落地经验,出于性能考虑,推荐以下两种:- 基于 grpc-gateway 另起一个 http server 用于转发 grpc 请求,每次调整需要重新发布代码,性能可用,无需引入新的中间件- 基于 envoy 配置 protoset 和 filter ,每次调整只需要更改配置,性能相对较高,需要引入新的中间件

搞复杂了,网关直接根据 http 请求组装一个 general 的 grpc 消息,grpc 有一个统一入口二次分发,并不是说网关直接就 touch 到业务层级去根据 proto 组装业务 grpc 数据

先报下网关选型吧,不然也不好说你能有哪些方案。常见的方式有grpc2grpc ,直接过网关透传,网关正常解 ssl 之类的。envoy 之类的技术选型天然支持。http2grpc ,网关做协议转换,kong 之类的网关有插件做。这类一般比较耗 cpu ,机器开大点。如果 protobuf 和 json 的银蛇关系非常基础、标准,可以用。这类插件遇到复杂一些的报文拼装逻辑基本歇菜。服务自己开个 http 口子。咋说呢,用 grpc 的服务不多的话,这个方案其实最省事,啥也不用折腾,毕竟网关改个配置搞错了还影响别的业务。

c#的话 我记得用过微软自己有一套 引入库直接在 grpc 文件里面定义 api 就好了两个端口 一个 grpc 一个 http 调用 import "google/api/annotations.proto";service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { get: "/v1/greeter/{name}" }; }}详细的看看微软的文档吧 learn.microsoft.com/en-us/aspnet/core/grpc/browser?view=aspnetcore-8.0还有 go 的 grpc gateway github.com/grpc-ecosystem/grpc-gateway

在 grpc 服务中增加一个 http 服务对现有系统影响是最小的,也就是一个微服务中同时提供了 http 和 grpc 两种调用(不是 grpc-gateway 方式),共用一套业务逻辑,B 站开源的微服务框架 kratos 是支持 http 和 grpc 的,我猜 B 站应该是这样的方案。