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

77 天前
 dsvshx

背景:

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

方案

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

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

2320 次点击
所在节点    Java
31 条回复
iseki
77 天前
arena ,把 payload 弄到堆外面去,手动管理。但是这么一来…protobuf 自己解析想想就很麻烦。
长期来看这只能是个权宜之计,以后不能这么设计 API ,搞出大量大体积的 bytes
GenericT
76 天前
试试 intern ,和上面的 arena 一个路数,但是实现简单一些,本质都是避免多次分配。
flyqie
75 天前
挺好奇,是什么场景会有如此巨大的 grpc bytes 需求给到 java 服务端?
dsvshx
74 天前
@ccde8259 思路是这个,就是说目前 grpc 的 api 不支持分配到非堆,所以想看看我说的那个用 netty 实现的思路行不行
dsvshx
74 天前
@flyqie 消息队列的场景
dsvshx
74 天前
@momo24672 这个解决不了,protobuf 里面的 bytes 还是会分配对堆内存的问题
dsvshx
74 天前
@iseki proto 编解码工作量还行,接口不多,而且工作是一次性的。至于 API 这个,说多了都是泪,需要适配客户端,客户端升级不了。
能再详细说一下 arena 是什么原理,怎么用吗?
ccde8259
74 天前
@dsvshx 想完全避免内存分配的话……从 mmap 把数据往外撸的地方就得下手……TCP 你还不知道读多长……unsafe malloc 难写
dsvshx
74 天前
@ccde8259 这个我理解 netty 已经给封装好了?各种 handler ,直接处理 ByteBuf 就行了
iseki
74 天前
话说,你的序列化反序列化 API 不支持按流处理吗?比如说我经常处理大体积的 JSON ,大一点一个对象可能 1G+,数据会在反序列化过程中被处理,比如说可能有去重之类的逻辑。 @dsvshx
dsvshx
71 天前
@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