Dotnet Core下的Channel, 你用了吗?

今天给大家分享一个微软官方的好东西:Channel。

前言

今天给大家分享一个微软官方的生产者/消费者方案的特性解决:Channel。

Channel在System.Threading.Channels命名空间下,Core 2.1使用时,需要从Nuget上安装。

% dotnet add package System.Threading.Channels

而在Core 3.0 preview 7开始,就直接包含在框架中了。

这是一个相对较新的特性。从Core 2.1开始加入,现在版本是5.0.0(嗯,这个版本号有点骗人,Channel的第一个版本就是4.5.0)。

Channel能做什么?

逻辑上,Channel实际就是一个高效的、线程安全的队列,支持在生产者和消费者之间传递数据。

利用Channel,通过发布和订阅,可以将生产者和消费者分开。生产者Producer负责接收请求,并写入Channel,而消费者Consumer为每个进入Channel的数据执行处理。这样做,一方面可以使生产者和消费者并行工作来提高性能,另一方面,可以通过创建更多的生产者或消费者来提高应用的吞吐量。

    为防止非授权转发,这儿给出本文的原文链接:https://www.cnblogs.com/tiger-wang/p/14068973.html

下面,我们以一个实际例子,来解释这个特性。

创建Channel

Channel提供了一个静态Channel类,提供了两个公开方法来创建两种类型的Channel。

  • CreateUnbounded - 创建一个具有无限容量的Channel。

  • CreateBounded - 创建一个具有有限容量的Channel。

人通常来说,这两种方式使用上没有太大的区别。实际应用中,具体要看生产和消费的速度,以及期望产生的结果。有限容量的Channel,容量是有上限的,到达上限后,可以让生产者非阻塞等待消费者使用并释放Channel容量后再继续。这种方式,好处是可以控制生产的速度,控制系统资源的使用,缺点也是。因为控制速度意味着生产速度会被限制,甚至停止。而无限容量,生产者可以全速进行生产。但也有缺点,如果消费者的消费速度低于生产者,Channel的资源使用会无限增加,会有服务器资源耗尽的可能。

今天的例子,我们使用无限Channel。

var channel = Channel.CreateUnbounded<string>();

非常简单的一行代码,就创建了一个无限容量的Channel。

我们定义这个Channel用来保存字符串对象。

创建方法是一个通用的工厂方法,所以我们可以为需要使用的任何类型的对象和数据创建Channel。

Channel有两个属性:阅读器返回ChannelReader,写入器返回ChannelWriter。

写入Channel

使用写入器ChannelWriter,可以对Channel进行写入操作。ChannelWriter提供了以下几个方法:

  • WriteAsync - 异步写入

  • WaitToWriteAsync - 非阻塞等待,直到有空间可写入时或Channel关闭时,返回true/false

  • TryWrite - 尝试写入

  • Complete - 标记Channel为关闭,并不再写入数据到该Channel

  • TryComplete - 尝试标记Channel为关闭。

这几个方法很容易理解,就不解释了。

在本文的例子里,我用了:

await channel.Writer.WriteAsync("New message");

读取Channel

使用阅读器ChannelReader从Channel进行数据的读取。也提供了几个方法:

  • ReadAsync - 异步读取

  • ReadAllAsync - 异步读取Channel中的所有数据

  • TryRead - 尝试读取

  • WaitToReadAsync - 非阻塞等待,直到有数据可读取或Channel关闭时,返回true/false

不同的消费者模式,会用到不同的读取方法。这个根据经验来写就好。

本文的例子中,我是采用WaitToReadAsync和ReadAsync配合来使用的:

while (await ChannelReader.WaitToReadAsync()){    if (ChannelReader.TryRead(out var timeString))    {          /***/    }}

WaitToReadAsync是一个非阻塞等待,在有消息可读或Channel关闭时,才会唤醒并继续。

考虑到有多个消费者的情况,有可能别的线程已经进行了读取,这儿使用TryRead进行读取操作。

要注意:数据的同步工作是由Channel进行管理的。Channel会确保多个消费者不会读到相同的数据。Channel同时也管理数据的次序。

示例代码

今天的示例代码我放到了Github上。链接是文章最后。

这个例子中,我做了三个场景。

首先是Channel。我使用了无限Channel。然后是创建生产者和消费者。数据传输过程就简单化了,生产者只简单将一个字符串写入到Channel。消费者也是,简单等待并从Channel读取数据字符串,写入控制台。

三个场景分别是:

单一生产者/单一消费者

这个例子中,创建了一个生产者和一个消费者。两者的任务都是并发启动的。

里面的延时,是用来模拟工作负载的。

多个生产者/单一消费者

这个例子中有两个生产者。通常在应用中有多个生产者时,我们需要确保生产与单个消费者所能处理的消息数量大致相当,这样能更好地利用服务器资源。

单一生产者/多个消费者

