Grpc 服务优化 GC 的一个问题,请教一下大佬们

2024-04-12 17:36:56 +08:00
 dsvshx

背景:

客户端用的是 grpc 协议,这个动不了。所以服务端必须用 grpc 协议,但是我们的服务流量非常大。proto 中的 bytes 会比较大,会卡在 gc 上,性能上不去。

方案

服务端不用 grpc 框架,自己用 netty 来实现,就是两层,一层用 Netty Http2 相关的封装,一层自己手动解析 proto 的二进制,遇到 bytes 字段直接用 ByteBuf ,省掉了拷贝到堆内存的 byte[],进而节省这部分的 gc 。返回的时候直接编码成二进制 proto 的格式。

有人做过类似的吗,有什么坑吗? 或者有没有其他更好的方案解决 gc 问题,提高性能?

3126 次点击
所在节点    Java
31 条回复
iseki
2024-04-13 05:13:01 +08:00
arena ,把 payload 弄到堆外面去,手动管理。但是这么一来…protobuf 自己解析想想就很麻烦。
长期来看这只能是个权宜之计,以后不能这么设计 API ,搞出大量大体积的 bytes
GenericT
2024-04-13 18:58:11 +08:00
试试 intern ,和上面的 arena 一个路数,但是实现简单一些,本质都是避免多次分配。
flyqie
2024-04-14 14:38:19 +08:00
挺好奇,是什么场景会有如此巨大的 grpc bytes 需求给到 java 服务端?
dsvshx
2024-04-15 10:55:38 +08:00
@ccde8259 思路是这个,就是说目前 grpc 的 api 不支持分配到非堆,所以想看看我说的那个用 netty 实现的思路行不行
dsvshx
2024-04-15 10:55:51 +08:00
@flyqie 消息队列的场景
dsvshx
2024-04-15 10:57:13 +08:00
@momo24672 这个解决不了,protobuf 里面的 bytes 还是会分配对堆内存的问题
dsvshx
2024-04-15 11:02:08 +08:00
@iseki proto 编解码工作量还行,接口不多,而且工作是一次性的。至于 API 这个,说多了都是泪,需要适配客户端,客户端升级不了。
能再详细说一下 arena 是什么原理,怎么用吗?
ccde8259
2024-04-15 12:19:25 +08:00
@dsvshx 想完全避免内存分配的话……从 mmap 把数据往外撸的地方就得下手……TCP 你还不知道读多长……unsafe malloc 难写
dsvshx
2024-04-15 16:44:34 +08:00
@ccde8259 这个我理解 netty 已经给封装好了?各种 handler ,直接处理 ByteBuf 就行了
iseki
2024-04-15 22:37:43 +08:00
话说,你的序列化反序列化 API 不支持按流处理吗?比如说我经常处理大体积的 JSON ,大一点一个对象可能 1G+,数据会在反序列化过程中被处理,比如说可能有去重之类的逻辑。 @dsvshx
dsvshx
2024-04-18 17:54:39 +08:00
@iseki 主要还是 grpc 框架的限制,目前是不支持这种方式的。然后就算是在流中处理,他也是需要占用堆内存,还是解决不了 GC 的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1032027

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX