xampp 在同时发出许多 API 请求时崩溃

xampp crashes when many simultaneous API requests are made

我正在制作一个应用程序,它使用 Twitter API 接收用户的推文,其中一个组件是从推文文本中提取情感。对于开发,我使用 xampp,当然使用 Apache HTML 服务器作为我的工作区。我将 Eclipse 用于 PHP 作为 IDE.

对于情感提取,我使用 uClassify Sentiment Classifier。分类器使用 API 来接收大量请求,并针对每个请求发送回 XML 数据,从中可以解析情绪值。

现在应用程序可以一次处理大量推文(最多允许 3200 条)。例如,如果有 3200 条推文,那么系统将立即向该分类器发送 3200 API 次调用。不幸的是,对于这个数字,系统不能很好地扩展,实际上 xampp 在 运行 系统进行这些调用后不久就崩溃了。但是,对于少量的推文(例如 500 条推文),系统工作正常,所以我假设这可能是由于大量 API 调用。 uClassify 每天允许的 API 调用的最大次数是 5000,但由于最大值是 3200,我很确定它不会超过这个数字,这可能会有所帮助。

这几乎是我第一次从事此类 Web 开发,所以我不确定我是否犯了新手错误。我不确定我可能做错了什么,也不知道从哪里开始寻找。任何 advice/insight 都会有很大帮助!

编辑:添加了有问题的源代码

更新索引方法

function updateIndex($timeline, $connection, $user_handle, $json_index, $most_recent) {
    // URL arrays for uClassify API calls
    $urls = [ ];
    $urls_id = [ ];

    // halt if no more new tweets are found
    $halt = false;
    // set to 1 to skip first tweet after 1st batch
    $j = 0;
    // count number of new tweets indexed
    $count = 0;
    while ( (count ( $timeline ) != 1 || $j == 0) && $halt == false ) {
        $no_of_tweets_in_batch = 0;
        $n = $j;
        while ( ($n < count ( $timeline )) && $halt == false ) {
            $tweet_id = $timeline [$n]->id_str;
            if ($tweet_id > $most_recent) {
                $text = $timeline [$n]->text;
                $tokens = parseTweet ( $text );
                $coord = extractLocation ( $timeline, $n );
                addSentimentURL ( $text, $tweet_id, $urls, $urls_id );
                $keywords = makeEntry ( $tokens, $tweet_id, $coord, $text );
                foreach ( $keywords as $type ) {
                    $json_index [] = $type;
                }
                $n ++;
                $no_of_tweets_in_batch ++;
            } else {
                $halt = true;
            }
        }
        if ($halt == false) {
            $tweet_id = $timeline [$n - 1]->id_str;

            $timeline = $connection->get ( 'statuses/user_timeline', array (
                    'screen_name' => $user_handle,
                    'count' => 200,
                    'max_id' => $tweet_id 
            ) );
            // skip 1st tweet after 1st batch
            $j = 1;
        }
        $count += $no_of_tweets_in_batch;
    }

    $json_index = extractSentiments ( $urls, $urls_id, $json_index );

    echo 'Number of tweets indexed: ' . ($count);
    return $json_index;
}

提取情感方法

function extractSentiments($urls, $urls_id, &$json_index) {
    $responses = multiHandle ( $urls );
    // add sentiments to all index entries
    foreach ( $json_index as $i => $term ) {
        $tweet_id = $term ['tweet_id'];
        foreach ( $urls_id as $j => $id ) {
            if ($tweet_id == $id) {
                $sentiment = parseSentiment ( $responses [$j] );
                $json_index [$i] ['sentiment'] = $sentiment;
            }
        }
    }
    return $json_index;
}

处理多个API调用的方法

这是立即处理 uClassify API 调用的地方:

function multiHandle($urls) {

    // curl handles
    $curls = array ();

    // results returned in xml
    $xml = array ();

    // init multi handle
    $mh = curl_multi_init ();

    foreach ( $urls as $i => $d ) {
        // init curl handle
        $curls [$i] = curl_init ();

        $url = (is_array ( $d ) && ! empty ( $d ['url'] )) ? $d ['url'] : $d;

        // set url to curl handle
        curl_setopt ( $curls [$i], CURLOPT_URL, $url );

        // on success, return actual result rather than true
        curl_setopt ( $curls [$i], CURLOPT_RETURNTRANSFER, 1 );

        // add curl handle to multi handle
        curl_multi_add_handle ( $mh, $curls [$i] );
    }

    // execute the handles
    $active = null;
    do {
        curl_multi_exec ( $mh, $active );
    } while ( $active > 0 );

    // get xml and flush handles
    foreach ( $curls as $i => $ch ) {
        $xml [$i] = curl_multi_getcontent ( $ch );
        curl_multi_remove_handle ( $mh, $ch );
    }

    // close multi handle
    curl_multi_close ( $mh );

    return $xml;
}

问题是一次性给 curl 太多 URL。我很惊讶你可以并行管理 500 个,因为我看到人们抱怨即使是 200 个也有问题。This guy has some clever code 一次只处理 100 个,但每次完成后添加下一个,但我注意到他将其编辑为一次只做 5 个。

我刚刚注意到该代码的作者围绕这个想法发布了一个开源库,所以我认为这是适合您的解决方案:https://github.com/joshfraser/rolling-curl

至于为什么会发生崩溃,对此问题的评论表明原因可能是达到 OS 文件句柄的最大数量:What is the maximum number of cURL connections set by? 和其他建议只是使用了很多带宽、CPU 和内存。 (如果你在 windows,打开任务管理器应该可以让你看看是否是这种情况;在 linux 使用 top