内容:
- rpc调用外部服务时,需要将req和resp的信息打印出来,以便于排查问题。
- 但是有的rpc服务的resp信息过于庞大,比如resp中有List<>信息,list很大很大时
- 会导致log.info打印信息时,产生GC,影响业务
通过将大对象拆分为小对象,解决GC耗时过长问题,进而解决GC过长对业务的影响(TP999过长导致超时、慢sql)等
1、背景
正常情况下,2M、3M就为大对象。会直接被分配至old region。如果此大对象为日志对象,被频繁的加入老年代,会引起Full Gc,影响接口性能或db性能。
2、解决
将大对象,part拆分为小对象再打印,这样young gc更快,影响更小
3、code实现(以List的拆分为例)
@Slf4j
@Component
public class PartLogUtils {public <V> void partLog(List<V> info,int count,Logger logger,String format) {List<List<V>> result = splitInfo(info, count);logInfo(result, logger, format);}private <V> List<List<V>> splitInfo(List<V> info, int count) {List<List<V>> result = Lists.newArrayList();if (CollectionUtils.isEmpty(info) || info.size() < count) {result.add(info);return result;}List<V> temp = Lists.newArrayList();int index = 0;for (V item : info) {index++;temp.add(item);if (index % count == 0) {result.add(temp);temp = Lists.newArrayList();}}if (temp.size() > 0) {result.add(temp);}return result;}private <V> void logInfo(List<V> infoList, Logger logger, String format) {for (V item : infoList) {logger.info(format, GsonUtils.toJsonStr(item));}}}
类A中使用
private final static Logger logger = LoggerFactory.getLogger(A.class);PartLogUtils.partLog(resp, 2000, logger,"queryUserInfo:[{}]");