前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何高效的处理第三方接口数据?

如何高效的处理第三方接口数据?

作者头像
林老师带你学编程
发布2019-07-31 14:38:45
1.4K0
发布2019-07-31 14:38:45
举报
文章被收录于专栏:强仔仔强仔仔

很多公司业务都需要进行第三方接口的对接工作,特别是那种大部分数据都来自第三方的项目。比如亚马逊商家服务的saas系统,基本上所有的数据都来自亚马逊平台。

背景

像这种需要定期获取亚马逊接口数据,然后存储到本地数据库中的项目,一般就会涉及到数据转换过程。这边我将会给大家介绍一个实际项目案例,平台从亚马逊获取数据,进行解析的过程中,因为数据过大,导致内存溢出的场景。

接口说明

亚马逊平台返回的是json格式数据,然后通过jackson进行json解析,将最后的解析结果保存到我们自己的数据库中。但是json反序列也是需要技巧的,否则会因为使用不当导致内存溢出。

json解析

一开始我们通过jackson工具类,将json流解析为JsonNode,如下所示:

代码语言:javascript
复制
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree((GZIPInputStream) reportMap.get("data"));

但是当请求量过大的时候,内存中就会出现大量的LinkHashMap、Entry、HashMap、Node之类的集合对象,时间一长就OOM内存溢出了。

image
image

解析改造

集合对象如果没有管理好,会很难被GC回收,所以一开始我们想到的办法是将JsonNode设置为null,后面发现这样做没起到任何作用,所以只能进行彻底的改造,直接用jackson解析成我们需要的对象,如下所示:

代码语言:javascript
复制
private List<ReportAdvertisementDto> parseJsonIO(GZIPInputStream gzipInputStream) {
ObjectMapper mapper = new ObjectMapper();
List<ReportAdvertisementDto> advertisementDtoList =new ArrayList<>();
try {
    advertisementDtoList = mapper.readValue(gzipInputStream, new TypeReference<List<ReportAdvertisementDto>>() {
            });
} catch (IOException e) {
    logger.error("parseJsonIO转化异常,错误信息为:{}", ExceptionUtil.formatException(e));
}
return advertisementDtoList;
}

修改完之后可以很明显的看到,LinkHashMap、Entry、HashMap、Node之类的对象数量大量减少,内存的占用率明显降低,大大的减少了内存OOM的风险。

image
image

深入改造

写到这一步是不是就优化完毕了呢?不!!!一开始的时候我是将所有的字段全部设置为String,然后通过Long.value()和Integer.value()转换为数据库需要的字段类型,如下所示:

代码语言:javascript
复制
campaignSearchTermReport.setImpressions(Integer.valueOf(impressions));
campaignSearchTermReport.setTotalspend(Long.valueOf(cost));
campaignSearchTermReport.setSales(BigDecimal.valueOf(sales));

所以为了避免这种情况发生,我们需要将转换的对象字段提前设置好,数据库需要什么类型,我们就设置为同样的类型,这样的好处就是我们不需要进行转型,直接就可以set进去,如下所示:

代码语言:javascript
复制
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ReportAdvertisementDto {
    private double cost;
    private String attributedSales1d;
    private int impressions;
    private int clicks;
    private long campaignId;
    private String campaignName;
    private String adGroupName;
    private long adId;
    private long adGroupId;
    private String sku;
    private String asin;
    private long keywordId;
    private String matchType;
    private String query;
    private String keywordText;
    private int attributedConversions7d;
    private double attributedSales7d;
    private int attributedUnitsOrdered7d;
    private int attributedConversions7dSameSKU;
    private double attributedSales7dSameSKU;
}

总结

在数据量不大的情况下,代码就算效率不高,也不会出现什么问题,但是当数据量达到一定级别,代码问题就会被凸显出来。比如我们平时用Map来存储临时数据,但是map集合的大小要比对象更加占用内存,如果服务器硬件不高,很容易就发生内存溢出。 所以我们在处理接口数据的时候,一定要本着简单、适用。尽量不要将json数据解析为map等集合,对象字段尽量设置为和入库的的表字段类型一致,减少转型的发生。禁止出现大量对象和对象之间数据流转,尽量做到一个解析后的对象直接入库,不需要进行任何转型操作。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年07月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档