zoukankan      html  css  js  c++  java
  • 基于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服务器上跑的服务截图

  • 相关阅读:
    7.6 C程序的存储空间布局
    7.10 setjmp和longjmp函数
    7.2 main函数
    7.8 存储器分配
    7.5 环境表
    7.1 进程环境 引言
    7.4 命令行参数
    7.3 进程终止
    电影名扬四海主题歌节奏强动感十足的经典歌曲!
    随便写点人生感悟
  • 原文地址:https://www.cnblogs.com/263613093/p/5887636.html
Copyright © 2011-2022 走看看