基于SignalR实现B/S系统对windows服务运行状态的监测

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

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

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

首先创建一个控制台应用程序,.NET 4.5,Nuget添加 Microsoft.AspNet.SignalR.SelfHost Microsoft.Owin.Cors TopShelf(实现windows服务安装)

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

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

具体代码如下

 1 using System.Linq;
 2 using System.Threading;
 3
 4 namespace wxRbt.Service.Realtime.Hub
 5 {
 6     /// <summary>
 7     /// 服务监控器
 8     /// </summary>
 9     public class ServiceMonitorHub:Microsoft.AspNet.SignalR.Hub
10     {
11         static ServiceMonitorHub()
12         {
13             new Thread(new ThreadStart(() =>
14             {
15                 while (true)
16                 {
17                     //获取所有服务名称以wxRbt开头的服务
18                     var services = System.ServiceProcess.ServiceController.GetServices().Where(t => t.ServiceName.StartsWith("wxRbt"))
19                         .Select(t => new Model.Service
20                         {
21                             DisplayName = t.DisplayName,
22                             ServiceName = t.ServiceName,
23                             Status = (int)t.Status
24                         }).ToArray();
25                     Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<ServiceMonitorHub>().Clients.All.refresh(services);
26                     //休眠一秒,实现每秒推送服务运行状态
27                     System.Threading.Thread.Sleep(1000);
28                 }
29             })).Start();
30         }
31     }
32 }

现在我们再利用TopShelf把当前的控制台安装成windows服务

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

 1 using Microsoft.AspNet.SignalR;
 2 using Microsoft.Owin.Cors;
 3 using Microsoft.Owin.Hosting;
 4 using Owin;
 5 using System;
 6 using Topshelf;
 7 using System.Configuration;
 8
 9 namespace wxRbt.Service.Realtime.Service
10 {
11     public class ServiceMonitorService:ServiceControl
12     {
13         private IDisposable app;
14         private static string domain="http://*:3333";
15
16         static ServiceMonitorService() {
17             domain = ConfigurationManager.AppSettings["Domain"] ?? domain;
18             Console.WriteLine("获取配置:"+domain);
19         }
20
21         public bool Start(HostControl hostControl)
22         {
23             Console.WriteLine("事实消息服务运行在:"+domain);
24
25             app = WebApp.Start(domain, builder =>
26             {
27                 builder.UseCors(CorsOptions.AllowAll);
28                 builder.MapSignalR(new HubConfiguration
29                 {
30                     EnableJSONP = true,
31                     EnableDetailedErrors = true,
32                     EnableJavaScriptProxies = true
33                 });
34             });
35             return true;
36         }
37
38         public bool Stop(HostControl hostControl)
39         {
40             if (app != null) {
41                 app.Dispose();
42             }
43             return true;
44         }
45     }
46 }

