[ASP.NET Core 3框架揭秘] 服务承载系统[1]: 承载长时间运行的服务[上篇]

2023-12-25 16:48

本文主要是介绍[ASP.NET Core 3框架揭秘] 服务承载系统[1]: 承载长时间运行的服务[上篇],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

借助.NET Core提供的承载(Hosting)系统,我们可以将任意一个或者多个长时间运行(Long-Running)的服务寄宿或者承载于托管进程中。ASP.NET Core应用仅仅是该承载系统的一种典型的服务类型而已,任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载。

一、承载长时间运行服务

老幺网 www.laoyao.org

一个ASP.NET Core应用本质上是一个需要长时间运行的服务,开启这个服务是为了启动一个网络监听器。当监听到抵达的HTTP请求之后,该监听器会将请求传递给应用提供的管道进行处理。管道完成了对请求处理之后会生成HTTP响应,并通过监听器返回客户端。除了这种最典型的承载服务,我们还有很多其他的服务承载需求,下面通过一个简单的实例来演示如何承载一个服务来收集当前执行环境的性能指标

我们演示的承载服务会定时采集并分发当前进程的性能指标。简单起见,我们只关注处理器使用率、内存使用量和网络吞吐量这3种典型的性能指标,为此定义了下面的PerformanceMetrics类型。我们并不会实现真正的性能指标收集,所以定义静态方法Create利用随机生成的指标数据创建一个PerformanceMetrics对象。

public class PerformanceMetrics
{private static readonly Random _random = new Random();public int Processor { get; set; }public long Memory { get; set; }public long Network { get; set; }public override string ToString() => $"CPU: {Processor * 100}%; Memory: {Memory / (1024 * 1024)}M; Network: {Network / (1024 * 1024)}M/s";public static PerformanceMetrics Create() => new PerformanceMetrics{Processor = _random.Next(1, 8),Memory = _random.Next(10, 100) * 1024 * 1024,Network = _random.Next(10, 100) * 1024 * 1024};
}

承载服务通过IHostedService接口表示,该接口定义的StartAsync方法和StopAsync方法可以启动与关闭服务。我们将性能指标采集服务定义成如下这个实现了该接口的PerformanceMetricsCollector类型。在实现的StartAsync方法中,我们利用Timer创建了一个调度器,每隔5秒它会调用Create方法创建一个PerformanceMetrics对象,并将它承载的性能指标输出到控制台上。这个Timer对象会在实现的StopAsync方法中被释放。

public sealed class PerformanceMetricsCollector : IHostedService
{private IDisposable _scheduler;public Task StartAsync(CancellationToken cancellationToken){_scheduler = new Timer(Callback, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));return Task.CompletedTask;static void Callback(object state){Console.WriteLine($"[{DateTimeOffset.Now}]{PerformanceMetrics.Create()}");}}public Task StopAsync(CancellationToken cancellationToken){_scheduler?.Dispose();return Task.CompletedTask;}
}

承载系统通过IHost接口表示承载服务的宿主,该对象在应用启动过程中采用Builder模式由对应的IHostBuilder对象来创建。HostBuilder类型是对IHostBuilder接口的默认实现,所以可以采用如下方式创建一个HostBuilder对象,并调用其Build方法来提供作为宿主的IHost对象。

class Program
{static void Main(){new HostBuilder().ConfigureServices(svcs => svcs.AddSingleton<IHostedService, PerformanceMetricsCollector>()).Build().Run();}
}

在调用Build方法之前,可以调用IHostBuilder接口的ConfigureServices方法将PerformancceMetricsCollector注册成针对IHostedService接口的服务,并将生命周期模式设置成Singleton。除了采用普通的依赖服务注册方式,针对IHostedService服务的注册还可以调用IServiceCollection接口的AddHostedService<THostedService>扩展方法来完成,如下所示的编程方式与上面是完全等效的。

class Program
{static void Main(){new HostBuilder().ConfigureServices(svcs => svcs.AddHostedService<PerformanceMetricsCollector>()).Build().Run();}
}

最后调用Run方法启动通过IHost对象表示的承载服务宿主,进而启动由它承载的PerformancceMetricsCollector服务,该服务将以下图所示的形式每隔5秒显示由它“采集”的性能指标。(源代码从这里下载)

10-1

二、依赖注入

服务承载系统无缝整合了依赖注入框架。从上面给出的代码可以看出,针对承载服务的注册实际上就是将它注册到依赖注入框架中。既然承载服务实例最终是通过依赖注入框架提供的,那么它自身所依赖的服务当然也可以注册到依赖注入框架中。下面将PerformanceMetricsCollector承载的性能指标收集功能分解到由4个接口表示的服务中,其中IProcessorMetricsCollector、IMemoryMetricsCollector和INetworkMetricsCollector接口代表的服务分别用于收集3种对应性能指标,而IMetricsDeliverer接口表示的服务则负责将收集的性能指标发送出去。

