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);}}
}

这个代码中,有两件事需要注意:

  1. 在前边Program.cs中加入UseSystemd()时,已经注入了IConfiguration。因此,可以在这个方法中直接引入并使用。换句话说,就是可以直接读取例如appsetting.json的内容;

  2. 是上边提到的,真正的服务响应在ExecuteAsync(CancellationToken stoppingToken)中。这儿没什么特别的,就是正常的写法。

上面这个,是服务端的程序,是响应。

下面我简单做个客户端的请求,供测试用。就不解释了,只列出步骤:

  1. 创建一个工程

% dotnet new console -o democlient
  1. 修改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

当然,这种方式只用于调试。正式运行时,还应该是上面的方式。

这就是今天的内容,希望能帮到大家。感觉有用的话,给个三连呗~

喜欢就来个三连,让更多人因你而受益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】java io 总结(图)

2019独角兽企业重金招聘Python工程师标准>>> 转载于:https://my.oschina.net/dlpinghailinfeng/blog/91191

TensorFlow的各种应用,你晓得不?

近几年&#xff0c;AI 的重大进展对我们的日常生活产生了积极影响。随着Google发布了《Google AI 原则》( Google AI Principles )&#xff0c;它们为 AI 发展提供了一个框架。由于这一领域的发展非常迅速&#xff0c;一些原则的最佳实践&#xff0c;如 “ 避免制造或加强不公平…

dhcp服务器显示主机名,linux – 当我没有在dhclient.conf中定义一个时,我的DHCP服务器如何知道我的机器的主机名?...

我正试图在我们的网络上解决与DHCP相关的一些时髦的DNS问题(我怀疑我们目前运行的是多个DHCP服务器),并且在试图解决这个问题时,我发现有一些奇怪的新服务器我只是建立.有问题的服务器是运行Ubuntu 9.10服务器的Xen虚拟机.物理Xen服务器也在我们的网络上,当我第一次在Xen中启动…

6月开招|工业互联才是王道,最高可达50k!

就在昨天&#xff0c;工信部发布了《工业互联网十个典型应用场景和五个重点行业实践》&#xff0c;具体介绍10个典型场景及5个重点行业工业互联网的实际应用情况&#xff0c;可以看到国内工业互联网正在蓬勃发展&#xff0c;欣欣向荣&#xff0c;工业4.0的浪潮正在席卷整个行业…

micropython安装ros_ROS2与STM32入门教程-microROS的linux版本

ROS2与STM32入门教程-micro_ros的linux版本说明&#xff1a;介绍如何安装使用micro_ros步骤&#xff1a;安装ros2版本foxy&#xff0c;查看教程加载ros2环境source ~/ros2_foxy/install/setup.bash也可以把这一句加到bashrc文件&#xff0c;新开终端就不用再输入安装micro-xrce…

php引用

php引用允许两个变量指向同一个内容。意思是&#xff0c;当这样做时 <?php $a&$b; ?> 意味着$a与$b指向同一变量&#xff0c;这并不是$a指向了$b或者相反,而是$a和$b指向了同一地方 如果对一个未定义的变量进行引用赋值、引用参数传递或引用返回&#xff0c;则会自…

2018 年最受欢迎的 Python 库,你都用过吗?

全世界只有3.14 % 的人关注了数据与算法之美前段时间&#xff0c;数据科学网站 KDnuggets 评选出了顶级 Python 库 Top15&#xff0c;领域横跨数据科学、数据可视化、深度学习和机器学习。推荐阅读《Python3.0科学计算指南》上图&#xff1a;根据 GitHub star 和贡献评选出的 2…

登录服务器修改数据库吗,如何修改服务器登录数据库 sa

如何修改服务器登录数据库 sa 内容精选换一换为确保华为云关系型数据库服务发挥出最优性能&#xff0c;用户可根据业务需求对用户创建的参数模板中的参数进行调整。您可以修改用户创建的数据库参数模板中的参数值&#xff0c;但不能更改默认数据库参数模板中的参数值。以下是您…

用NSubstitute来mock

Moq在.net中比较出名的mock框架&#xff0c;NSubstitute也是属于这类框架&#xff0c;使用方式也如出一辙&#xff0c;是通过实现子类来达到mock的效果。下面的测试方法都是按照 UnitTest的三板斧Arrange Act Assert来展开的&#xff0c;代码具体如下。using Microsoft.VisualB…

ubuntu安装mysql_Ubuntu18.04下安装MySQL

