.net core windows 服务简易框架-已用于生产环境(重复造轮子系列)
目录
.net core windows 服务简易框架-已用于生产环境(重复造轮子系列)
概要
项目中经常需要用到window service ,主要用于后台任务执行,定时任务,和一些比较耗时的数据处理等.一般做成windows service 后可以随系统启动而启动,减少管理成本节约一些部署时间.网上也有现成的框架,但是个人由于特别懒,还有强迫症,所以不喜欢在我的系统中出现多余的功能,和复杂的结构,便开始了漫长的造轮子的过程.
效果
控制台进行命令调试和安装.
install: 安装服务到系统
delete: 删除|卸载服务
start : 直接启动所有服务(这里是个框架,可以同时运行多个服务)
stop : 停止所有服务
welcome : 没啥用,欢迎词
help :显示所有命令.(如果绝对命令不够多,还可以扩展)
这里新建了2个服务ClockService 每秒输出当前时间,MonethService 每1.5秒输出当前月份
看效果
所有代码如下:
class Program
{
static void Main(string[] args)
{
new ServiceHost()
.Register<ClockService>(null)
.Register<MonethService>(null)
.Start(args);
}
}
安装开发包
nuget->Virtuesoft.Windows.Services
整个包大小 27kb 相当小了 .
新建项目
开发环境:vs 2019 .net core 3.1, 新建.Net Core 控制台程序
编写服务
ClockService
using Virtuesoft.Windows.Services;
public class ClockService : IWindowsService
{
/// <summary>
/// 服务名称
/// </summary>
public string Name => "Sample.Clock.Service";
/// <summary>
/// 服务简介
/// </summary>
public string Display => "每秒输出服务";
private Task task;
/// <summary>
/// 启动服务
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool Start(ServiceContextBase context)
{
task= Task.Run(async () => {
while (true)
{
context.Log($"Now Time = {DateTime.Now.ToString()}");
await Task.Delay(1000);
}
});
return true;
}
/// <summary>
/// 停止服务
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool Stop(ServiceContextBase context)
{
task.Dispose();
return true;
}
}
MonethService
public class MonethService : IWindowsService
{
public string Name => "Sample.Moneth.Service";
public string Display => "每秒月份服务";
public bool Start(ServiceContextBase context)
{
Task.Run(async () => {
while (true)
{
context.Log($"Now Moneth = {DateTime.Now.Month.ToString()} Action");
await Task.Delay(1500);
}
});
return true;
}
public bool Stop(ServiceContextBase context)
{
return true;
}
}
配置服务运行
参数基本够用就行,多了怕累
static void Main(string[] args)
{
//新建一个服务宿主
new ServiceHost()
//配置服务环境
.Config(option => {
//服务名称,安装到系统后的名称
option.Name = "virtuesoft.windows.service";
//服务简介,安装到系统后显示的缩略文字
option.Display = "xx项目服务";
//服务详细介绍,安装后的服务详细说明
option.Description = "每秒输出当前时间,每1.5秒输出当前的月份,如果停止该服务着可能会影响时间日志的输出.";
//设置配置文件的路径
//如果需要其他比较多的配置,比如RSA密钥,数据库连接,网络服务,账户等等,可以采用配置文件的形式
//这里配置文件的内容作为公共参数每个子服务均可以获取
option.UseConfig(config => {
//文件路径支持本地绝对|相对,远程路径,比如https://b.a.cn/config.json
//{name:"local",sex:"男",age:12} //仅支持json格式单层
config.Path = "WindowsService.json";
});
//网络访问客户端
//option.Http = new System.Net.Http.HttpClient();
})
//注册服务
.Register<ClockService>(option=> {
option
//添加单独的服务参数,这里的参数只有该服务本身可以获取,同系统的其他服务无法获取
.Add("queque.rsa.private", "1234567890")
.Add("queque.rsa.public", "0987654321")
//设置单独的配置文件路径
.UseConfig(config => {
//文件路径支持本地绝对|相对,远程路径,比如https://b.a.cn/config.json
config.Path = "ClockService.json";
});
})
//注册服务
.Register<MonethService>(null)
//启动服务
.Start(args);
}
说明已经比较详细了.懒得打字.
到这里直接运行就能出效果.
服务之间共享数据
每个服务可以共享参数(ServiceContext.AddShareData),object类型,当共享到参数表后,其他服务便可以通过(ServiceContext.GetShareData)进行获取.当然这个功能不建议用,容易污染数据.而且共享数据没有回收机制,会一直存在可能导致内存过大.建议使用消息队列或者缓存,方便分布式部署.
//写入共享数据
context.AddShareData("user.role.update",new { id=0x01,name="sys.user.vip",m=36f});
//获取共享数据
var sharedata = context.GetShareData("user.role.update");
配置数据的获取
服务里可以通过ServiceContext 获取配置文件数据,获取启动参数.
//获取参数
var privatekey = context.Get<string>("queque.rsa.private");
var publickey = context.Get<string>("queque.rsa.public");
//获取配置文件
var config = context.GetConfigration();
简单的日志输出
为了输出部分信息,集成了简单的日志输出,同时输出到控制台和文件.默认会在运行目录新建log文件夹,主程序日志直接以日期命名保存,子服务以服务名称为文件夹名,日志以日期分钟为文件名进行输出.
//日志输出
context.Log("这里是日志信息");//扩展方法
this.Log("这里是日志输出");//扩展方法