Dotnet创建Linux下的Service应用
创建Service应用,是一个服务端开发的必会技能。
前言
说到服务端应用,最常见的就是API服务。
除此之外,还有一类应用,比方一个Socket的服务器。这类型的应用,本身没有Web层,当然也不属于API服务。
通常大家会怎么做?
不讲究的做法,就是做一个Console应用,加载到后台一直跑着。
其实,还有另外一种做法,就是把应用加载到Services里,使应用以一个Service来做响应。这样可以依托操作系统的Services管理器来进行统一管理,自动运行和故障处理。
Dotnet做Window Service的内容,网上有很多。我今天写一个在Linux下做Service的方法。
创建Linux下的Service应用
创建一个LInux下的Service应用其实很简单,就分这么几步:
1. 用 Worker 模板创建工程
如果习惯用VS上创建,就找一下Worker Service
模板。
我是习惯从命令行创建,就一条命令:
% dotnet new worker -o projectname
Dotnet会自动造成工程,并自动引用Microsoft.Extensions.Hosting
包,因为这本身是一个Self-Hosting
应用。
2. 加入Linux Service扩展包
其实这就是一个包:Microsoft.Extensions.Hosting.Systemd
。这个包为应用提供了在Linux下使用Systemd守护进程的基础配置。
还是命令行:
% dotnet add package Microsoft.Extensions.Hosting.Systemd
3. 修改Program.cs
其实就是一行代码,把第二步引入的包加入应用。修改Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).UseSystemd() // 加入的就是这一行。.ConfigureServices((hostContext, services) =>{services.AddHostedService<Worker>();});
到这儿,套路性的工作已经完成。简单吧?
我们来看一下现在的工程:
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Worker.cs
├── appsettings.Development.json
├── appsettings.json
└── workerdemo.csproj
大家会注意到,里面多了一个Worker.cs
的类文件。
看一下这个文件:
public class Worker : BackgroundService
{private readonly ILogger<Worker> _logger;public Worker(ILogger<Worker> logger){_logger = logger;}protected override async Task ExecuteAsync(CancellationToken stoppingToken){while (!stoppingToken.IsCancellationRequested){_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);await Task.Delay(1000, stoppingToken);}}
}
这其实就是加载到Systemd里的服务的模板。我们需要的服务代码,需要加到ExecuteAsync(CancellationToken stoppingToken)
方法中。
我简单做个例子,在里面加入UDP服务,看代码:
public class Worker : BackgroundService
{private readonly ILogger<Worker> _logger;private readonly IConfiguration _configuration;public Worker(ILogger<Worker> logger, IConfiguration configuration){_logger = logger;_configuration = configuration;}protected override async Task ExecuteAsync(CancellationToken stoppingToken){_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000));while (!stoppingToken.IsCancellationRequested){UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();string message = Encoding.UTF8.GetString(udpReceiveResult.Buffer);Console.WriteLine($"{udpReceiveResult.RemoteEndPoint.ToString()} - {message}");await udpClient.SendAsync(Encoding.Default.GetBytes("Got"), 3, udpReceiveResult.RemoteEndPoint);}}
}
这个代码中,有两件事需要注意:
在前边Program.cs中加入
UseSystemd()
时,已经注入了IConfiguration
。因此,可以在这个方法中直接引入并使用。换句话说,就是可以直接读取例如appsetting.json
的内容;是上边提到的,真正的服务响应在
ExecuteAsync(CancellationToken stoppingToken)
中。这儿没什么特别的,就是正常的写法。
上面这个,是服务端的程序,是响应。
下面我简单做个客户端的请求,供测试用。就不解释了,只列出步骤:
创建一个工程
% dotnet new console -o democlient
修改Program.cs
static async Task Main(string[] args)
{UdpClient udpClient = new UdpClient();for (int i = 0; i < 10000; i++){byte[] buffer = new byte[8 * 1024];await Task.Run(() =>{udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000));});}while (true){UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();string message = Encoding.UTF8.GetString(udpReceiveResult.Buffer);Console.WriteLine($"{udpReceiveResult.RemoteEndPoint.ToString()} - {message}");}Console.ReadKey();
}
运行一下,看看效果。
到这里,Service应用开发的工作已经完成。
下面是部署。
部署Service应用
Linux下面部署一个Service应用,只有两个步骤:
1. 创建Service定义
Linux下的每个Service,都会有个定义文件。这个文件存在于/etc/systemd/system
目录下。
下面我给出一个简单的Service模板:
[Unit]
Description=DemoProject[Service]
Type=notify
ExecStart=dotnet /yourfolder/yourproject.dll[Install]
WantedBy=multi-user.target
把这个内容保存为一个文件,例如叫demo.service
。然后把这个文件复制到/etc/systemd/system
下,并改为可执行。
简单说一下这个文件的一些项:
Description,是服务的名字。不重要,启动时,你用到的是文件名
demo.service
;Type,服务类型,使用Dotnet加载时,只能是这种类型。如果把程序编译为自包含程序,这个类型可以是simple;
ExecStart,启动程序的命令,是全路径的,要确保能找得到这个程序。上面例子中,
dotnet /yourfolder/yourproject.dll
,是因为dotnet命令是有PATH变量支持的。
这个文件的配置项有很多,包括定义是否需要自动重启、重启间隔等。如果需要,可以去这里查询。
2. 启动Service
有两种方法。
第一种是刷新Service守护
% systemctl daemon-reload
刷新守护时,守护进程会去/etc/systemd/system
目录下,寻找新加入的Service文件,并启动。
第二种是单独启动,有一系列命令:
启动
% systemctl start demo.service
停止
% systemctl stop demo.service
重启
% systemctl restart demo.service
查询状态
% systemctl status demo.service
嗯。这就是服务加载和停止了。
注意,这种方式加载的Service,是完全系统的服务,会没有任何输出。
如果需要调试,一种方式是加文件日志,另一种方式是用另一个命令启动:
% journalctl -u dnsserver.service
当然,这种方式只用于调试。正式运行时,还应该是上面的方式。
这就是今天的内容,希望能帮到大家。感觉有用的话,给个三连呗~
喜欢就来个三连,让更多人因你而受益
Dotnet创建Linux下的Service应用相关推荐
- linux 下的 service 和systemctl 服务管理方式
linux 下的 service 和systemctl 服务管理方式 man service 得到:执行一个system V 风格的启动脚本 service - run a System V ini ...
- dotnet core Linux下图片验证码解决方案
dotnet core Linux下图片验证码解决方案 参考文章: (1)dotnet core Linux下图片验证码解决方案 (2)https://www.cnblogs.com/xxff/p/9 ...
- linux oracle 用户创建,LINUX下Oracle数据库用户创建方法详解
本文实例分析了LINUX下Oracle数据库用户创建方法.分享给大家供大家参考,具体如下: 1)登录linux,以oracle用户登录(如果是root用户登录的,登录后用 su - oracle命令切 ...
- linux下的进程创建,Linux下进程的创建
这篇文章主要是讲解到Linux进程的控制,包括程序和进程.守护进程.守护进程的出错处理. 1.程序和进程 程序(program)是存放在磁盘文件中的可执行文件,程序的执行实例被称为进程(process ...
- Linux下使用service启动jar包.md
为了方便启动jar项目,我们可以使用xxx.service方式. 1. 执行命令,进入到system目录下: cd etc/systemd/system 2. 创建一个*.service 后缀的文件( ...
- OpenBSD操作系统(1)——服务管理程序rcctl 类似linux下的service或systemctl
目录 rcctl简介 启用或禁用后台进程 启动或停止后台进程 列出进程相关的参数 列出进程默认参数 列出符合特定条件的进程 列出符合条件的进程 设置进程参数 rcctl简介 rcctl是OpenBSD ...
- openbsd运行Linux应用程序,OpenBSD操作系统(1)——服务管理程序rcctl 类似linux下的service或syst...
目录 rcctl简介rcctl是OpenBSD系统上的后台进程(daemon)管理程序,功能上类似于以前RedHat Linux上的chkconfig或新版中的systemctl. 它其实是一个she ...
- linux虚拟机 xen,创建LINUX下XEN虚拟机
mkdir /domU 1.创建虚拟机映像 dd if=/dev/zero of=xen.img bs=1M count=16000 dd if=/dev/zero of=xen2.img bs=1M ...
- linux tcp 创建,Linux下tcp服务器创建的步骤
创建一个socket,使用函数socket() socket(套接字)实质上提供了进程通信的端点,进程通信之前,双方首先必须建立各自的一个端点,否则没有办法通信.通过socket将IP地址和端口绑定之 ...
最新文章
- CentOS 6.2 下samba 服务的配置
- Linux IPv6 地址配置
- Juju-Gui 安装笔记
- Python剑指offer:数组中重复的数字
- chartcontrol饼状图属性设置_温故而知新,ggplot2 饼图的几点笔记
- 【重庆】2021年下半年软考报考时间及通知
- 从东岳流体下载自带OpenFOAM的Vmware虚拟机(Ubuntu20.04+OpenFOAM),无法共享文件夹【终极解决方案】
- 使用java.util.prefs.Preferences代替java.util.Properties
- Matlab看跌期权二叉树,欧式期权二叉树MATLAB程序
- Weaveworks增加发布自动化和事件管理
- 【正点原子MP157连载】 第二十一章 DMA实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南
- sip账号服务器,如何解决“sip账号未登录” ?
- jQuery图片弹出Lightbox插件带轮播
- 淘宝天猫店铺装修问题与技巧性经验汇总
- 移动混合开发框架+Android原生模块化/组件化
- android碎片化的解决方法,Android碎片化的处理
- JMS入门(一)--JMS基础
- 转贴:谁说我会画板?
- 示波器表笔旁边的夹子是什么_示波器探头的地线夹子应该要靠近测量点
- android 音量 广播,Android平台音量调节(一)音量键调节音量
热门文章
- 线切割机上的DOS系统
- 介绍自定义JDataGrid电子表格版本公式中的函数?
- 广西工学院c语言试题答案,广西工学院的C语言考试试题
- Xamarin.Android 开发中遇到旋转屏幕错误
- wampServer配置WWW根目录遇到的坑
- jquery动态改变图片
- Android:源码环境编译自定义的APP到ROM(System Image)中
- 薛定谔的猫——.NET 4.1 中的新基类,开源Preview中
- Unity3D学习笔记之二资源导入以及工程管理
- 如何将世界时钟和时区小部件添加到您的iPhone