基于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}); |
|