【问题标题】:Server saturation with Ajax callsAjax 调用导致服务器饱和
【发布时间】:2015-09-24 12:15:44
【问题描述】:

我在 Windows Server 2008 上通过 IIS 7.5 使用 PHP。

我的 Web 应用程序在后台使用 Ajax 反复请求 3 个不同的 JSON 页面:

  • 每 6 秒第 1 页
  • 第 2 页每 30 秒一次
  • 每 60 秒第 3 页

它们检索与某些表的当前状态相关的数据。这样我就可以保持视图更新。

通常我对此没有太大问题,但最近我看到我的服务器充满了数百个未响应的请求,我相信问题可能是由于其中一个请求的延迟造成的。

如果每 6 秒请求一次的 page1 需要 45 秒来响应(由于数据库查询速度慢或其他原因),那么在我看来,请求开始一个接一个地堆积起来。 如果我有多个用户同时(或使用多个选项卡)连接到 Web 应用程序,事情可能会变得很糟糕。

关于如何避免此类问题的任何建议?

我正在考虑使用诸如 ZMQSockets.io in the client side 之类的东西,但由于我请求的数据不会从任何用户操作中触发,我不知道如何触发它服务器端。

【问题讨论】:

  • 让请求不需要 45 秒?还是不要每 6 秒请求一次?
  • @DarkFalcon 通常不需要 45 秒,但有时会。我正在寻求一种方法来解决这个问题。
  • 我认为用 sockets.io 实现它是个好主意。类似的东西甚至使用 SO 来动态更新问题/答案投票/cmets
  • @MateiMihai 但是什么会触发来自服务器端的消息?
  • 如果请求没有返回,就不要再发送了。但是修复服务器端代码并​​加快速度。

标签: javascript php ajax socket.io zeromq


【解决方案1】:

我正在考虑在客户端使用诸如 ZMQ 和 Sockets.io 之类的东西......

这几乎绝对是长时间运行请求的最佳选择。

...但是由于我请求的数据不会被任何用户操作触发,我看不出如何从服务器端触发。

在这种情况下,有问题的“用户操作”是连接到 socket.io 服务器。此简化示例取自socket.io getting started 文档之一:

var io = require('socket.io')(http);

io.on('connection', function(socket) {
  console.log('a user connected');
});

当 'connection' 事件被触发时,您可以开始在您的 ZMQ 消息队列上侦听消息。如有必要,您还可以启动长时间运行的查询。

【讨论】:

  • 感谢您的回答,但我不太确定您所说的是否明白。我需要每 6 秒更新一次用户视图,对吗?视图如何从服务器端获取更新?必须在此处进行推送的是服务器端。
  • Websockets 的行为与正常的 HTTP 请求不同,因为消息可以在任一方向发送,而不仅仅是浏览器->服务器->浏览器。首先,您从浏览器连接到 websocket 服务器,这会触发 connection 事件。从那时起,您的服务器可以直接向浏览器发送更新消息,而无需浏览器发起任何进一步的请求。
  • 我知道套接字是如何工作的。你不理解我的问题。这是 PHP,不是 javascript。我不能让一个进程运行 setInterval 函数来不时推送通知。必须有一些东西来推动客户。那就是我遇到了麻烦。
  • 抱歉,我完全没看清问题​​的第一行!
【解决方案2】:

我最终按照@epascarello 的建议解决了这个问题,如果我在 X 时间内没有得到响应,我会稍微改进一下。

如果请求没有返回,请不要发送另一个请求。但是修复服务器端代码并​​加快速度。

基本上我做了如下的事情:

var ELAPSED_TIME_LIMIT = 5; //5 minutes
var responseAnswered = true;
var prevTime = new Date().getTime();

setInterval(function(){
    //if it was answered or more than X m inutes passed since the last call
    if(responseAnsswered &&  elapsedTime() > ELAPSED_TIME_LIMIT){
        getData()
        updateElapsedTime();
    }
}, 6000);

function getData(){
    responseAnswered = false;
    $.post("http://whatever.com/action.json", function(result){
        responseAnswered = true
    });
}

//Returns the elapsed time since the last time prevTime was update for the given element.
function elapsedTime(){
    var curTime = new Date().getTime();

    //time difference between the last scroll and the current one
    var timeDiff = curTime - prevTime;

    //time in minutes
    return (timeDiff / 1000) / 60;
}

//updates the prevTime with the current time
function updateElapsedTime(){
    prevTime = new Date().getTime();
}

【讨论】:

    【解决方案3】:

    这是一个非常糟糕的设置。如果可能,您应该始终避免轮询。不是每 6 秒从客户端向服务器发送一次请求,而是从服务器向客户端发送数据。您应该在服务器端检查数据是否有任何变化,然后使用 websockets 将数据传输到客户端。你可以在服务器端使用nodejs来监控数据的任何变化。

    【讨论】:

    • 我知道我可以使用节点,但事实是 Web 应用程序使用的是 PHP,我无法更改它。除此之外,node 与 Oracle DB 和 PLSQL 过程的集成并不完美。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多