首页 > 其他分享 >重新整理 .net core 实践篇———承载[外篇]

重新整理 .net core 实践篇———承载[外篇]

时间:2023-07-17 23:33:51浏览次数:39  
标签:core Task AddSingleton private public 重新整理 readonly net svcs

前言

简单介绍一下承载。

正文

名称叫做承载,其实就是.net core 定义的一套长期运行的服务的规范。

这个服务可以是web服务,也可以是其他服务,比如tcp,或者一些监控服务。

这里以监控服务为例子:

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()
	{
		return $"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
	};
}
internal 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.UtcNow } { PerformanceMetrics.Create() }");
		}
	}

	public Task StopAsync(CancellationToken cancellationToken)
	{
		_scheduler.Dispose();

		return Task.CompletedTask;
	}
}

然后服务继承IHostedService, 有一个StartAsync 和 StopAsync, 也就是开始和停止服务。

然后在main里面进行注入:

new HostBuilder()
	.ConfigureServices(svcs =>
	// svcs.AddSingleton<IHostedService, PerformanceMetricsCollector>()
	svcs.AddHostedService<PerformanceMetricsCollector>()
	)
	.Build()
	.Run();

这里就是添加这个服务,然后Build,在run 起来就好了。

之所以我们要使用这个HostBuilder,其实就是为了里面帮我们定义的一些依赖注入。

比如一个长期服务需要用到这几个接口:

internal interface IMemoryMetricsCollector
{
	long GetUsage();
}

internal interface INetworkMetricsCollector
{
	long GetThroughput();
}

internal interface IProcessorMetricsCollector
{
	int GetUsage();
}

internal interface IMetricsDeliverer
{
	Task DeliverAsync(PerformanceMetrics counters);
}

他们的实现为:

internal class FakeMetricsCollector : IMemoryMetricsCollector, INetworkMetricsCollector, IProcessorMetricsCollector
{
	long INetworkMetricsCollector.GetThroughput()
	{
		return PerformanceMetrics.Create().Network;
	}

	long IMemoryMetricsCollector.GetUsage()
	{
		return PerformanceMetrics.Create().Memory;
	}

	int IProcessorMetricsCollector.GetUsage()
	{
		return PerformanceMetrics.Create().Processor;
	}
}

public class FackMetricsDeliverer : IMetricsDeliverer
{
	Task IMetricsDeliverer.DeliverAsync(PerformanceMetrics counter)
	{
		Console.WriteLine($"{ DateTimeOffset.UtcNow } { counter }");

		return Task.CompletedTask;
	}
}

然后你的服务就可以这样写:

internal class PerformanceMetricsCollector2 : IHostedService
{
	private IDisposable _scheduler;
	private readonly IProcessorMetricsCollector _processorMetricsCollector;
	private readonly IMemoryMetricsCollector _memoryMetricsCollector;
	private readonly INetworkMetricsCollector _networkMetricsCollector;
	private readonly IMetricsDeliverer _metricsDeliverer;

	public PerformanceMetricsCollector2(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;
	}
}

那么在builder的时候,你需要这样写:

var collector = new FakeMetricsCollector();

new HostBuilder()
	.ConfigureServices(svcs =>
	{
		svcs.AddSingleton<IProcessorMetricsCollector>(collector);
		svcs.AddSingleton<IMemoryMetricsCollector>(collector);
		svcs.AddSingleton<INetworkMetricsCollector>(collector);
		svcs.AddSingleton<IMetricsDeliverer, FackMetricsDeliverer>();

		svcs.AddHostedService<PerformanceMetricsCollector2>();
	})
	.Build()
	.Run();

这样就可以注入服务了。

有了依赖注入,那么可以做很多事情,比如说配置:

internal class FackMetricsDeliverer3 : IMetricsDeliverer
{
	private readonly TransportType _transport;

	private readonly EndPoint _deliverTo;

	private readonly ILogger _logger;

	private readonly Action<ILogger, DateTimeOffset,
		PerformanceMetrics, EndPoint, TransportType, Exception> _logForDelivery;

	public FackMetricsDeliverer3(IOptions<MetricsCollectionOptions> optionsAccessor, 
		ILogger<FackMetricsDeliverer3> logger)
	{
		var options = optionsAccessor.Value;
		_transport = options.Transport;
		_deliverTo = options.DeliverTo;
		_logger = logger;
		_logForDelivery = LoggerMessage.Define<DateTimeOffset, PerformanceMetrics,
			EndPoint, TransportType>(LogLevel.Information, 0, $"[{0}] Deliver performance counter {1} to {2} via {3}");
	}

	Task IMetricsDeliverer.DeliverAsync(PerformanceMetrics counters)
	{
		// Console.WriteLine($"[{DateTimeOffset.Now}] Deliver performance counter {counters} to {_deliverTo} via {_transport}");

		_logForDelivery(_logger, DateTimeOffset.UtcNow, counters, _deliverTo, _transport, null);

		return Task.CompletedTask;
	}
}

然后服务这样写:

