配色: 字号:
基于SignalR实现windows服务运行状态的监测
2016-09-20 | 阅:  转:  |  分享 
  
基于SignalR实现windows服务运行状态的监测
通常来讲一个BS项目肯定不止单独的一个BS应用,可能涉及到很多后台服务来支持BS的运行,特别是针对耗时较长的某些任务来说,Windows服务肯定是必不可少的,我们还需要利用B/S与windows服务进行交互,来实现更好的用户体验,搭配redis,memcached等来实现分布式缓存,消息列队处理等等。。。

但是通常情况我们在B/S端是无法得知其依赖的windows服务当前处于什么样的运行状态,只能通过到server里面去进行查看,或者通过其他途径!

今天我们就通过SignalR来实现一个B/S端对windows服务运行状态的监控,这里我们用SignalRselfHost,不依赖IIS,然后利用topshelf把SignalRServer部署成windows服务,然后在B/S端通过SignalRjsclient进行连接获取服务运行状态!



首先创建一个控制台应用程序,.NET4.5,Nuget添加Microsoft.AspNet.SignalR.SelfHostMicrosoft.Owin.CorsTopShelf(实现windows服务安装)

具体新建SignalRSelfHostServer的方法可以看我以前的博客:SignalRSelfHost实时消息,集成到web中,实现服务器消息推送


新建一个hub命名为ServiceMonitorHub,继承Microsoft.AspNet.SignalR.Hub,我们要实现服务状态1秒钟推送一次

具体代码如下

复制代码
1usingSystem.Linq;
2usingSystem.Threading;
3
4namespacewxRbt.Service.Realtime.Hub
5{
6///
7///服务监控器
8///

9publicclassServiceMonitorHub:Microsoft.AspNet.SignalR.Hub
10{
11staticServiceMonitorHub()
12{
13newThread(newThreadStart(()=>
14{
15while(true)
16{
17//获取所有服务名称以wxRbt开头的服务
18varservices=System.ServiceProcess.ServiceController.GetServices().Where(t=>t.ServiceName.StartsWith("wxRbt"))
19.Select(t=>newModel.Service
20{
21DisplayName=t.DisplayName,
22ServiceName=t.ServiceName,
23Status=(int)t.Status
24}).ToArray();
25Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext().Clients.All.refresh(services);
26//休眠一秒,实现每秒推送服务运行状态
27System.Threading.Thread.Sleep(1000);
28}
29})).Start();
30}
31}
32}
复制代码
现在我们再利用TopShelf把当前的控制台安装成windows服务

新建一个类ServiceMonitorService,继承Topshelf.ServiceControl接口,实现其Start跟Stop方法,具体代码如下

复制代码
1usingMicrosoft.AspNet.SignalR;
2usingMicrosoft.Owin.Cors;
3usingMicrosoft.Owin.Hosting;
4usingOwin;
5usingSystem;
6usingTopshelf;
7usingSystem.Configuration;
8
9namespacewxRbt.Service.Realtime.Service
10{
11publicclassServiceMonitorService:ServiceControl
12{
13privateIDisposableapp;
14privatestaticstringdomain="http://:3333";
15
16staticServiceMonitorService(){
17domain=ConfigurationManager.AppSettings["Domain"]??domain;
18Console.WriteLine("获取配置:"+domain);
19}
20
21publicboolStart(HostControlhostControl)
22{
23Console.WriteLine("事实消息服务运行在:"+domain);
24
25app=WebApp.Start(domain,builder=>
26{
27builder.UseCors(CorsOptions.AllowAll);
28builder.MapSignalR(newHubConfiguration
29{
30EnableJSONP=true,
31EnableDetailedErrors=true,
32EnableJavaScriptProxies=true
33});
34});
35returntrue;
36}
37
38publicboolStop(HostControlhostControl)
39{
40if(app!=null){
41app.Dispose();
42}
43returntrue;
44}
45}
46}
复制代码
这里给个默认的监听域名,然后从app.config读取配置的监听域名

最后打开Progarm.cs文件,代码如下:

复制代码
1usingTopshelf;
2
3
4namespacewxRbt.Service.Realtime
5{
6classProgram
7{
8staticvoidMain(string[]args)
9{
10HostFactory.Run(s=>{
11s.Service();
12s.SetDisplayName("微信实时消息服务");
13s.StartAutomatically();
14});
15}
16}
17}
复制代码
调试运行程序,如图







上面服务端已经完成,下面,我们来实现客户端:

创建一个MVC4.0web空项目(随便,个人爱好),Nuget引用Microsoft.AspNet.SignalR.JS,该js依赖jquery,会自动下载jquery,写TypeScript同学可以顺带下载这两个JS的d.ts文件

然后创建一个HomeController,在Index里面返回view即可

Views文件夹创建Home文件夹,创建一个Index.cshtml的razor试图,引用jquery跟signalrjs

然后创建一个单独的JS,尽量不要把js写到页面里面去

这里我用TypeScript写一个消息模块

复制代码
1///
2
3modulewxrbt.manager{
4exportconstenumServiceStatus{
5/服务停止/
6Stopped=1,
7/正在运行/
8StartPending=2,
9/正在停止/
10StopPending=3,
11/运行中/
12Running=4,
13/正在继续/
14ContinuePending=5,
15/正在暂停/
16PausePending=6,
17/已暂停/
18Paused=7,
19}
20interfaceIService{
21DisplayName:string;
22ServiceName:string;
23Status:ServiceStatus
24}
25/管理服务/
26exportclassservice{
27privateproxy:SignalR.Hub.Proxy;
28private$:JQueryStatic;
29privateip:string;
30privateport:number;
31constructor(ip:string,port:number){
32this.ip=ip;
33this.port=port;
34}
35/
36开启服务运行状态监测
37@param{(services}callback
38/
39start(callback:(services:Array)=>void){
40jQuery.getScript("http://"+this.ip+":"+this.port+"/signalr/hubs",()=>{
41jQuery.connection.hub.url="http://"+this.ip+":"+this.port+"/signalr";
42this.proxy=jQuery.signalR.hub.createHubProxy("ServiceMonitorHub");
43
44//每次刷新数据回调
45this.proxy.on("refresh",(services:Array)=>{
46callback(services);
47});
48
49
50jQuery.connection.hub.start().fail(()=>{
51alert("连接实时消息服务期:http://"+this.ip+":"+this.port+"失败,请确认消息服务配置正确且正常开启!");
52});
53});
54}
55}
56}
复制代码
下面我结合RequireJs实现的该模块调用

复制代码
1require(["message"],()=>{
2
3jQuery(()=>{
4
5var$service=jQuery("#serviceList");
6varmsg=newwxrbt.manager.service("127.0.0.1",3333);
7msg.start(services=>{
8$service.empty();
9for(letserviceofservices){
10varisRunning=service.Status==wxrbt.manager.ServiceStatus.Running;
11varstatusCls=isRunning?"success":"warning";
12varstatusTxt=isRunning?"运行中":"已停止";
13varstatus=`${statusTxt}`;
14$service.www.wang027.comappend(`
  • ${service.DisplayName}${status}
  • `);
    15}
    16});
    17
    18});
    19
    20
    21});
    献花(0)
    +1
    (本文系thedust79首藏)