Javascript 通过http远程实时监视/控制服务器的正确方法
在我的客户端(带浏览器的手机)上,我想查看服务器CPU、RAM和HDD的状态,并从各种日志中收集信息 我正在使用ajax轮询 在客户端上,每5秒(setInterval)调用一个PHP文件:Javascript 通过http远程实时监视/控制服务器的正确方法,javascript,php,ajax,node.js,Javascript,Php,Ajax,Node.js,在我的客户端(带浏览器的手机)上,我想查看服务器CPU、RAM和HDD的状态,并从各种日志中收集信息 我正在使用ajax轮询 在客户端上,每5秒(setInterval)调用一个PHP文件: 扫描包含N个日志的文件夹 读取每个日志的最后一行 将其转换为JSON 问题: 每5秒打开一次新连接 多个AJAX调用 请求头(它们也是数据,因此会占用带宽) 响应头(^) 使用PHP每5秒读取一次文件。即使一切都没有改变 最后的JSON数据小于5 KB,但我每5秒发送一次,每次都有头文件和新连接,所以基本上
60秒/5秒=12
每分钟新连接数,如果我保持应用程序打开,每小时流量约为15 MB
假设我有100个用户,我让他们监视/控制我的服务器,一小时内大约有1.5 GB的传出流量
更不用说PHP服务器每5秒读取多个文件100次
我需要在服务器上每隔5秒读取这些日志的最后几行,并可能将它们写入文件,然后我只想在更改后将这些数据推送到客户端。
SSE(服务器发送事件)和PHP
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true){
echo "id: ".time()."\ndata: ".ReadTheLogs()."\n\n";
ob_flush();
flush();
sleep(1);
}
在这种情况下,在与第一个用户建立连接之后
连接保持打开状态(PHP不是为此而设计的),因此我节省了一些空间(请求头、响应头)。这项工作在我的服务器上,但大多数服务器不允许长时间保持连接打开
同时,对于多个用户,我会多次读取日志(降低旧服务器的速度)
我无法控制服务器。。。我需要使用ajax来发送命令
我需要网袋
node.js和WebSocket 据我所知,使用node.js,我可以在不消耗大量资源的情况下完成所有这些工作 资源和班德维奇。连接保持打开,因此没有不必要的头,我可以接收和发送数据。它可以很好地处理多个用户 这就是我需要你帮助的地方。
这是我发现并修改的第一个示例
var ws=require("nodejs-websocket");
var server=ws.createServer(function(conn){
var data=read(whereToStoreTheLogs);
conn.sendText(data)// send the logs data to the user
//on first connection.
setTimeout(checkLogs,5000);
/*
here i need to continuosly check if the logs are changed.
but if i use setInterval(checkLogs,5000) or setTimeout
every user invokes a new timer and so having lots of timers on the server
can i do that in background?
*/
conn.on("text",function(str){
doStuff(str); // various commands to control the server.
})
conn.on("close",function(code,reason){
console.log("Connection closed")
})
}).listen(8001);
var checkLogs=function(){
var data=read(whereToStoreTheLogs);
if(data!=oldData){
conn.sendText(data)
}
setTimeout(checkLogs,5000);
}
上面的脚本将是通知服务器,但我还需要找到一个解决方案来存储这些多个日志的信息,并在每次更改某些内容时在后台执行此操作
您将如何保持bandwich较低,同时也保持服务器资源
你会怎么做?
编辑
顺便问一下,有没有一种方法可以同时将这些数据传输到所有客户机上
编辑
关于日志:我还希望能够缩放更新之间的时间扩展。。。我的意思是如果我阅读ffmpeg的日志,我会在可能的情况下每秒钟更新一次。。。但当没有转换处于活动状态时。。我需要每5分钟获取一次基本的机器信息,也许。。。等等
目标:
1.执行读取和存储日志数据的方法(仅当clinets连接…[mysql,文件,可以将此信息存储在ram中(使用node.js??))。
2.将数据流传输到各种客户端(同时)的性能方法。
3.能够向服务器发送命令。。(双向)
4.使用web语言(js、php…)和lunix命令(易于在多台机器上实现)。。如果需要,免费软件
最好的办法是:
根据当前活动,将日志读到系统内存,并通过已打开的连接将流同时连续地,读到带有WebSocket的各种客户端
我不知道还有什么比这更快的
更新
node.js服务器已经启动并运行,使用的是webSocketServer实现,因为它似乎是最快的实现。
我在@HeadCode的帮助下编写了以下代码,以正确处理客户情况&尽可能降低流程。检查广播回路中的各种内容。现在推送和客户处理处于一个良好的状态
var
wss=new (require('ws').Server)({port:8080}),
isBusy,
logs,
clients,
i,
checkLogs=function(){
if(wss.clients&&(clients=wss.clients.length)){
isBusy||(logs=readLogs()/*,isBusy=true*/);
if(logs){
i=0;
while(i<clients){
wss.clients[i++].send(logs)
}
}
}
};
setInterval(checkLogs,2000);
var
wss=new(require('ws').Server)({port:8080}),
我很忙,
日志,
客户,
我
checkLogs=函数(){
if(wss.clients&(clients=wss.clients.length)){
isBusy | |(logs=readLogs()/*,isBusy=true*/);
如果(日志){
i=0;
while(inodejs)输出实现
linux文件系统api
请记住,我需要扫描各个文件夹中的日志,然后以某种方式解析输出的数据,并且每2秒进行一次
注:如果日志读取系统是异步的,我将isBusy添加到服务器变量中
编辑
答案不完整。
缺失:
一种读取、解析和存储日志的高效方法(linux文件系统api或nodejs api,因此我将日志直接存储到系统内存中)
如果可以直接将数据流传输给多个用户,则说明。
显然,nodejs通过客户端循环,因此(我认为)发送了多次数据
顺便说一句,如果没有客户端,是否有可能/值得关闭节点服务器并在apache端重新启动新连接。(例如:如果我连接到apache托管的html文件,脚本将再次启动nodejs服务器)。这样做
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res){
res.sendfile('index.html');
});
io.on('connection', function(socket){
// This is where we should emit the cached values of everything
// that has been collected so far so this user doesn't have to
// wait for a changed value on the monitored host to see
// what is going on.
// This code is based on something I wrote for myself so it's not
// going to do anything for you as is. You'll have to implement
// your own caching mechanism.
for (var stat in cache) {
if (cache.hasOwnProperty(stat)) {
socket.emit('data', JSON.stringify(cache[stat]));
}
}
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
(function checkLogs(){
var data=read(whereToStoreTheLogs);
if(data!=oldData){
io.emit(data)
}
setTimeout(checkLogs,5000);
})();
<script src="/path/to/socket.io.js"></script>
<script>
// Set up the websocket for receiving updates from the server
var socket = io();
socket.on('data', function(msg){
// Do something with your message here, such as using javascript
// to display it in an appropriate spot on the page.
document.getElementById("content").innerHTML = msg;
});
</script>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>WS example</title>
</head>
<body>
<script>
var connection;
window.addEventListener("load", function () {
connection = new WebSocket("ws://"+window.location.hostname+":8001")
connection.onopen = function () {
console.log("Connection opened")
}
connection.onclose = function () {
console.log("Connection closed")
}
connection.onerror = function () {
console.error("Connection error")
}
connection.onmessage = function (event) {
var div = document.createElement("div")
div.textContent = event.data
document.body.appendChild(div)
}
});
</script>
</body>
</html>
var ws = require("nodejs-websocket")
var os = require('os');
Tail = require('tail').Tail;
tail = new Tail('./testlog.txt');
var server = ws.createServer(function (conn) {
conn.on("text", function (str) {
console.log("Received " + str);
});
conn.on("close", function (code, reason) {
console.log("Connection closed");
});
}).listen(8001);
setInterval(function(){ checkLoad(); }, 5000);
function broadcast(mesg) {
server.connections.forEach(function (conn) {
conn.sendText(mesg)
})
}
var load = '';
function checkLoad(){
var new_load = os.loadavg().toString();
if (new_load === 'load'){
return;
}
load = new_load;
broadcast(load);
}
tail.on("line", function(data) {
broadcast(data);
});