提示&#xff1a;以下操作均在root用户下进行&#xff0c;如在普通用户&#xff0c;请自行加上sudo&#xff01;# 查看有没有安装MySQL&#xff1a;dpkg -l | grep mysql# 安装MySQL&#xff1a;apt install mysql-server安装完成之后可以使用如下命令来检查是否安装成功&#…

shell 赋值

${parametre-default}与{parameter:-default}的输出等效&#xff0c;只当parameter被声明但值为null时候&#xff0c;二者才有区别。//变量未声明、未赋值[rootinstructor ~]# echo $a[rootinstructor ~]# echo ${a-1}1[rootinstructor ~]# echo ${a:-1}1//变量声明、赋值为nul…

居家好物┃超好用的擦窗神器保护腰椎尾椎久坐不累的美臀坐垫

▲卢sir特别推荐点击上图进入玩酷屋春节即将来临&#xff0c;小木特地挑选了好几款超级好用的居家生活产品。第一款&#xff1a;擦外窗神器&#xff0c; 颠覆你擦窗方式&#xff01;双面长柄 可伸缩 可折叠 可旋转便携擦玻璃神器第二款&#xff1a;天然抗菌除螨毛巾&#xff0c…

ML.NET Cookbook:(12)我想看看模型的系数

通常&#xff0c;一旦一个模型被训练出来&#xff0c;我们也会对“它学到了什么”感兴趣。例如&#xff0c;如果线性模型为我们认为重要的特征赋予零权重&#xff0c;则可能表明建模存在一些问题。线性模型的权重也可用作对“特征重要性”的估计。这是我们可以从训练的模型中提…

【读书笔记】《编写高效的JavaScript程序》

为什么80%的码农都做不了架构师&#xff1f;>>> 看到一篇文章&#xff0c;http://www.csdn.net/article/2012-11-20/2811887-writing-fast-memory-efficient-javascript/2 里面有个网页针对 原型链&#xff0c;模块化&#xff0c;模块化加缓存&#xff0c;进行了比…

Cloudera将被私有化,Hadoop时代或将落幕

北京时间 6 月 1 日晚&#xff0c;据 TechCrunch 报道 [1]&#xff0c;KKR 和 CD&R 将以 53 亿美元收购 Cloudera&#xff0c;Cloudera 将被私有化。截止到本文发稿时&#xff08;11 点 49 分&#xff09;&#xff0c;Cloudera 股票报价 15.94 美元&#xff0c;涨幅 23.95%…

mysql group_concat去重_MySQL group_concat() 函数用法

MySQL group_concat() 函数用法在使用 group by对数据进行分组后&#xff0c;如果需要对 select 的数据项进行字符串拼接&#xff0c;这时就需要用到group_concat()函数。1、基本用法group_concat()完整语法如下&#xff1a;group_concat([DISTINCT] 要连接的字段 [Order BY AS…

secureCRT常用设置

1、光标颜色 默认为黑色&#xff0c;非常不便&#xff0c;设置为白色。 Options–> Session Options –> Appearance –> Cursor –> 勾选use color选择白色 2、设置超时 Session Options –> Send protocol NO-OP every 输入60。 3、设置鼠标右键复制 Global O…

请问:如何写出没有BUG的代码?

全世界只有3.14 % 的人关注了数据与算法之美1947年9月9日&#xff0c;美国海军准将 Grace Hopper 在哈佛学院计算机实验室里使用 Mark II 和 Mark III 计算机进行研究工作。她的团队跟踪到 Mark II 上的一个错误&#xff0c;操作人员发现是由于一只飞蛾钻到了 Mark II 的继电器…

非常适合新手的redis cluster搭建过程

Redis集群演进过程Redis单节点主从复制&#xff1a;复制主要实现了数据的多机备份&#xff0c;以及对于读操作的负载均衡和简单的故障恢复。故障恢复无法自动化&#xff1b;写操作无法负载均衡&#xff1b;存储能力受到单机的限制。哨兵&#xff08;Sentinel&#xff09;&#…

mysql innodb事务中_MySQL InnoDB如何保证事务特性示例详解

前言如果有人问你“数据库事务有哪些特性”&#xff1f;你可能会很快回答出原子性、一致性、隔离性、持久性即ACID特性。那么你知道InnoDB如何保证这些事务特性的吗&#xff1f;如果知道的话这篇文章就可以直接跳过不看啦(#^.^#)先说结论&#xff1a;redo log重做日志用来保证事…