【问题标题】:How can REST API pass large JSON?REST API 如何传递大型 JSON?
【发布时间】:2015-01-03 08:37:12
【问题描述】:

我正在构建一个 REST API 并面临这个问题:REST API 如何传递非常大的 JSON?

基本上,我想连接到数据库并返回训练数据。问题出在数据库中,我有 400,000 个数据。如果我将它们包装成一个 JSON 文件并通过 GET 方法,服务器会抛出堆溢出异常。

我们可以用什么方法来解决这个问题?

DBTraining trainingdata = new DBTraining();
@GET
@Produces("application/json")
@Path("/{cat_id}")
public Response getAllDataById(@PathParam("cat_id") String cat_id) {
    List<TrainingData> list = new ArrayList<TrainingData>();
    try {
        list = trainingdata.getAllDataById(cat_id);
        Gson gson = new Gson();
        Type dataListType = new TypeToken<List<TrainingData>>() {
        }.getType();
        String jsonString = gson.toJson(list, dataListType);
        return Response.ok().entity(jsonString).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET").build();

    } catch (SQLException e) {
        logger.warn(e.getMessage());
    }
    return null;
}

【问题讨论】:

  • 您可能需要对数据进行分页,例如 /request/?page=1&itemsPerPage=100 并在循环中多次调用以获取所有数据。
  • 也许 json 不是你的正确选择。它旨在移动小块数据,而不是整个数据库......只是我的 2c
  • @Zdravko Danev 那么除了 JSON,我还能使用哪些其他方法?我应该上传文件吗?
  • @paul.abbott.wa.us 是的,我认为这可能是最常见的方式。就像亚马逊展示商品页面一样。
  • 嗯,这取决于... :) 根据您使用的数据库以及您要完成的工作,有不同和更好的选择。 json 用于在网页和网络服务器之间进行通信以移动少量数据。

标签: rest heap-memory large-data


【解决方案1】:

这样做的 RESTful 方式是创建一个分页 API。首先,添加查询参数以设置页面大小、页码和每页最大项目数。如果未提供其中任何一个或提供了不切实际的值,请使用合理的默认值。其次,修改数据库查询以仅检索数据的子集。将其转换为 JSON 并将其用作响应的有效负载。最后,按照 HATEOAS 原则,提供指向下一页(前提是您不在最后一页)和上一页(前提是您不在第一页)的链接。对于奖励积分,请同时提供指向首页和最后一页的链接。

通过以这种方式设计您的端点,您可以获得非常一致的性能特征,并且可以处理不断增长的数据集。

GitHub API 提供了good example of this

【讨论】:

    【解决方案2】:

    我的建议是不要将数据作为 JSON 传递,而是使用 multipart/form-data 作为文件传递。在您的文件中,每一行都可以是表示数据记录的 JSON。然后,很容易使用 FileOutputStream 来接收文件。然后,您可以逐行处理文件以避免内存问题。

    Grails 示例:

        if(params.myFile){
               if(params.myFile instanceof org.springframework.web.multipart.commons.CommonsMultipartFile){
               def fileName = "/tmp/myReceivedFile.txt"
               new FileOutputStream(fileName).leftShift(params.myFile.getInputStream())
           }
           else
               //print or signal error
        }
    

    你可以使用 curl 来传递你的文件:

        curl -F "myFile=@/mySendigFile.txt" http://acme.com/my-service
    

    https://stackoverflow.com/a/13076550/2476435 上有关类似解决方案的更多详细信息

    【讨论】:

      【解决方案3】:

      HTTP 具有分块编码的概念,它允许您以较小的部分发送 HTTP 响应主体,以防止服务器必须将整个响应保存在内存中。您需要了解您的服务器框架如何支持分块编码。

      【讨论】:

        猜你喜欢
        • 2021-07-27
        • 2016-09-16
        • 2020-05-31
        • 2019-04-14
        • 2021-07-17
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        相关资源
        最近更新 更多