internal class PerformanceMetricsCollector3 : IHostedService
{
	private IDisposable _scheduler;
	private readonly IProcessorMetricsCollector _processorMetricsCollector;
	private readonly IMemoryMetricsCollector _memoryMetricsCollector;
	private readonly INetworkMetricsCollector _networkMetricsCollector;
	private readonly IMetricsDeliverer _metricsDeliverer;
	private readonly TimeSpan _captureInterval;

	public PerformanceMetricsCollector3(IProcessorMetricsCollector processorMetricsCollector,
		IMemoryMetricsCollector memoryMetricsCollector,
		INetworkMetricsCollector networkMetricsCollector,
		IMetricsDeliverer metricsDeliverer, 
		IOptions<MetricsCollectionOptions> optionsAccesor)
	{
		_processorMetricsCollector = processorMetricsCollector;
		_memoryMetricsCollector = memoryMetricsCollector;
		_networkMetricsCollector = networkMetricsCollector;
		_metricsDeliverer = metricsDeliverer;
		_captureInterval = optionsAccesor.Value.CaptureInterval;
	}

	public Task StartAsync(CancellationToken cancellationToken)
	{
		_scheduler = new Timer(Callback, null, _captureInterval, _captureInterval);

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

然后注入的时候这样:

var collector = new FakeMetricsCollector();

new HostBuilder()
	.ConfigureAppConfiguration(builder =>
	{
		builder.AddJsonFile("appSettings.json");
	})
	.ConfigureServices((context, svcs) =>
	{
		svcs.AddSingleton<IProcessorMetricsCollector>(collector);
		svcs.AddSingleton<IMemoryMetricsCollector>(collector);
		svcs.AddSingleton<INetworkMetricsCollector>(collector);
		svcs.AddSingleton<IMetricsDeliverer, FackMetricsDeliverer2>();

		svcs.AddHostedService<PerformanceMetricsCollector3>();

		svcs.AddOptions().Configure<MetricsCollectionOptions>(context.Configuration.GetSection("MetricsCollection"));
	})
	.Build()
	.Run();

就是把appSettings.json进行注入。

这里有了配置之后,还有一个东西需要注意,那就是环境,比如不同的环境加载不同的配置:

new HostBuilder()
	// 设置host 环境
	.ConfigureHostConfiguration(builder => builder.AddCommandLine(args))
	// 设置app 环境
	.ConfigureAppConfiguration((context, builder) =>
	{
		builder.AddJsonFile("appSettings.json", optional: false);
		Console.WriteLine(context.HostingEnvironment.EnvironmentName);
		builder.AddJsonFile(path: $"appSettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
	})
	.ConfigureServices((context, svcs) =>
	{
		svcs.AddSingleton<IProcessorMetricsCollector>(collector);
		svcs.AddSingleton<IMemoryMetricsCollector>(collector);
		svcs.AddSingleton<INetworkMetricsCollector>(collector);
		svcs.AddSingleton<IMetricsDeliverer, FackMetricsDeliverer2>();

		svcs.AddHostedService<PerformanceMetricsCollector3>();

		svcs.AddOptions().Configure<MetricsCollectionOptions>(context.Configuration.GetSection("MetricsCollection"));
	})
	.Build()
	.Run();

有了不同环境不同的配置后,那么你还需要日志:

internal class FackMetricsDeliverer3 : IMetricsDeliverer
{
	private readonly TransportType _transport;

	private readonly EndPoint _deliverTo;

	private readonly ILogger _logger;

	private readonly Action<ILogger, DateTimeOffset,
		PerformanceMetrics, EndPoint, TransportType, Exception> _logForDelivery;

	public FackMetricsDeliverer3(IOptions<MetricsCollectionOptions> optionsAccessor, 
		ILogger<FackMetricsDeliverer3> logger)
	{
		var options = optionsAccessor.Value;
		_transport = options.Transport;
		_deliverTo = options.DeliverTo;
		_logger = logger;
		_logForDelivery = LoggerMessage.Define<DateTimeOffset, PerformanceMetrics,
			EndPoint, TransportType>(LogLevel.Information, 0, $"[{0}] Deliver performance counter {1} to {2} via {3}");
	}

	Task IMetricsDeliverer.DeliverAsync(PerformanceMetrics counters)
	{
		// Console.WriteLine($"[{DateTimeOffset.Now}] Deliver performance counter {counters} to {_deliverTo} via {_transport}");

		_logForDelivery(_logger, DateTimeOffset.UtcNow, counters, _deliverTo, _transport, null);

		return Task.CompletedTask;
	}
}

然后配置的时候这样配:

// about log
var collector = new FakeMetricsCollector();

new HostBuilder()
	// 设置host 环境
	.ConfigureHostConfiguration(builder => builder.AddCommandLine(args))
	// 设置app 环境
	.ConfigureAppConfiguration((context, builder) => {
		builder.AddJsonFile("appSettings.json", optional: false);
		Console.WriteLine(context.HostingEnvironment.EnvironmentName);
		builder.AddJsonFile(path: $"appSettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
	})
	.ConfigureServices((context, svcs) =>
	{
		svcs.AddSingleton<IProcessorMetricsCollector>(collector);
		svcs.AddSingleton<IMemoryMetricsCollector>(collector);
		svcs.AddSingleton<INetworkMetricsCollector>(collector);
		svcs.AddSingleton<IMetricsDeliverer, FackMetricsDeliverer3>();

		svcs.AddHostedService<PerformanceMetricsCollector3>();

		svcs.AddOptions().Configure<MetricsCollectionOptions>(context.Configuration.GetSection("MetricsCollection"));
	})
	.ConfigureLogging((context , builder)=>
	{
		builder.AddConfiguration(context.Configuration.GetSection("Logging"));
		builder.AddConsole();
	})
	.Build()
	.Run();

这里ConfigureLogging 配置了日志,同样配置了日志的配置。

至此就是一个.net core 定义的一个框架了。

里面有依赖注入、配置、环境、日志。

所以我们依赖这个框架就可以马上专注我们的业务。

下一节看下这种框架是如何设计的。

下一节承载的设计。

标签:core,Task,AddSingleton,private,public,重新整理,readonly,net,svcs
From: https://www.cnblogs.com/aoximin/p/17560719.html

相关文章

  • windows 安装telnet(含疑难杂症解决)
    一、常规安装办法常规遇到telnet不是内部或外部命令,表明telnet还未安装,安装即可。操作步骤:Win+R打开控制面板:输入control-程序和功能-启用或关闭Windows功能-勾选Telnet客户端一般以上步骤可以打开telnet二、还是无法使用......
  • Netty 作为 http client 请求https 的 get与post(二)双向ssl
    接Netty作为httpclient请求https的get与post,packagecom.example.demo;importio.netty.bootstrap.Bootstrap;importio.netty.buffer.ByteBuf;importio.netty.buffer.Unpooled;importio.netty.channel.*;importio.netty.channel.nio.NioEventLoopGroup;importio.net......
  • EF Core Like 模糊查询
    在EFCore中可用EF.Functions.Like()、StartWith、Contains、EndsWith实现模糊查询 EF.Functions.Like() 在EntityFrameworkCore2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在LINQ查询中直接调用。query=query.Where(d=>EF.Fun......
  • [论文研读]空天地一体化(SAGIN)的网络安全_A_Survey_on_Space-Air-Ground-Sea_Integra
    ------------恢复内容开始------------空天地一体化(SAGIN)的网络安全目前关注的方面:集中在安全通信、入侵检测、侧通道攻击、GPS欺骗攻击、网络窃听、消息修改/注入等方面,有些侧重于分析现有的安全威胁[20]、[21],有些提出了他们的攻击方法[14]、[22],还有一些则更多地侧重于SAG......
  • 网络编程 p2 InetAddress
    InetAddress类相关方法:getLocalHost():获取本机InetAddress对象;getByName():根据指定主机名/域名获取IP地址对象;getHostName():获取InetAddress对象的主机名;getHostAddress():获取InerAddress对象的地址;代码演示:importjava.net.InetAddress;importjava.net.UnknownHostEx......
  • .NET Core6.0 通过EF的方式如何链接MySQL
    之前一直用的是EF链接SQLServer今天聊一聊EF链接MySQL第一步我们首先创建一个简单的用户实体类 这里呢创建了一个主键为string类型的用户Id和一个用户名称第二步我们创建一个类库里面创建上下文类 但是这里需要注意引用的NuGet包和链接SQLServer的包有个是不一样的这是......
  • 命令_查看占用端口 netstat -ano|findstr "8080"
    查看占用端口 netstat-ano|findstr"8080" tasklist|findstr"12448"netstat-ano|findstr"8080"列说明1:协议 2:本地地址    3:外部地址   4:状态     5:PID查看PID对应的进程名称:tasklist|findstr"12448"......
  • net core-未来
    满足未来30年每周吃一个鸭子的需求为了计算从现在开始养多少只鸭子,以满足未来30年每周吃一个鸭子的需求,我们需要考虑以下几个因素:鸭子的寿命:鸭子的寿命通常在5到10年之间,具体取决于品种和饲养条件。我们可以假设鸭子的寿命为7年。繁殖周期:鸭子的繁殖周期平均为28天,这是鸭子......
  • 算法_贝叶斯网络学习_bayesian networks
    基本概念条件概率联合概率边缘概率链式法则随机变量的独立性条件独立性贝叶斯规则、贝叶斯概率推理和贝叶斯网络模型。stochastic,主要用作形容词,主要意思为“随机的;猜测的”R语言包R语言用lme4多层次(混合效应)广义线性模型(GLM),逻辑回归分析lme4广义线性混合模型......
  • net core-反向代理
    推荐使用框架:Yarp.ReverseProxy,微软开源的框架一基本使用varbuilder=WebApplication.CreateSlimBuilder(args);builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));varapp=builder.Build();app.MapRevers......