使用 Windows 服务运行 Hangfire,并添加网站作为控制面板(上)

本贴最后更新于 2701 天前,其中的信息可能已经渤澥桑田

前言

由于 hangfire 在 asp.net 环境有不稳定因素,例如 IIS 中应用程序池默认会在闲时自动休眠、隔一段时间会自动重启等问题,在对可用性要求高的场景就会凸显这种不稳定。
虽然官方给出了解决方法,但终究不太科学,IIS 的应用程序池天生就是需要隔一段时间就回收一下的东西,强制“always running”其实并不和谐。

我认为更合理的方式是使用 Windows Service 来运行 Hangfire,然后另开一个网站作为 Hangfire 的操控面板。

这里会使用两到三篇文章的篇幅来分享,从新建项目到调试和安装这样一个完整的过程。分享的粒度会尽量细一些,以免节奏太快让大家看不明白。


建立 Windows service 项目并引入 Hangfire

建立 Windows service 项目:

文件 ——> 新建 ——> Windows 服务

引入 Hangfire:

工具 ——> NuGet包管理器 ——> 程序包管理器控制台

在控制台中输入:
PM> Install-Package Hangfire.Core
PM> Install-Package Hangfire.SqlServer

这里也可以在可视化的 NuGet 包管理器中搜索这两个包进行安装。

只要 Hangfire.Core 就足够了。
不需要安装 hangfire ,这个 package 包含一些你不需要的依赖项。(例如:Microsoft.Owin.Host.SystemWeb

这里演示中使用 SqlServer 作为 Hangfire 服务的 Storage。
Hangfire 官方在免费版中只提供了 SqlServer 接入的支持,在收费版多一个 Redis。
需要 MongoDB、MySql、PostgreSql、SQLite 等其他 Storages 的可以自己寻找第三方的开源项目,这里有一个官方推荐的扩展清单,清单中列出了一些其他种类的 Storages。

初始化 Hangfire 服务并添加任务

进入 Service1 的代码视图,添加一个后台任务服务。

using System.ServiceProcess;
using Hangfire;
using Hangfire.SqlServer;

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        private BackgroundJobServer _server;

        public Service1()
        {
            InitializeComponent();
            //记得在配置文件中添加数据库连接字符串
            GlobalConfiguration.Configuration.UseSqlServerStorage("connection_string");
        }

        protected override void OnStart(string[] args)
        {
            _server = new BackgroundJobServer();
            //可以在BackgroundJobServer实例化之后的任意位置添加任务
        }

        protected override void OnStop()
        {
            _server.Dispose();
        }
    }
}

可以在 BackgroundJobServer 实例化之后的任意位置添加定时任务,添加的任务会持久化在 Storage 中,关于任务的添加及相关配置这里不做说明,请参见官方文档

为该 Windows 服务添加安装程序

在服务的设计视图中右键,选择添加安装程序。

为服务起一个名字,并添加描述。

使用 Visual Studio 工具安装和卸载服务

Windows 服务无法在 VS 中直接调试或运行,需要把该程序安装为服务才能运行。后文会详细讲解如何调试安装好的服务。

可以使用 sc create 命令创建 Windows 服务,这里讲解一种.NET 环境下独有的方式。
.net framwork 提供了一个名为 InstallUtil.exe 的工具,可以在 cmd 中使用该工具。

通常可以在 C:\Windows\Microsoft.NET\Framework\*version* 找到这个工具,然后在该目录启动 cmd 来使用它。

可但是,微软官方推荐使用 Visual Studio 的命令行开发人员工具来搞事,所以这里演示使用 Visual Studio 开发人员工具来 安装/卸载 服务。

桌面 ——> 开始 ——> 所有应用程序 ——> Visual Studio ——> Visual Studio 工具 ——> 开发人员命令提示

大概是这样一个路径能找到这个工具,不同的操作系统略有差异,我 Win10 + VS2017 的环境找到的工具名称是 Developer Command Prompt for VS 2017

注意:这里必须使用管理员身份启动该工具,否则会报一个如下所示的异常。

在安装程序集“D:\OneDrive\Code\WindowsService.Hangfire.exe”。
受影响的参数是:
   logtoconsole = 
   logfile = D:\OneDrive\Code\WindowsService.Hangfire.InstallLog
   assemblypath = D:\OneDrive\Code\WindowsService.Hangfire.exe
正在安装服务 Himall.Hangfire...
正在日志 Application 中创建 EventLog  Himall.Hangfire...
正在回滚程序集“D:\OneDrive\Code\WindowsService.Hangfire.exe”。
受影响的参数是:
   logtoconsole = 
   logfile = D:\OneDrive\Code\WindowsService.Hangfire.InstallLog
   assemblypath = D:\OneDrive\Code\WindowsService.Hangfire.exe
正在将事件日志还原到源 Himall.Hangfire 的前一状态。
 System.Diagnostics.EventLogInstaller 安装程序的“回滚”阶段发生异常。
System.Security.SecurityException: 未找到源,但未能搜索某些或全部事件日志。  不可访问的日志: Security
在安装的“回滚”阶段发生异常。将忽略该异常并继续回滚。但是,在完成回滚后计算机可能无法完全还原到它的初始状态。

打开 Visual Studio 开发人员工具之后,输入如下命令来安装和卸载服务。
安装:

installutil D:\OneDrive\Code\WindowsService.Hangfire.exe

卸载:

installutil /u D:\OneDrive\Code\WindowsService.Hangfire.exe

安装之后可以通过 事件查看器 检查服务是否正常启动。

编写 bat 文件简化安装与卸载

因为 installutil 命令安装好的服务并不会自动启动,自动启动的设置需要操作系统重启后才生效,然后在开发过程中需要频繁地
修改代码...卸载服务...编译...安装...启动服务.........修改代码...卸载服务...编译...安装...启动服务.........修改代码...卸载服务...编译...安装...启动服务.........

那么编写一个批处理工具简化流程就显得非常重要,这里提供一键 安装/卸载 的代码。
安装:

@echo off

echo 正在安装服务...

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

C:

InstallUtil.exe %~dp0HangfireTest.exe

echo 安装完成。

echo ----------------------------------------------------------

net start HangfireTest

pause

卸载:

@echo off

echo 正在卸载服务...

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

c:

InstallUtil.exe /u %~dp0HangfireTest.exe


pause

脚本中的 %~dp0 表示 bat 文件所在的目录路径。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...