通常来讲一个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秒钟推送一次

具体代码如下

 using System.Linq;
using System.Threading; namespace wxRbt.Service.Realtime.Hub
{
/// <summary>
/// 服务监控器
/// </summary>
public class ServiceMonitorHub:Microsoft.AspNet.SignalR.Hub
{
static ServiceMonitorHub()
{
new Thread(new ThreadStart(() =>
{
while (true)
{
//获取所有服务名称以wxRbt开头的服务
var services = System.ServiceProcess.ServiceController.GetServices().Where(t => t.ServiceName.StartsWith("wxRbt"))
.Select(t => new Model.Service
{
DisplayName = t.DisplayName,
ServiceName = t.ServiceName,
Status = (int)t.Status
}).ToArray();
Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<ServiceMonitorHub>().Clients.All.refresh(services);
//休眠一秒,实现每秒推送服务运行状态
System.Threading.Thread.Sleep();
}
})).Start();
}
}
}

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

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

 using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using Topshelf;
using System.Configuration; namespace wxRbt.Service.Realtime.Service
{
public class ServiceMonitorService:ServiceControl
{
private IDisposable app;
private static string domain="http://*:3333"; static ServiceMonitorService() {
domain = ConfigurationManager.AppSettings["Domain"] ?? domain;
Console.WriteLine("获取配置:"+domain);
} public bool Start(HostControl hostControl)
{
Console.WriteLine("事实消息服务运行在:"+domain); app = WebApp.Start(domain, builder =>
{
builder.UseCors(CorsOptions.AllowAll);
builder.MapSignalR(new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
});
return true;
} public bool Stop(HostControl hostControl)
{
if (app != null) {
app.Dispose();
}
return true;
}
}
}

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

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

 using Topshelf;

 namespace wxRbt.Service.Realtime
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(s => {
s.Service<Service.ServiceMonitorService>();
s.SetDisplayName("微信实时消息服务");
s.StartAutomatically();
});
}
}
}

调试运行程序,如图

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

创建一个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写一个消息模块

 /// <reference path="../../../scripts/typings/signalr/signalr.d.ts" />

 module wxrbt.manager {
export const enum ServiceStatus {
/**服务停止*/
Stopped = ,
/**正在运行*/
StartPending = ,
/**正在停止*/
StopPending = ,
/**运行中*/
Running = ,
/**正在继续*/
ContinuePending = ,
/**正在暂停*/
PausePending = ,
/**已暂停*/
Paused = ,
}
interface IService {
DisplayName: string;
ServiceName: string;
Status: ServiceStatus
}
/**管理服务*/
export class service {
private proxy: SignalR.Hub.Proxy;
private $: JQueryStatic;
private ip: string;
private port: number;
constructor(ip: string, port: number) {
this.ip = ip;
this.port = port;
}
/**
* 开启服务运行状态监测
* @param {(services} callback
*/
start(callback: (services: Array<IService>) => void) {
jQuery.getScript("http://" + this.ip + ":" + this.port + "/signalr/hubs", () => {
jQuery.connection.hub.url = "http://" + this.ip + ":" + this.port + "/signalr";
this.proxy = jQuery.signalR.hub.createHubProxy("ServiceMonitorHub"); //每次刷新数据回调
this.proxy.on("refresh", (services: Array<IService>) => {
callback(services);
}); jQuery.connection.hub.start().fail(() => {
alert("连接实时消息服务期:http://" + this.ip + ":" + this.port + "失败,请确认消息服务配置正确且正常开启!");
});
});
}
}
}

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

 require(["message"], () => {

     jQuery(() => {

         var $service = jQuery("#serviceList");
var msg = new wxrbt.manager.service("127.0.0.1", 3333);
msg.start(services=>{
$service.empty();
for (let service of services) {
var isRunning = service.Status == wxrbt.manager.ServiceStatus.Running;
var statusCls = isRunning ? "success" : "warning";
var statusTxt = isRunning ? "运行中" : "已停止";
var status = `<label class='label label-${statusCls}'>${statusTxt}</label>`;
$service.append(`<li><a href='javascript:;'><i class='icon-check'></i>${service.DisplayName}${status}</a></li><li class="divider"></li>`);
}
}); }); });

