云平台中使用的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服务器。

通过监控线程状态来保证socket服务器的稳定运行的更多相关文章

  1. MegaCli 监控raid状态 限戴尔服务器

    MegaCli 监控raid状态 MegaCli是一款管理维护硬件RAID软件,可以通过它来了解当前raid卡的所有信息,包括 raid卡的型号,raid的阵列类型,raid 上各磁盘状态,等等.通常 ...

  2. 使用pm2来保证Spring Boot应用稳定运行

    Spring Boot开发web应用就像开发普通的java程序一般简洁,因为其内嵌了web容易,启动的时候只需要一条命令java -jar server.jar即可,非常方便.但是由此而来的问题是万一 ...

  3. Java--FutureTask原理与使用(FutureTask可以被Thread执行,可以被线程池submit方法执行,并且可以监控线程与获取返回值)

    package com; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; i ...

  4. 通过线程监控socket服务器是否done机

    现实中的socket可能会因为各种原因done机,但这么重要的服务器怎么能允许这种事情发生?这次我们就来通过一个线程去监控socket服务器,如果done机重新将其启动. 下面是监控项目和socket ...

  5. 可扩展多线程异步Socket服务器框架EMTASS 2.0 续

    转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...

  6. C#使用Socket实现一个socket服务器与多个socket客户端通信

    在分布式调度系统中,如果要实现调度服务器与多台计算节点服务器之间通信,采用socket来实现是一种实现方式,当然我们也可以通过数据存储任务,子节点来完成任务,但是往往使用数据作为任务存储都需要定制开发 ...

  7. c#Socket服务器与客户端的开发(1)

    上个项目中用到了Socket通讯,项目中直接借助SuperSocket实现,但是我觉得这毕竟是一个我没接触过的东西,所以也顺便学习了一下原生socket的使用,做了一个socket服务器与客户端的开发 ...

  8. 【RL-TCPnet网络教程】第19章 RL-TCPnet之BSD Socket服务器

    第19章      RL-TCPnet之BSD Socket服务器 本章节为大家讲解RL-TCPnet的BSD Socket,学习本章节前,务必要优先学习第18章的Socket基础知识.有了这些基础知 ...

  9. 可扩展多线程异步Socket服务器框架EMTASS 2.0

    0 前言 >>[前言].[第1节].[第2节].[第3节].[第4节].[第5节].[第6节] 在程序设计与实际应用中,Socket数据包接收服务器够得上一个经典问题了:需要计算机与网络编 ...

随机推荐

  1. touches 事件捕获不到

    在UIView上加载了一个UIScrollView(全屏),touches 事件捕获不到了 原因:UIView的touch事件被UIScrollView捕获了,无法传递下去 解决方法:写一个UIScr ...

  2. web常见错误提示总结

    在写web程序的时候,经常会出现一些网页错误的数字提示,如果能够明白这些提示的含义,那对于调试程序是有极大帮助的.网上有很多这方面的总结,但为了适应自己的阅读习惯,以及日后的查找方便,就做了一些修改并 ...

  3. Codeforces Round #361 (Div. 2) C

    C - Mike and Chocolate Thieves Description Bad news came to Mike's village, some thieves stole a bun ...

  4. 有关于canvas几个新知识点

    对于canvas的初学者来说,以下几点应该是不知道的知识点: 1.canvas有兼容IE6/7/8的脚本文件 下载地址:https://github.com/arv/explorercanvas 2. ...

  5. CoolPlist 帧动画自动生成工具

    工具英文名称:CoolPlist作者: 陈前帆 thinkingMan | sonny 邮箱: 625936034@qq.com | chenqianfan1@163.com电话: 136704713 ...

  6. CSS基础篇之选择符3

    border(边框) 如何用CSS调出边框 我们给p标签加一个边框试一下 p{ border:1px solid #ccc:/*这是缩写*/ } 第一个值是为边框的宽度 第二个值是为边框线样式为直线 ...

  7. 使用EF取数据库返回的数据

    目录 一.取oracle自定义函数返回的自定义类型. 一.取oracle自定义函数返回的自定义类型. 1.首先创建一个函数返回自定义类型集合 --1.建立自定义类型 CREATE OR REPLACE ...

  8. Scala 笔记

    环境 1. Intellij Idea 2. Scala 插件 3. http://scala-lang.org/ 教程: idea官方教程: https://www.jetbrains.com/he ...

  9. Nova PhoneGap框架 第七章 设备事件处理

    我们的框架包含了几种设备事件的处理,目的是为了让我们的程序员更容易的完成代码.这些事件包括:回退键(Android)和横竖屏切换事件. 7.1 Android回退键 首先来说说回退键的事件处理.当用户 ...

  10. CCLuaLoadChunksFromZIP加载后的require路径问题

    对于require来说,在LUA中的机制就是搜索path路径了.但对于CCLuaLoadChunksFromZIP加载的LUA文件来说,require的路径又是怎么样的呢? 我在服务器上有一个 oox ...