Golang Go语言应该如何选择API网关呢
公司基于 gin 开发了一个系统,目前是单体服务,基本上都是 Http 和前端交互。
由于业务发展,想转入微服务,我们想基于 eureka/Consul 做注册中心,引入一款网关作为负载均衡器。
所以请问一下,应该如何选择 api 网关呢。
(关于 gin 往注册中心注册,我们准备自己写。微服务之间的调用,也是准备自己写。)
当然准备是准备,,这个也说不准,看实际情况,
Golang Go语言应该如何选择API网关呢
如果计划接口全用 gRPC 去开发,可以选:gRPC Gateway + Buf
更多关于Golang Go语言应该如何选择API网关呢的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我之前群里和你说了,用 b 站的奎托斯啊,注册中心直接依赖 k8s 就行了,你们不会微服务不上 k8s 吧?服务注册发现还用自己搞?直接 k8s 用 endpoints 或者 service 、label 做不就得了。
如果不上 K8S 这一套,推荐看看 APISIX
直接开源版本的 kong 网关就行了。
上面的老哥说的挺好的,gRPC Gateway + Buf 推荐,很舒服。但也有一些小坑要踩。可以调研一下
既然是做调研,问自己三个问题:
1. 服务怎么拆分
2. 拆分后 膨胀的工作量, 和熵增的架构 怎么治理 (服务治理
3. 我真的需要为服务吗
nginx->api gateway->grpc 服务, api gateway 用 go 自己写。 简单一点就是 nginx->业务服务
推荐一下 Nats 这个消息中间件。
Nats 是一款分布式消息平台,内置负载均衡、服务注册、消息队列等功能,很适合用来做微服务间通讯。
https://nats.io/
https://github.com/nats-io/nats.go/blob/main/micro/README.md
我是用的 阿里云 ALB 做负载均衡器
楼上回复,均已感谢。
谢谢大家回复。
建议别误入歧途😂
dapr
玩不了 k8s ,公司没有运维。
#12
OP 撒谎,明明没有感谢我。。。
我一声叹息的意思就是别做没必要的折腾了,自己都说了公司没有运维,这点规模的团队业务量估计也不会太大、性能足够、大不了硬件规格升级下也比负载均衡省事。如果真的业务量暴涨了,关键性能瓶颈基本都在数据库这层,即便扩容多节点的 gin 服务,cdn 回源到几个 nginx 、nginx 里均衡下 gin 服务就足够了,没必要非得叫什么 api 网关。
前面有几个人建议引入 grpc 的,千万别信他们,引入一层,则每个接口都需要你把 grpc 那层、gin 这层都实现一道 grpc call 、method 的逻辑,本来 api 直达 gin handler 就可以,非要中间插一杠子、关键中间插这一道完全是多余的。
也建议那几位搞清楚 rpc 适合哪些地方,例如你搞数据中台,或者内部拆分的不同的服务之间的调用,rpc 比 http 性能高而且结构化之类的更规范方便,是可以的,这其中最适合的主要是数据量很大、可能数据层单点或者简单集群无法满足业务需要,或者你们微服务拆分的太多、如果都直连数据层、数据库之类的连接池数量压力就非常大,这时候你搞个几种的数据层服务、中台之类的是合理的,或者不同部门之间也都挺大、业务内容多,那么独立出来服务给其他部门调用。
但 OP 的这个场景是直接面向用户的 to c 的接口,这种在中间加一个 api 转 rpc ,纯纯是给自己加工作量、给公司增加成本浪费资源、并且出问题时候的纵向定位链条增加了、更麻烦,而且配套下来又要引入更多东西比如链路追踪。。。
#7 随便引入消息队列之类的更是离谱。消息队列用于解耦、削峰之类的 ok ,但你得是不要求消息队列消费后再返还结果的服务比较好。否则首先相当于改变了同步模式,因为你需要等待入队后消费方把结果再给你、你才能把结果返还给请求方。这本质上相当于回调,虽然你可以用 chan 之类的、进程内不同模块或者不同服务之间 rpc 之类的实现类似同步代码的封装、但还要处理超时失败之类的一系列配套处理,逻辑流程可比之前麻烦太多了。所以,如果是电商下单这种,例如你先插入了订单、然后 push 到消息队列里作为待处理订单、然后就可以响应用户下单成功了,后续的待处理由商户触发已发货、物流已出发、后续订单签收确认之类的是其他模块从待处理的消费队列里去一步步处理并丢入下一个流程的消息队列或者订单状态改变,本次请求不需要请求方等待消息队列消费后的结果,这是 ok 的,否则就是给自己找罪受
上来就推荐 k8s 同样的更是离谱,除了中大规模团队,上 k8s 新增的管理、软硬、人员成本,比带来的好处可高多了,入不敷出,别张口就来
几位人间清醒比较值得赞,既往楼层的其他人(如果我没看错的话)统统不值得感谢、并且是误人子弟! OP 真是有病乱投医!
#16 这时候你搞个几种的数据层服务
-> 这时候你搞个集中的数据层服务
看你写了很多,我就反驳你一条吧。
我看你写了“则每个接口都需要你把 grpc 那层、gin 这层都实现一道 grpc call 、method 的逻辑”
一般 api gateway 写好了之后,后续增加接口只需要在 web 页面上配置一下 path+method 转发到哪个 service 的哪个 method ,谁还需要一个个接口硬编码去转发?
还有,链路追踪这些跟微服务根本就没有啥必然关系,就算是单体服务,照样可以用链路追踪,它可以帮助你快速发现和排查问题。
还有,给 OP 推荐这个方案是因为 OP 说要搞微服务+api 网关, 业务该不该上微服务是 OP 自己的判断,我只是按照 OP 的需求推荐方案。
就算退一万步说,公司的业务确实单体就够了,但是站在知识储备和个人发展的角度来说,做一点过度设计对自己的职业发展、对公司的后期拓展也不是啥坏事, 而不是一句公司业务不需要就拒绝这些技术方案。
我们在 kong 和 apisix 中选择了 apisix ,目前快两年了,中间升级过一次,没有问题。
apisix 和 kong 都可以.支持多语言网关自定义插件…也可以插入 K8S 或者独立部署+普通 docker 服务
all in http 稳妥些…包括内网…现在 ai 加持.http 是未来趋势.
gRPC 负载均衡是个大坑…也不适合业务扩展…除了前几年扯上还能装下逼.明明 1 公里骑个单车或者走路都能到…非要打个车
现在这些云厂商的负载均衡产品都可以作为网关使用了,代替 nginx 的角色。
我猜你说的 grpc 负载均衡的坑是在 k8s 环境下,新伸缩出的节点与老节点负载不均的问题吧?
> #6 nginx->api gateway->grpc 服务,api gateway 用 go 自己写。
api gateway 自己写,你得先有 http handler 然后转成 grpc call 去请求原来的服务对吧?原来的 gin 服务得改造成 grpc server 、把以前的 gin handler 改成 grpc method 对吧?
> #18 一般 api gateway 写好了之后,后续增加接口只需要在 web 页面上配置一下 path+method 转发到哪个 service 的哪个 method
所以还得开发个 web 页面管理这个功能啊?
但是 grpc golang call 好像没有直接通过字符串调用方法的功能吧?所以你得首先生成了对应的 call 代码、然后再在你的 web 页面上配置才行吧,那么每次更新版本有新增、修改 grpc 协议相关,你都需要把 grpc gateway 也发版本、这也是运维成本
我看了下 grpc-gateway 也是要每次先按协议生成之后才能调用,按 proto 生成之后按道理就没必要自己再 web 页面上配置了、所以你说的 web 页面的开发和在上面人工配置的成本估计可以省掉,但每次改协议发版本也仍然是多余的浪费:
https://github.com/grpc-ecosystem/grpc-gateway?tab=readme-ov-file#4-generate-reverse-proxy-using-protoc-gen-grpc-gateway
另外,如果想全动态,当然也可以自己去把 grpc 协议格式弄出来自己去拼二进制的协议,也可以搞,但同样需要花不少时间去搞这个、而且这个一半的 CURDer 也搞不定。
另外,由于 grpc gateway 直接处理 client 的 http 请求,可能就难以避免偶尔对个别接口参数的定制,网关最好还是透明一些,grpc 用 pb 这种强类型定义相比于 json 没那么方便做到网关功能的透明
所以我持续抵制这种 to c 的 api 使用这种 api 转 rpc 的 gateway 的架构设计方案,微服务集群内部之间直接 rpc 就可以了也没太大必要加这种 gateway
> #18 还有,链路追踪这些跟微服务根本就没有啥必然关系,就算是单体服务,照样可以用链路追踪,它可以帮助你快速发现和排查问题。
这个我不是很同意:例如原本只有一个 gin server 的 api 流程(连网关、反代都不需要加)、只要查 gin server 日志就够了,没有多链路所以也无所谓链路追踪
但引入更多中间节点,链路就变长了、流程就变多了,当然也可以分散着各自去查各个节点的日志,但不够系统
当然,我也不是说必须增加,自己单独查 grpc gateway 日志也行
> #6 简单一点就是 nginx->业务服务
这句是好的建议
没人用过 traefik ? traefik 是 golang 原生实现的 api 网关, 支持 二进制、docker 、k8s 等部署方式.
https://github.com/traefik/traefik
grpc 可以直接动态的完成 client 调用,grpcurl 可以看一下,grpc 协议也不是跟 protobuf 强绑定了,也可以用 json 作为编码格式。 链路追踪很多时候是用来记录 io 操作的,所以 redis mysql 等也会被记录进来,在开发和线上排查问题特别好用(例如线上一个接口比较慢,但看不出哪里阻塞的,链路追踪可以一眼看出症结)。 还有,绝大多数大一点的公司都有 api gateway 这一层的,它能做很多事情(接口配置、鉴权、限流、灰色发布、流量染色、数据清洗、编排等等等等),只不过目前你们还没感受到罢了。
技术,简单的场景有简单的方案,复杂的场景有复杂的方案。 我个人认为,技术人员,不应该让自己抵触某种技术,毕竟不会跟会但是不用是两码事。 至少面试的时候别人会让你回答怎么造飞机。
能单体就单体吧,别搞太复杂
k8s + istio
我最近也在搞这些东西,刚好看到这篇帖子,从楼上学习到了。
记得是 18 年的时候.Envoy 还能勉强正常.新老节点相对稳定…那时候大部分中间件都不支持.要不就是内存泄漏要不就压力大连接不会重用…现在大部分企业多少业务会有 grpc 的遗留项目或者那班架构师还在…没办法.曾经吹得那么火…中台.GRPC.等等…都是坑
自己写一个咯
#25
> grpc 可以直接动态的完成 client 调用,grpcurl 可以看一下,grpc 协议也不是跟 protobuf 强绑定了,也可以用 json 作为编码格式。
那这个开发动态的可以方便些,但是 json 也更慢了一点。
而且不管开发怎么方便,仍然是新的成本,使用 api gateway 相比于 nginx 也未必是优势。
> 链路追踪很多时候是用来记录 io 操作的,所以 redis mysql 等也会被记录进来,在开发和线上排查问题特别好用(例如线上一个接口比较慢,但看不出哪里阻塞的,链路追踪可以一眼看出症结)。
这可不只是记录 io 哦,重要的业务,也会带上业务信息,例如电商订单 ID ,可以按订单 ID 查询所有相关流程日志、快速定位问题。
> 还有,绝大多数大一点的公司都有 api gateway 这一层的,它能做很多事情(接口配置、鉴权、限流、灰色发布、流量染色、数据清洗、编排等等等等),只不过目前你们还没感受到罢了。
这些用 nginx 好像也可以搞吧?
所以这并不是我们自己感受不感受的问题,而是选型上我们就不认为这个相比于传统方案具有优势。
别说的好像不自己定制开发就活不下去了似的
> 技术,简单的场景有简单的方案,复杂的场景有复杂的方案。
咱别凭空把自己认为的优势就是优势,至少把原因讲出来,我前面抵触这种 gateway 都是带了说明的、而且是说明具体原因,而不是像你这样说大公司都有拿来背书,好像大公司有就是好的、别人没有就是不好的一样,劣币驱逐良币也好、推广力度不同造成用户数量不同的事情多了去了,所以不同的事物对比、可别拿 xxx 都在用这种逻辑来辩论、这可不是直接的因果关系啊。
当然,如果我家业务确实需要定制,那我也会去定制开发,但绝大多数团队,没必要,包括很多大公司的项目多加这一层也是画蛇添足
> 我个人认为,技术人员,不应该让自己抵触某种技术,毕竟不会跟会但是不用是两码事。 至少面试的时候别人会让你回答怎么造飞机。
不管会不会,我倒是无所谓被面试官欺负,反正习惯了自己造。至于 grpc 我到底会不会,我得说明一下。
grpc 我个人不怎么用,我用自己的:
https://github.com/lesismal/arpc
这是 benchmark 对比,但这个只是性能 benchmark ,arpc 性能还可以,至少比 grpc 强很多,因为谁叫 grpc 爹非要选 http2 做网络层呢,对于内网之间的 rpc 、http2 就显得比较多余和浪费了、直接 tcp 性能好得多:
https://colobu.com/2022/07/31/2022-rpc-frameworks-benchmarks/
不只是性能,实际使用上 arpc 还有很多便利:
比如不只是 server 之间可以用、client 也可以请求 server
比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
比如可以做的业务类型也不限于微服务,游戏、IM 、推送各种业务都可以做
比如 arpc 不限制序列化方式,相同或者不同的 method 的每次请求都可以是不同的序列化,甚至也可以直接使用一段 buffer
中间件之类的也都支持,而且是支持两个维度的中间件:编解码、路由,用户可以自己定制、扩展更多东西
grpc 对我而言性能和易用性都太弱,复杂点的业务、功能它实现起来很麻烦
我也不只是做 web 这种相对简单的服务,所以我个人一是不稀罕用 grpc 因为性能差、二是它确实无法满足我的需求,即使用它、仍然要引入更多轮子来实现它搞不定的业务功能
因为不怎么用 grpc 、所以我也确实对 grpc 只了解基本使用而已、不像你们那样对它那么熟悉
确切地说,我不只是抵触 grpc gateway ,我连 grpc 都抵触的 😇😂
建议不要为了微服务而微服务,微服务说实话没什么用,提升了项目复杂度不说还降低了性能,做 web 开发最大的性能瓶颈基本都是在 mysql 这边,微服务唯一能解决的痛点就是大型项目多人协作问题,其它情况都是画蛇添足,不如直接 monorepo + 单体服务
你抵触 grpc 我觉得没问题,但你抵触 api gateway 我就无话可说了, 因为 api gateway 这个东西怎么说呢,稍微大点的公司里面都有的,它是证明了自己的价值的。 还有,为啥要抵触呢?特别是你也是想自己做 rpc 的,更应该看一下现有的几个比较出名的 rpc 方案的优缺点,这样才能集大成于一体,而不是闭门造车,不是吗?
还有 grpc 用的广有一个很重要的原因是因为它名气大,适配的语言也多,遇到问题网上现成的答案也多,rpc 方案里能与它竞争的也只有 thrift ,在未公司项目做技术选型时选择一门成熟的、名气大的、适配语言多的、社区活跃的也是一个很重要的原因,它能帮你规避很多坑。
能自己手撸 rpc 协议乃至 7 层协议的很多,不稀奇,但是在微服务领域,一般除非是顶尖大厂(顶尖大厂为了规避法律风险、漏洞等未知风险、极致性能等原因),绝大多数都是用现成的,因为好维护、组建团队都比较方便。
当年造出 RPC 这个概念的人、以及 HTTP 作者,他们这些大佬本身对互联网发展做出了巨大贡献,但是单就这俩玩意而言,造成了很多开发者对网络只知道或者只会用 request-response 这种模式。
而实际业务种这种单一的 request-response 模式无法满足复杂需求。网络交互本质就是相互发数据,对于 client 、server 两个点而言,就是 c->s 和 s->c 两个方向,发数据也不一定要对方响应,不需要回复可以叫 notify 或者 push 、只发不收,需要响应的可以叫 request and response 。
2 个方向是否响应 2 种=4 种交互,但 RPC 和 HTTP 都只搞了一种,HTTP2 的 stream 都是后话了、而且使用方式仍然局限。
arpc 本质上其实不是 RPC ,而是更广义的网络交互库,支持 c->s 和 s->c 两个方向上的 notify 和 request and response ,就是相当于上面说的 22=4 种交互,所以能用来实现各种业务。
对比之下,传统的 RPC 框架,模式局限、也主要是 server 之间的,用起来感觉就像是被阉割过、老觉得裤裆一紧。
所以,我是真的不喜欢那些传统 RPC 框架,太弱太难用了,可能 web 圈主流只有这些所以你们只能用这些吧。。。
grpc 我之前也用 后来我为啥不用了
我的 mac 执行了一次 brew update 后问题就来了 版本升级了 新版本生成的文件兼容不了老版本
比如不只是 server 之间可以用、client 也可以请求 server
-你这个指的是 grpc 编译生成 client?
比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
-grpc 的双向数据流模式
比如可以做的业务类型也不限于微服务,游戏、IM 、推送各种业务都可以做
-grpc 一样做吧,这个业务场景跟协议没啥关系。IM 都可以用 grpc 的双向数据流模式写,如果你想的话。
比如 arpc 不限制序列化方式,相同或者不同的 method 的每次请求都可以是不同的序列化,甚至也可以直接使用一段 buffer
-grpc 的自定义编码集
中间件之类的也都支持,而且是支持两个维度的中间件:编解码、路由,用户可以自己定制、扩展更多东西
-grpc 的 Interceptor?
或者这么说吧,正常大家能想到的常用的场景,grpc thrift 这种级别的项目基本上都已经有了,都不用想的。 所以,切勿闭门造车。
#34
不是 100%的纯抵触,而是,用它和不用它对比之下,它可能没有带来真正的优势。只有在我确认它能带来提升的时候我才会去搞它,OP 这种场景,我觉得没必要,甚至即使改造成微服务,如果数据量不是很大,我都不建议在微服务中引入任何 RPC 。
因为相比于直达、RPC 是纵向链条新增了一层,新增一层对于开发、维护、问题排查,就新增了一个复杂度,这个复杂度可能不是+1 ,而是+N 。
兄弟,你说的这个就是 grpc 的双向数据流模式啊,你去看看文档吧。。唉,闭门造车说的一点不假。 你这要是跟别人技术交流的时候这么讲,就要被人喷了。
consul 挺不好用的 可能我用的姿势不对
更喜欢 ETCD
#37
> 比如不只是 server 之间可以用、client 也可以请求 server
> -你这个指的是 grpc 编译生成 client?
不是。
是指用户直接访问,比如 web 前端直接请求:
https://github.com/lesismal/arpc/blob/master/examples/webchat/chat.html#L81
> 比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
> -grpc 的双向数据流模式
> -grpc 一样做吧,这个业务场景跟协议没啥关系。IM 都可以用 grpc 的双向数据流模式写,如果你想的话。
> 比如可以做的业务类型也不限于微服务,游戏、IM 、推送各种业务都可以做
这倒确实是可以,但使用起来更麻烦,普通的推送服务还好。
复杂点的业务比如游戏,每个协议包也都可能是不同的 CMD/Method/Router ,你可能需要在 stream 基础上再二次封装一道 router handler 的逻辑
> 比如 arpc 不限制序列化方式,相同或者不同的 method 的每次请求都可以是不同的序列化,甚至也可以直接使用一段 buffer
> -grpc 的自定义编码集
> 中间件之类的也都支持,而且是支持两个维度的中间件:编解码、路由,用户可以自己定制、扩展更多东西
> -grpc 的 Interceptor?
你说的这些,很多需要再扩展之类的,像我这种不熟悉它们的"小白"去研究怎么扩展就已经很难受了,而 arpc 里这些默认是开箱即用了,另外还有性能因素。
> 或者这么说吧,正常大家能想到的常用的场景,grpc thrift 这种级别的项目基本上都已经有了,都不用想的。 所以,切勿闭门造车。
闭门造车这个词,建议也先对比下,如果造出来的比原来的差,那确实没必要,如果造出来的比原来的好,那就不叫闭门造车了。
反倒是建议你,不要闭关锁国、多开眼看看世界比较好吧
另外,百度、腾讯、字节各种大厂,也都有开源自己的 rpc ,就像你前面举例大厂都用 api gateway 来做论点一样,我想以彼之道问你一句:这些大厂自己造 rpc 而不是直接用 google 家的、它们算不算是闭门造车?
请不要说它们是大厂有资格闭门造车,我个人太弱没这个资格。还是前面的论点:不要虚空用 xxx 在做这种逻辑来辩论,要用实际的好坏来做逻辑
再另外,我还真就喜欢造车,但造的东西肯定也不是为了瞎折腾,而是为了能解决一些痛点:
https://github.com/lesismal/nbio
https://www.v2ex.com/t/945827
#39
先看#41 吧,别乱用闭门造车这个词,grpc 这种破车有什么好的值得你如此喜欢,拿块烂铁当宝贝呢。。
对比我自己造的、grpc 的主要优势就是跨语言支持更强罢了,没办法啊,我精力有限,不可能多个语言都搞一轮
闭门造车这个词可能不对,但闭门这个词还算是比较准确,因为我造车的时候确实没有参考它们、主要是按照自己的设计来做的
兄弟如果你的从业经验主要是应用层的工作、公司里头不需要你造轮子、那你可能只要有轮子并且够用就可以了也不关心轮子好坏,但你可能就 get 不到这些造轮子的重点、也不太能够对轮子之间的重点进行合理的对比,这没错,大多数人都是这样工作的,但请不要以为自己用的就是最好的、其他的就都是闭门造车了,这样就有点一叶障目了
看起来不错啊
> 比如 server 也可以直接推送数据给 client 、client 也可以只推送数据不需要 server response
> -grpc 的双向数据流模式
> -grpc 一样做吧,这个业务场景跟协议没啥关系。IM 都可以用 grpc 的双向数据流模式写,如果你想的话。
这么说吧,grpc 双向流之上封装也能搞定这些,但双向流就相当于 TCP 之于 arpc ,双向流只是支持了基础的网络交互方式、相当于网络传输层相当于 TCP ;
对于复杂场景的协议交互、应用层仍然需要很多 Cmd/Method/Router 所以对于这些场景,用户仍然需要额外的协议封装,arpc 开箱即用的双向 Call 、Notify 都已经封装好了;
双向流太难用了,性能也一般
作为运维:上来就微服务的,我要问候他姥姥
作为运维:上来就引入 k8s 的,感谢程序员赏口饭吃
本来想再反驳两句的,后来想了想每个人都有自己的思想,无关对错也没有对错。 另,祝你成功,再见!
网关: Apinto
服务注册+发现: Polaris
面向简历编程是把? 唉,程序员都太焦虑了。
traefik
嗯嗯,也祝你成功,并且欢迎来体验下我的库 ~
感觉 dapr 有点意思。。。
楼上说了很多,
网关类:kong ,traefik ,apisix ,nginx ,gRPC Gateway ,Apinto ,这一类都是网关类型
ALB 类:阿里云 ALB
新的类型:dapr ,istio
在选择Golang的API网关时,可以从以下几个方面进行考虑:
一、功能需求
明确API网关所需的功能,如路由分发、限流、熔断、鉴权等。根据功能需求选择具备相应功能的API网关。
二、性能表现
API网关的性能对于微服务架构至关重要。选择并发性能高、吞吐量大、延迟低的网关,如基于Golang开发的Go-Gateway,利用Golang的并发优势,可以处理大量并发请求。
三、开源与社区支持
选择开源的API网关,如Kong、Tyk等,可以获取丰富的功能和插件支持。同时,开源社区活跃,可以获取及时的更新和维护。
四、集成与扩展性
考虑API网关与现有系统的集成能力,以及是否支持自定义插件和扩展。如Go-Micro微服务框架,提供了API网关的完整实现,支持服务发现、负载均衡和熔断等功能,且易于扩展。
五、安全性
安全性是API网关不可忽视的一环。选择具备身份验证、授权机制、数据加密等安全功能的网关,如Go-Gateway内置JWT鉴权、IP黑白名单等功能,确保API的安全性。
综上所述,选择Golang的API网关时,需要综合考虑功能需求、性能表现、开源与社区支持、集成与扩展性以及安全性等方面。具体选择哪个网关,还需根据项目的实际情况和需求进行权衡。