私が持っている 1 つの Web サイトは、もともと PHP で作成されていました。ユーザーが Web サイトで特定のクエリを実行するたびに、別の Web サイトに対して Web POST 要求を実行します。
function post_request($url, $data, $referer='') {
$data = http_build_query($data);
$url = parse_url($url);
if ($url['scheme'] != 'http') {
die('Error: Only HTTP request are supported !');
}
// extract host and path:
$host = $url['host'];
$path = $url['path'];
// open a socket connection on port 80 - timeout: 7 sec
$fp = fsockopen($host, 80, $errno, $errstr, 7);
if ($fp){
// Set non-blocking mode
stream_set_blocking($fp, 0);
// send the request headers:
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "User-Agent: Mozilla/5.0 Firefox/3.6.12\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
// receive the results of the request
$result .= fgets($fp, 128);
}
// close the socket connection:
fclose($fp);
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
// split the result header from the content
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
// return as structured array:
return array(
'status' => 'ok',
'header' => $header,
'content' => $content
);
}
このアプローチは問題なく機能します。唯一の問題は、上記のコードで 100 人の同時ユーザーをサポートするのにほぼ 3 つの CPU が必要なことです。
これを行うには Node.js が適していると考えて (Web 要求は非同期になります)、次のようにしました。CPU 要件に関しては、明確な改善がありました (ほとんどの場合、1 つの CPU で動作し、多くても 2 つです)。
function postPage(postPath, postData, postReferal, onReply, out) {
var post_options = {
host: 'www.somehost.com',
port: '80',
path: postPath,
method: 'POST',
headers: {
'Referer': postReferal,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length,
'User-Agent': 'Mozilla/5.0 Firefox/3.6.12',
'Connection': 'close'
}
};
// create request
var post_req = http.request(post_options, function (res) {
var reply = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
reply += chunk;
});
res.on('end', function () {
onReply(reply, out);
});
res.on('error', function (err) {
out.writeHead(500, { 'Content-Type': 'text/html' });
out.end('Error');
});
});
// post the data
post_req.write(postData);
post_req.end();
}
この場合の問題は、非常に壊れやすく、Web 要求の約 20% が失敗することです。ユーザーがクエリを再試行すると機能しますが、良いエクスペリエンスではありません。
Windows Azure Web サイトを使用して、上記の両方のソリューションをホストしています。
さて、質問
- これにPHPを使用すると、それだけ多くのリソースが必要になると予想されますか、それとも私のコードが最適ではないためですか?
- 非常に多くのリクエストが失敗するのは、私のノード コード (または Azure) の何が問題なのですか?