最后运行页面查看效果:

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

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

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

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

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

    基于SignalR实现B/S系统对windows服务运行状态的监测 通常来讲一个BS项目肯定不止单独的一个BS应用,可能涉及到很多后台服务来支持BS的运行,特别是针对耗时较长的某些任务来说,Windo ...

  2. C++ 检查Windows服务运行状态

    检查Windows服务运行状态  C++ Code  1234567891011121314151617181920212223242526272829303132333435363738394041 ...

  3. C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)

    在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...

  4. Topshelf+Quartz3.0基于控制台应用程序快速开发可调度windows服务

    1.TopShelf TopShelf是一个开源的跨平台的宿主服务框架.可通过.Net Core/.Net Framwork控制台应用程序快速开发windows服务,更加便于服务调试. 本文基于.Ne ...

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

    相对而言,还是比较通用的吧,如果哪位仁兄有更好的实现方式,或者发现有不足之处,还请多多指教.  @echo off echo.------------------------------------- ...

  6. C#曲线分析平台的制作(六,Sqldependency+Signalr+windows 服务)

    在经过五天的学习和资料收集后,终于初步实现了利用sqldependency进行数据库变化监控,signalr进行前后台交互,数据实时更新.下面将源代码贴出进行初步分析: 1.系统整体框架构成: 2.具 ...

  7. 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式

    连表查询都用Left Join吧   最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...

  8. asp.net基于windows服务实现定时发送邮件的方法

    本文实例讲述了asp.net基于windows服务实现定时发送邮件的方法.分享给大家供大家参考,具体如下: //定义组件 private System.Timers.Timer time; publi ...

  9. C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

随机推荐

  1. 回首经典的SQL Server 2005

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com SQL Server是我使用时间最长的数据库,算起来已经有10年了.上世纪90年代,微软在软件开发的所有领域高歌猛 ...

  2. 深入理解DIP、IoC、DI以及IoC容器

    摘要 面向对象设计(OOD)有助于我们开发出高性能.易扩展以及易复用的程序.其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC.DI以及Ioc容器等概念.通过本文我们将一起学 ...

  3. BootStrap_02之全局样式及组件

    1.BootStrap指定的四种屏幕尺寸: ①超大PC屏幕--lg(large):w>=1200px: ②中等PC屏幕--md(medium):1200px>w>=992px: ③P ...

  4. WinForm 天猫2013双11自动抢红包【源码下载】

    1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...

  5. 【解决方案】Myeclipse 10 安装 GIT 插件 集成 步骤 图解

    工程开发中,往往要使用到集成GIT ,那么下面说说插件安装步骤 PS:以Myeclipse 10 为例,讲解集成安装步骤. ----------------------main------------ ...

  6. [APUE]文件和目录(中)

    一.link.unlink.remove和rename 一个文件可以有多个目录项指向其i节点.使用link函数可以创建一个指向现存文件连接 #include <unistd.h> int ...

  7. CentOS下mysql数据库常用命令总结

    mysql数据库使用总结 本文主要记录一些mysql日常使用的命令,供以后查询. 1.更改root密码 mysqladmin -uroot password 'yourpassword' 2.远程登陆 ...

  8. js报错: Uncaught RangeError: Invalid string length

    在ajax请求后得到的json数据,遍历的时候chrome控制台报这个错误:Uncaught RangeError: Invalid string length,在stackoverflow查找答案时 ...

  9. peer not authenticated的终极解决方案

    一.前述 使用httpclient发起https请求时,可能会遇到如下异常: javax.net.ssl.SSLPeerUnverifiedException: peer not authentica ...

  10. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...