这里给个默认的监听域名,然后从app.config读取配置的监听域名

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

 1 using Topshelf;
 2
 3
 4 namespace wxRbt.Service.Realtime
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             HostFactory.Run(s => {
11                 s.Service<Service.ServiceMonitorService>();
12                 s.SetDisplayName("微信实时消息服务");
13                 s.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 /// <reference path="../../../scripts/typings/signalr/signalr.d.ts" />
 2
 3 module wxrbt.manager {
 4     export const enum ServiceStatus {
 5         /**服务停止*/
 6         Stopped = 1,
 7         /**正在运行*/
 8         StartPending = 2,
 9         /**正在停止*/
10         StopPending = 3,
11         /**运行中*/
12         Running = 4,
13         /**正在继续*/
14         ContinuePending = 5,
15         /**正在暂停*/
16         PausePending = 6,
17         /**已暂停*/
18         Paused = 7,
19     }
20     interface IService {
21         DisplayName: string;
22         ServiceName: string;
23         Status: ServiceStatus
24     }
25     /**管理服务*/
26     export class service {
27         private proxy: SignalR.Hub.Proxy;
28         private $: JQueryStatic;
29         private ip: string;
30         private port: number;
31         constructor(ip: string, port: number) {
32             this.ip = ip;
33             this.port = port;
34         }
35         /**
36          * 开启服务运行状态监测
37          * @param {(services} callback
38          */
39         start(callback: (services: Array<IService>) => void) {
40             jQuery.getScript("http://" + this.ip + ":" + this.port + "/signalr/hubs", () => {
41                 jQuery.connection.hub.url = "http://" + this.ip + ":" + this.port + "/signalr";
42                 this.proxy = jQuery.signalR.hub.createHubProxy("ServiceMonitorHub");
43
44                 //每次刷新数据回调
45                 this.proxy.on("refresh", (services: Array<IService>) => {
46                     callback(services);
47                 });
48
49
50                 jQuery.connection.hub.start().fail(() => {
51                     alert("连接实时消息服务期:http://" + this.ip + ":" + this.port + "失败,请确认消息服务配置正确且正常开启!");
52                 });
53             });
54         }
55     }
56 }

下面我结合RequireJs实现的该模块调用

 1 require(["message"], () => {
 2
 3     jQuery(() => {
 4
 5         var $service = jQuery("#serviceList");
 6         var msg = new wxrbt.manager.service("127.0.0.1", 3333);
 7         msg.start(services=>{
 8             $service.empty();
 9             for (let service of services) {
10                 var isRunning = service.Status == wxrbt.manager.ServiceStatus.Running;
11                 var statusCls = isRunning ? "success" : "warning";
12                 var statusTxt = isRunning ? "运行中" : "已停止";
13                 var status = `<label class=‘label label-${statusCls}‘>${statusTxt}</label>`;
14                 $service.append(`<li><a href=‘javascript:;‘><i class=‘icon-check‘></i>${service.DisplayName}${status}</a></li><li class="divider"></li>`);
15             }
16         });
17
18     });
19
20
21 });

最后运行页面查看效果:

唯一不足的就是1秒钟这个dropdownlist会闪动一次,我这里是先清除再append进来,所以会出现这个情况,如果采用dom节点递归更新状态就不会有这个问题了!

因为是公司项目,没办法上源码!有不清除的可以留言!

下面是在windows服务器上跑的服务截图

http://www.cnblogs.com/263613093/p/5887636.html

时间: 2024-09-28 23:01:41

基于SignalR实现B/S系统对windows服务运行状态的监测的相关文章

windows服务,安装、启动、停止,配置,一个批处理文件搞定

相对而言,还是比较通用的吧,如果哪位仁兄有更好的实现方式,或者发现有不足之处,还请多多指教. @echo off echo.-------------------------------------------------- echo.---- 技术支持:CC          -------- echo.---- 今天是%date%  -------- echo.-------------------------------------------------- echo.正在检测服务是否已经

基于SignalR的服务端和客户端通讯处理

SignalR是一个.NET Core/.NET Framework的实时通讯的框架,一般应用在ASP.NET上,当然也可以应用在Winform上实现服务端和客户端的消息通讯,本篇随笔主要基于SignalR的构建一个基于Winform的服务端和客户端的通讯处理案例,介绍其中的处理过程. 1.SignalR基础知识 SignalR是一个.NET Core/.NET Framework的开源实时框架. SignalR的可使用Web Socket, Server Sent Events 和 Long

基于Windows服务的WCF

(1)创建WCF 代码示例: [ServiceContract] public interface ILimsDBService { [OperationContract] int ExecuteSql(string strSql); [OperationContract] DataTable GetDataTable(string strSql); [OperationContract] DataSet GetDataSet(string strSql); } public class Lim

基于C#&amp;.net2.0的windows服务创建与安装

起因:一台服务器中部署的程序,停电后未按照计划任务正常启动. 一.创建并配置Windows服务程序 开发工具VS2015 Framework版本2.0 1.新建Windows服务 2.在Service.cs中编写服务程序所需要执行的操作 服务运行时会自动加载Service1中的代码,亦有OnStart(),OnStop(),OnShutdown()方法分别对应服务启动,服务停止和计算机关闭操作. 3.添加安装程序并配置服务属性 3.1在Service.cs中鼠标右键单击,添加安装程序. 3.2配

基于Flume做FTP文件实时同步到本地磁盘的windows服务。

需求:做一个windows服务,实现从ftp服务器实时下载或者更新文件到本地磁盘. 功能挺简单的.直接写个ftp工具类用定时器跑就能搞定,那我为什么不用呢? 别问,问就是我无聊啊,然后研究一下Flume打发时间.哈哈~ 一.Flume部分 Source组件和Sink组件用的都是第三方. source组件:https://github.com/keedio/flume-ftp-source Sink组件用的谁的目前已经找不到了,网上搜到了一个升级版的. sink组件:https://github.

玩转Windows服务系列&mdash;&mdash;给Windows服务添加COM接口

当我们运行一个Windows服务的时候,一般情况下,我们会选择以非窗口或者非控制台的方式运行,这样,它就只是一个后台程序,没有界面供我们进行交互. 那么当我们想与Windows服务进行实时交互的时候,我们应该怎么做呢? 快速给Windows服务添加实时交互功能的方案 Windows服务是一个进程,而我们用于交互的程序,又是另外一个进程.我们与Windows服务实时交互,其实就是一个进程间通信的问题.所有的进程间通信的方案基本上都适用于实时交互的方案,比如Socket.共享内存.管道.COM等.

RDIFramework.NET框架SOA解决方案(集Windows服务、WinForm形式与IIS形式发布)-分布式应用

RDIFramework.NET框架SOA解决方案(集Windows服务.WinForm形式与IIS形式发布)-分布式应用 RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,给用户和开发者最佳的.Net框架部署方案.该框架以SOA范式作为指导思想,作为异质系统整合与互操作性.分布式应用提供了可行的解决方案. 1.SOA平台简介 1.1.概述 SOA(service-oriented architecture,也叫面向服务的体系结构或面向服务架构)是指为了解决在Inte

C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(上)

译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 and .NET Core 1.0>.水平有限,各位阅读时仔细分辨,唯望莫误人子弟. 附英文版原文:Professional C# 6 and .NET Core 1.0 - Chapter 39 Windows Services --------------------------------

web站点和windows服务项目发布时如何排除指定文件

在发布asp.net站点和windows服务项目时,有的时候这样的需求:msbuild编译之后发布到服务器指定目录时要排除指定文件,比如通过jenkins构建时,不希望覆盖原来的Web.config和App.config,那么该如何排除呢? web站点项目 比如不希望发布Web.config文件,有以下三种方法. 1,将项Content改为None 修改前: 1 <Content Include="Web.config" /> 修改后: 1 <None Include