长时间运行的AJAX请求在几分钟后重新提交

Long running AJAX request resubmits after a couple of minutes

本文关键字:几分钟 新提交 提交 运行 AJAX 请求 长时间 分钟      更新时间:2023-09-26

我有一个长时间运行的服务调用,我使用jQuery.ajax进行调用。该服务可能需要2分钟以上才能完成。

AJAX请求已提交,不需要任何响应。一个单独的AJAX请求报告操作的进度。

在一些站点上,我们发现代理在2分钟后重新提交Ajax请求。浏览器是Chrome,但我怀疑这是一个与Chrome相关的问题。

这绝对不是我们重新提交ajax请求的情况。为了确保我们设置了一个bool,以防止在beforeSend事件中再次提交。

我现在处理这种重新提交的方式是在数据请求中添加一个nonce,服务在执行操作之前测试该nonce是否已经提交。对该服务的任何第二次调用都将无害地返回,并且原始请求将继续进行。

请注意,我添加了一个毫无意义的服务,它只会等待5分钟,而且我从未遇到过测试服务(在生产站点上)的问题。

有人能告诉我是什么导致了ajax的重新提交,以及如何在本地复制它吗?

这是用于发送请求的js:

var sent = false;
var data = { ... }; // data is a very large object;
$.ajax("service.ashx?loc=area/subarea/", {
    type: "POST",
    data: data,
    traditional: true,
    error: function (jqXHR, textStatus, errorThrown) {
        if (jqXHR.status === 0) {
            // see http://stackoverflow.com/questions/3825581/does-an-http-status-code-of-0-have-any-meaning
        } else {
            ReportFailure(textStatus,errorThrown);
        }
    },
    beforeSend: function () {
        if (sent === true) {
            return false;
        }
        sent = true;
        return true;
    }
});

这是从HTTP存档(HAR)请求的ajax,在那里请求被重新提交,但立即失败。注意2分钟的时间。

{
"startedDateTime": "2015-12-11T12:26:58.018Z",
"time": 120066.61499999973,
"request": {
  "method": "POST",
  "url": "https://example.com/service.ashx?loc=area/subarea/",
  "httpVersion": "HTTP/1.1",
  "headers": [
    ... // removed for brevity
  ],
  "queryString": [
    { "name": "loc", "value": "area/subarea/" }
  ],
  "cookies": [
    ... // removed for brevity
  ],
  "headersSize": 1163,
  "bodySize": 48048,
  "postData": {
    "mimeType": "application/x-www-form-urlencoded; charset=UTF-8",
    "text": ..., // removed for brevity
    "params": [
      ... // removed for brevity        ] }
},
"response": {
  "status": 500,
  "statusText": "Internal Server Error",
  "httpVersion": "HTTP/1.1",
  "headers": [
    {
      "name": "Date",
      "value": "Fri, 11 Dec 2015 12:28:57 GMT"
    },
    ... // removed for brevity
  ],
  "cookies": [],
  "content": {
  "size": 54,
  "mimeType": "text/xml",
  "compression": 0
  },
  "redirectURL": "",
  "headersSize": 305,
  "bodySize": 54,
  "_transferSize": 359
},
"cache": {},
"timings": {
  "blocked": 120005.055999998,
  "dns": -1,
  "connect": -1,
  "send": 1.0939999989932403,
  "wait": 59.986000001008506,
  "receive": 0.47900000172376167,
  "ssl": -1
},
"connection": "7498"

这里也是一样。如果到目前为止客户端还没有收到响应,那么jQuery显然会在120秒(默认超时)后重新发送请求。

增加超时,如:

    $.ajax({
      url: localhost,
      type: 'POST',
      timeout: 1000*60*10

不会改变游戏。尽管客户端继续等待任何响应,但请求在2分钟后仍会重新发送。

尽管服务器端能够很好地并行处理这两个请求,但客户端请求在第一个请求的有效响应时失败。

还没有解决方案

编辑:

事实证明,浏览器是重新发送事件的浏览器,并且行为完全符合HTTP/1.1规范。实际上,(node.js)后端在超时120秒后关闭了套接字,如jonasnas所指出的。解决方案是在响应对象处禁用超时,如:

    // this is a long running request,
    // so disable response timeout
    response.setTimeout(0);

如果请求总是在2分钟内处理,这表明您的服务器端(node.js)没有正确完成响应(使用rsp.end())。2分钟是express/node服务器上的默认超时。

不幸的是,这里的所有其他(浏览器端)建议都不适合我。然而,简单地让ajax请求立即超时就可以了:

这可以通过以下方式实现:

$.ajax("https://someurl/", {
  ...
  timeout:1
  ...
});

附带说明:将超时设置为0无效。

如果服务器端的计算需要很长时间,那么在这里等待是没有意义的。需要一个单独的解决方案来检查计算是否完成。

这种方法看起来很糟糕。因此,任何更好的工作解决方案仍然非常受欢迎;-)

我们的问题是负载均衡器。当我们通过LB url从AJAX调用web api服务时,我们得到了120秒的问题,并重复调用该服务,而客户端没有代表性的额外调用。当我们通过直接服务器节点调用api,从等式中删除负载均衡器时,我们不会遇到这个问题。如果您的等式中包含负载均衡器,请调查直接调用服务器节点是否有效。如果是,请接合负载平衡器支架。

作为一种临时解决方法,在LB问题得到解决之前,我将在页面加载时在一个隐藏字段中向客户端页面返回服务器节点名称,并让我的JS代码使用它来构造一个直接的URL来调用服务。