阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

133次阅读
没有评论

共计 3019 个字符,预计需要花费 8 分钟才能阅读完成。

云平台中使用的 socket 服务器是我们自己定义一套通信协议,并通过 C# 实现的一个 socket 服务。

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

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

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

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

回收——固定时间间隔(分钟)改为 0

        ——虚拟 / 专用内存限制(KB)改为 0

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

这种方法会禁用 IIS 的进程回收,不过这样可能会导致长时间运行后服务器的性能下降。而且,经过多次尝试这样配置以后,经过很长时间的运行,IIS 还是会对进程进行回收的。

想到 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 服务器。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2015-05/117151.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-20发表,共计3019字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中