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服务器上跑的服务截图

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

  • 相关阅读:
    XAF 有条件的对象访问权限
    XAF 顯示 UnInplace Report(設置自定義條件顯示報表,不是根據選擇ListView記錄條件顯示報表)
    XAF 如何自定义PivotGrid单元格显示文本?
    XAF 如何布局详细视图上的按钮
    XAF How to set size of a popup detail view
    XAF Delta Replication Module for Devexpress eXpressApp Framework
    XAF 帮助文档翻译 EasyTest Basics(基础)
    XAF 用户双击ListView记录时禁止显示DetailView
    XAF How to enable LayoutView mode in the GridControl in List Views
    XAF 如何实现ListView单元格批量更改?
  • 原文地址:https://www.cnblogs.com/soundcode/p/5888250.html
Copyright © 2011-2022 走看看