经过监控线程状态来保证socket服务器的稳定运行

云平台中使用的socket服务器是咱们本身定义一套通讯协议,并经过C#实现的一个socket服务。web

该服务目前是和web服务一块儿运行在IIS容器中,经过启动一个永不退出的新线程来监听端口。数据库

在开发的初期,因为服务内一些消息的异常未进行捕获,例如客户端发来的消息格式不对、试图去关闭一个已经被释放的链接 等操做,会致使监听线程意外退出。服务器

后来随着系统的使用这些问题被一一修复,socket服务就稳定了不少,但是持续一个多周之后,socket服务仍是会偶尔挂掉,查看系统日志没有发现任何系统异常。到网上查了一些关于IIS的资料,发现IIS有一套智能的进程回收机制,目的是为了提升服务器的性能,进程回收时内存中的session、cache以及正在运行的线程都会被清掉,因此采用IIS做为服务器,要保证session、cache等资源长期可用的话,要把他们放到数据库中,或者分布式的放到其余服务器中保存。进程回收后,IIS会启动新的线程,原来部署在IIS中站点的端口都会被从新监听,可是以前用户本身启动的那些线程IIS就不会给启动了。session

网上有人给出一种解决方案,对IIS7进行配置:socket

 

回收——固定时间间隔(分钟) 改成 0分布式

        ——虚拟/专用内存限制(KB) 改成 0性能

进程模型——闲置超时(分钟) 改成 0ui

 

这种方法会禁用IIS的进程回收,不过这样可能会致使长时间运行后服务器的性能降低。并且,通过屡次尝试这样配置之后,通过很长时间的运行,IIS仍是会对进程进行回收的。spa

 

想到IIS在进程回收以后会重启本身对运行在其上的站点的端口监听,咱们本身也能够运行一个服务,来判断socket服务器的线程当前运行状态是否正常,若是不正常的话就重启服务。这个服务必须是运行在IIS以外的。线程

具体作法是:

web服务提供一个获取进程状态的接口 

/SocketServer.ashx?action=getThreadStatus

提供一个重启socket服务的接口

/SocketServer.ashx?action=startSocketServer

 

在IIS外部经过其余方法启动一个服务,每隔10秒访问一次获取进程状态的接口,若是不正常则调用重启socket服务的接口。

如今的作法是启动了一个Nodejs服务:

 

//此服务用来监控云平台的socket服务进程,若进程崩溃或重启,则从新启动socket服务、ws服务、任务超时检测
var http=require('http');
var moment = require('moment')
//var host="http://xxx"; //本地调试
var host="http://xxxxxx"; //内网服务
//var host="http://xxxx";//公网服务
var statusCheck="xxx";
var startSocket= "xxx" ;
var startWs= "xxx"  ;
var taskTimeout=  "xxx";
var inteval;
function start() {
    inteval = setInterval(checkStatus, 20000);
}
function end() {
    clearInterval(inteval);
}
start();
function checkStatus() {
    try {
        http.get(host + statusCheck, function (res) {
            res.on('data', function (data) {
                var socketStatus = JSON.parse(data.toString());
                if (socketStatus.socketServer == '挂了' || socketStatus.socketServer == 'Stopped') {
                    console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + "   socket服务不可用,正在重启")
                    //重启服务
                    restartService();
                }
            })
        }).on('error', function (e) {
            console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + "错误:" + e.message);
        });
    }
    catch (e) {
        console.log(e.message);
    }
}
function restartService() {
    //end();
    http.get(host + startSocket, function (res) {
        statusCode(res.statusCode, 'startSocket');
        console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + "   重启socketserver" + res.statusCode);
        res.resume();
    });
    http.get(host + startWs, function (res) {
        statusCode(res.statusCode, 'startWs');
        console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + "   重启wsserver" + res.statusCode);
        res.resume();
    });
    http.get(host + taskTimeout, function (res) {
        statusCode(res.statusCode, 'taskTimeout');
        console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + "   重启任务状态监控" + res.statusCode);
        res.resume();
    });
    var status = { startSocket: false, startWs: false, taskTimeout: false };
    function statusCode(code, name) {
        if (code == 200) {
            status[name] = true;
        }
        if (status.startSocket && status.startWs && status.taskTimeout) {
            //start();
        }
    }
}

 

 

这种作法目前有两个弊端:

 

1.每次IIS进程回收的时候,socket服务都会有几秒钟的时间不可用

2.socket服务运行在web服务器内,不利于之后web服务器或者socket服务器的扩展,链接到A服务器的设备没法被B服务器访问

 

之后的改进方向是:

把socket服务器独立出来,从新设计Web服务器与socket服务器的通讯方法。

这样可使socket服务不会受到IIS服务器配置的影响,并且能够随意扩展web服务器与socket服务器。

相关文章
相关标签/搜索