2

我的网站上有一个基本的聊天框模块,它通过 Jquery Ajax 调用每 3 秒更新一次聊天框,再加上另一个用于发送新消息的 jquery 调用。没有什么花哨。通常每个 jquery ajax 请求只需要 0.2 秒。但是在服务器上,当连接 20 多人时,服务器 CPU 变得非常高,每个 ajax 请求开始需要 12-14 秒,这是不可接受的。而且每个 httpd 进程也消耗 3% - 4% 的 CPU。

更新聊天框代码:

updatechatbox = $.getJSON("/chat/update",{ lastid: $("#messageBox li:last-child").attr("id") }, function(json) {
    $.each(json, function(key, val) {
        var m = val['message'];
        var id = val['id'];
        var messagebox = $("#messageBox ul");
        messagebox.append("<li id="+id+"><span class='msg'>"+m+"</span></li>");

        var myDiv = $("#messageBox");
        myDiv.animate({ scrollTop: myDiv.prop("scrollHeight") - myDiv.height() }, 0);
    });
});

服务器是 Fedora 15,运行 nginx 作为代理和 apache 用于 Web 服务,配置如下:


Timeout 120
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

IfModule prefork.c
  StartServers       8
  MinSpareServers    5
  MaxSpareServers   20
  ServerLimit      256
  MaxClients       256
  MaxRequestsPerChild  400
IfModule

IfModule worker.c
  StartServers         2
  MaxClients         150
  MinSpareThreads     25
  MaxSpareThreads     75
  ThreadsPerChild     25
  MaxRequestsPerChild  0
IfModule

问题:
- apache 为每个 httpd 进程使用那么多 CPU 是否正常?
- 我怎样才能解决这个问题?

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20089 apache    20   0 57524  16m 5840 S  7.3  0.8   0:18.16 httpd
19715 apache    20   0 56828  16m 5852 S  6.6  0.8   0:21.58 httpd
19749 apache    20   0 58536  16m 5864 S  6.6  0.8   0:22.29 httpd
19732 apache    20   0 62880  21m 5856 S  5.6  1.0   0:19.14 httpd
19803 apache    20   0 62076  21m 5840 S  5.3  1.1   0:17.94 httpd
19821 apache    20   0 61856  21m 5828 S  5.0  1.0   0:17.81 httpd
21574 apache    20   0 61584  18m 4664 S  3.3  0.9   0:00.69 httpd
19772 apache    20   0 61856  21m 5864 S  2.6  1.1   0:18.53 httpd
19932 apache    20   0 61856  20m 5844 S  2.6  1.0   0:17.07 httpd
14307 mysql     20   0  306m  52m 4576 S  2.3  2.6  81:32.57 mysqld
13175 nginx     20   0 15532 2284 1032 S  0.3  0.1   0:04.61 nginx

编辑:我的 PHP 更新功能。使用 Zend Framework v1.11.11

public function updateAction()
{
    $auth = Zend_Auth::getInstance();
    $user_info = $auth->getStorage()->read();
    $adminsess = new Zend_Session_Namespace("admin");
    $referrer = $_SERVER['HTTP_REFERER'];

    $user_id = $user_info->id;

    $query = "SELECT m.id, m.message, m.user_id
              FROM messagebox m
              LEFT JOIN users u ON m.user_id = u.id";

    if(isset($_GET['lastid']) && $_GET['lastid'] != ""){
        $lastId = $_GET['lastid'];
        $query .= "WHERE m.id > $lastId";
    }

    $r = $db->query($query);
    $result = $r->fetchAll();

    $data = array();

    if(count($result) > 0) {
        foreach($result as $row) {
            $data[$row['id']]['id'] = $row['id'];
            $data[$row['id']]['message'] = $row['message'];
            $data[$row['id']]['user_id'] = $user_id;
        }
    }

    echo json_encode($data);
    $this->_helper->layout->disableLayout();
}
4

1 回答 1

2

我之前遇到过类似的问题,结果证明与会话锁定有关。当启动会话的 PHP 脚本打开会话时,该会话文件被锁定。这意味着如果您的网页向 PHP 脚本发出大量请求,例如,通过 Ajax 加载内容,每个请求都可能锁定会话并阻止其他请求完成。这在此处进行了详细描述。

因此,您需要执行以下操作:

session_write_close();

如果这不是原因,请检查您没有做任何计算密集型的事情,比如大 SQL 调用大量递归等。

于 2012-06-22T16:04:54.807 回答