我开始这个项目是为了我的实时股价更新项目。
当我处理一两只股票时,这个项目效果很好,但当我想同时更新数百只股票的价格时,就不行了。我想知道我这样做是否正确。现在,我在服务器上的for
循环中获取所有股票的数据,但价格更新非常非常慢。我想知道如何改进这一点。
我想知道如何在不影响服务器性能的情况下每秒更新数百个股票价格。
我不知道我是否应该从客户端向服务器发送我需要的股票列表,比如:var ids = [ '', '', '', ... ]
,或者我是否可以从服务器本身运行这些id。
哪个是最好的:从客户端到服务器的股票请求,还是从服务器到客户端的股票请求?
注意:我将使用不同的url来获取股票价格
我的服务器端代码:
////
// CONFIGURATION SETTINGS
///
var PORT = 4000;
var FETCH_INTERVAL = 5000;
var PRETTY_PRINT_JSON = true;
///
// START OF APPLICATION
///
var express = require('express');
var http = require('http');
var io = require('socket.io');
var app = express();
var server = http.createServer(app);
var io = io.listen(server);
io.set('log level', 1);
server.listen(PORT);
var ticker = "";
app.get('/:ticker', function(req, res) {
ticker = req.params.ticker;
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket) {
var local_ticker = ticker;
ticker = "";
//Run the first time immediately
get_quote(socket, local_ticker);
//Every N seconds
var timer = setInterval(function() {
var ids = ['AAPL', '' , ..........100 stocks];
var l = ids.length;
for(var i=0; i<l; i++){
get_quote(socket, ids[i])
}
}, FETCH_INTERVAL);
socket.on('disconnect', function () {
clearInterval(timer);
});
});
function get_quote(p_socket, p_ticker) {
http.get({
host: 'www.google.com',
port: 80,
path: '/finance/info?client=ig&q=' + p_ticker
}, function(response) {
response.setEncoding('utf8');
var data = "";
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function() {
if(data.length > 0) {
try {
var data_object = JSON.parse(data.substring(3));
} catch(e) {
return;
}
var quote = {};
quote.ticker = data_object[0].t;
quote.exchange = data_object[0].e;
quote.price = data_object[0].l_cur;
quote.change = data_object[0].c;
quote.change_percent = data_object[0].cp;
quote.last_trade_time = data_object[0].lt;
quote.dividend = data_object[0].div;
quote.yield = data_object[0].yld;
p_socket.emit('quote', PRETTY_PRINT_JSON ? JSON.stringify(quote, true, 't') : JSON.stringify(quote));
}
});
});
}
我的客户端代码:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script type="text/javascript" src="http://localhost:4000/socket.io/socket.io.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect("http://localhost:4000");
socket.on('quote', function(data) {
var data = $("<pre>" + data + "</pre><hr />");
$("#quotes").append(data);
$("html, body").animate({ scrollTop: $(document).height() }, 100);
$(data).show("slide", { direction: "up" }, 250);
$(data).effect("highlight", {}, 1500);
});
});
</script>
<body>
<div id="quotes"></div>
</body>
我认为从客户端发送所需的ID将使您的应用程序更加灵活和易于使用。您仍然可以以一种高性能的方式编写服务器。
"For循环"将阻止节点的事件循环。对于需要在数组上迭代的异步操作,我建议:
https://github.com/caolan/async
特别是"异步每个"
我还没有运行你的代码,但我的直觉告诉我,我的浏览器不会一次喜欢那么多的DOM操作。我认为把小组分成更小的部分会有所帮助。例如:
把你的ID数组分成5个。然后错开每个的间隔。
var arr1 = [...]
var arr2 = [...]
var arr3 = [...]
var arr4 = [...]
var arr5 = [...]
setTimeout(doWorkOnArray(arr1), 4000)
setTimeout(doWorkOnArray(arr2), 3000)
setTimeout(doWorkOnArray(arr3), 2000)
setTimeout(doWorkOnArray(arr4), 1000)
setTimeout(doWorkOnArray(arr5), 0)
function doWorkOnArray(arr) {
setInterval(getData(arr), 5000)
}
或者,你可以考虑用Redis之类的东西设置一个Master/Worker来对工作进行排队。我认为这将是最好的表演。结账:
https://github.com/Automattic/kue