public interface IProcessorMetricsCollector
{int GetUsage();
}
public interface IMemoryMetricsCollector
{long GetUsage();
}
public interface INetworkMetricsCollector
{long GetThroughput();
}public interface IMetricsDeliverer
{Task DeliverAsync(PerformanceMetrics counter);
}

我们定义的FakeMetricsCollector类型实现了3个性能指标采集接口,它们采集的性能指标直接来源于通过静态方法Create创建的PerformanceMetrics对象。FakeMetricsDeliverer类型实现了IMetricsDeliverer接口,在实现的DeliverAsync方法中,它直接将PerformanceMetrics对象承载性能指标输出到控制台上。

public class FakeMetricsCollector :IProcessorMetricsCollector,IMemoryMetricsCollector,INetworkMetricsCollector
{long INetworkMetricsCollector.GetThroughput() => PerformanceMetrics.Create().Network;int IProcessorMetricsCollector.GetUsage() => PerformanceMetrics.Create().Processor;long IMemoryMetricsCollector.GetUsage() => PerformanceMetrics.Create().Memory;
}public class FakeMetricsDeliverer : IMetricsDeliverer
{public Task DeliverAsync(PerformanceMetrics counter){Console.WriteLine($"[{DateTimeOffset.UtcNow}]{counter}");return Task.CompletedTask;}
}

由于整个性能指标的采集工作被分解到4个接口表示的服务之中,所以可以采用如下所示的方式重新定义承载服务类型PerformanceMetricsCollector。如下面的代码片段所示,可以直接在构造函数中注入4个依赖服务。对于在StartAsync方法创建的调用器来说,它会利用3个对应的服务采集3种类型的性能指标,并利用IMetricsDeliverer服务将其发送出去。

public sealed class PerformanceMetricsCollector : IHostedService
{private readonly IProcessorMetricsCollector _processorMetricsCollector;private readonly IMemoryMetricsCollector _memoryMetricsCollector;private readonly INetworkMetricsCollector _networkMetricsCollector;private readonly IMetricsDeliverer _MetricsDeliverer;private IDisposable _scheduler;public PerformanceMetricsCollector(IProcessorMetricsCollector processorMetricsCollector,IMemoryMetricsCollector memoryMetricsCollector,INetworkMetricsCollector networkMetricsCollector,IMetricsDeliverer MetricsDeliverer){_processorMetricsCollector = processorMetricsCollector;_memoryMetricsCollector     ,= memoryMetricsCollector;_networkMetricsCollector = networkMetricsCollector;_MetricsDeliverer = MetricsDeliverer;}public Task StartAsync(CancellationToken cancellationToken){_scheduler = new Timer(Callback, null, TimeSpan.FromSeconds(5),TimeSpan.FromSeconds(5));return Task.CompletedTask;async void Callback(object state){var counter = new PerformanceMetrics{Processor = _processorMetricsCollector.GetUsage(),Memory = _memoryMetricsCollector.GetUsage(),Network = _networkMetricsCollector.GetThroughput()};await _MetricsDeliverer.DeliverAsync(counter);}}public Task StopAsync(CancellationToken cancellationToken){_scheduler?.Dispose();return Task.CompletedTask;}
}

在调用IHostBuilder接口的Build方法创建作为宿主的IHost对象之前,包括承载服务在内的所有服务都可以通过它的ConfigureServices方法进行注册,我们采用如下方式注册了作为承载服务的PerformanceMetricsCollector和它依赖的4个服务。修改后的程序启动之后同样会在控制台上看到上面图片所示的输出结果。(源代码从这里下载)

class Program
{static void Main(){var collector = new FakeMetricsCollector();new HostBuilder().ConfigureServices(svcs => svcs  .AddSingleton<IProcessorMetricsCollector>(collector).AddSingleton<IMemoryMetricsCollector>(collector).AddSingleton<INetworkMetricsCollector>(collector).AddSingleton<IMetricsDeliverer, FakeMetricsDeliverer>().AddSingleton<IHostedService, PerformanceMetricsCollector>()).Build().Run();}
}

服务承载系统[1]: 承载长时间运行的服务[上篇]
服务承载系统[2]: 承载长时间运行的服务[下篇]
服务承载系统[3]: 服务承载模型[上篇]
服务承载系统[4]: 服务承载模型[下篇]
服务承载系统[5]: 承载服务启动流程[上篇]
服务承载系统[6]: 承载服务启动流程[下篇]

这篇关于[ASP.NET Core 3框架揭秘] 服务承载系统[1]: 承载长时间运行的服务[上篇]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/536217

相关文章

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