这个其实是应用中最常见的情况,就是产生消息很快,但处理工作相关较慢,而且工作也更密集。这种情况,实际应用中我们可以通过扩大消费者数量来满足生产的需求。

总结

最近的项目在做一个大数据的采集,用到了一些Channel的技术。然后发现网上这部分内容很少,就做了个例子,写了这个文章。

Channel内容本身并不多,但用着很方便,而且实际应用中,比想像的更强大。它可以简化很多生产者/消费者模式的使用,而且,任务间交换数据,使用Channel会更方便,更直接。

示例代码在:https://github.com/humornif/Demo-Code/tree/master/0033/demo

(0)

相关推荐

  • 万字长文书写RabbitMQ最全见解!以后再也不用到处去搜索了呀!

    典型应用场景 1.跨系统的异步通信 人民银行二代支付系统,使用重量级消息队列 IBM MQ,异步,解耦,削峰都有体现. 2.应用内的同步变成异步 秒杀:自己发送给自己 3.基于Pub/Sub模型实现的 ...

  • (1条消息) RabbitMQ六种通信模式介绍

    文章目录 一.简介 二.代码实现 三.程序运行效果 四.模式总结 一.简介 本篇博客所讲的为RabbitMQ六种通信模式之一的发布与订阅模式,官网给出的图如下所示: 简单模式与工作模式2个案例中,只有 ...

  • 还不知道异步队列?点进来看!

    你不知道的分布式异步队列 关于异步队列你解多少? 它被誉为大数据高并发的终极解决方案. 来先给你介绍几种: RabbitQM:是爱立信的产品,基于erlang语言(函数式编程大数据 scala语言) ...

  • java之学习记录 7 - 2 - RabbitMQ安装及使用

    怎么用RabbitMQ 想要安装RabbitMQ,必须先安装erlang语言环境,类似安装tomcat,必须先安装JDK 查看匹配的版本:https://www.rabbitmq.com/which- ...

  • 九张图带你了解Kafka

    Kafka非常重要,每个人都应该了解本文的内容. 现在,每个公司都在互联网系统中使用Kafka. Kafka似乎是解决分布式并提高系统吞吐量的最佳松耦合解决方案之一. 我大约6年前开始使用Kafka. ...

  • dotNET Core WebAPI 统一处理(返回值、参数验证、异常)

    现在 Web 开发比较流行前后端分离,我们的产品也是一样,前端使用Vue,后端使用 dotNet Core WebAPI ,在写 API 的过程中有很多地方需要统一处理: 文档 参数验证 返回值 异常 ...

  • 温故知新,DotNet Core SDK和.Net CLI十八般武艺

    简介 .NET命令行接口 (CLI) 工具是用于开发.生成.运行和发布.NET应用程序的跨平台工具链. https://docs.microsoft.com/zh-cn/dotnet/core/too ...

  • dotNET Core 3.X 使用 Web API

    现在的 Web 开发大多都是前后端分离的方式,后端接口的正确使用显得尤为重要,本文讲下在 dotNET Core 3.X 下使用 Web API . 环境 操作系统:Mac IDE:Rider dot ...

  • dotNET Core 3.X 使用 Jwt 实现接口认证

    在前后端分离的架构中,前端需要通过 API 接口的方式获取数据,但 API 是无状态的,没有办法知道每次请求的身份,也就没有办法做权限的控制.如果不做控制,API 就对任何人敞开了大门,只要拿到了接口 ...

  • Azure 无服务器 Function 函数计算服务 dotnet core 3.1 创建和部署入门

    本文用的是 世纪互联 的 Azure.cn 版本,这个版本因为是在国内,所以网速会快超级超级多.使用 世纪互联 的版本需要一块钱哦,用一块钱就能进入一个月的免费试用.本文主要告诉小伙伴如何使用 Azu ...

  • WPF dotnet core 的 Blend SDK Behaviors 库

    之前版本是通过安装 Blend SDK 支持 Behaviors 库的,但是这个方法都是通过引用 dll 的方式,不够优雅.在升级到 dotnet core 3.0 的时候就需要使用 WPF 官方团队 ...

  • dotNET Core 3.X 依赖注入

    如果说在之前的 dotNET 版本中,依赖注入还是个比较新鲜的东西,那么在 dotNET Core 中已经是随处可见了,可以说整个 dotNET Core 的框架是构建在依赖注入框架之上.本文讲解下对 ...

  • 一文说通Dotnet Core的中间件

    前几天,公众号后台有朋友在问Core的中间件,所以专门抽时间整理了这样一篇文章. 一.前言 中间件(Middleware)最初是一个机械上的概念,说的是两个不同的运动结构中间的连接件.后来这个概念延伸 ...

  • 一文说通Dotnet Core的后台任务

    这是一文说通系列的第二篇,里面有些内容会用到第一篇中间件的部分概念.如果需要,可以参看第一篇:一文说通Dotnet Core的中间件 一.前言 后台任务在一些特殊的应用场合,有相当的需求. 比方,我们 ...