分类 💯C# 下的文章 - 社畜猿
首页
🕒归档
📖留言板
💌关于
搜 索
1
我的小世界——博客上线啦
1,323 阅读
2
写于小程序上线之前
1,209 阅读
3
近期准备上线本站小程序
868 阅读
4
利用CSS3制作旋转3D立方体
745 阅读
5
RabbitMq C# .NET 接收广播 消费者 订阅者 简单使用 ~~
381 阅读
💯C#
🐘PHP
📝烂笔头
♉侃侃
登录
搜 索
标签搜索
React Native
rabbmitmq
thinkphp
Mysql
Typecho
socket
uniapp
tinkphp
php
echart
C语言
程序猿
累计撰写
130
篇文章
累计收到
17
条评论
首页
栏目
💯C#
🐘PHP
📝烂笔头
♉侃侃
页面
🕒归档
📖留言板
💌关于
用户登录
登录
找到
47
篇与
相关的结果
2021-07-12
c# 连接mysql关闭清空缓冲池—记录
c# 连接mysql关闭清空缓冲池
2021年07月12日
22 阅读
0 评论
1 点赞
2021-04-09
c# 做ping检测
ping检测c#版
2021年04月09日
58 阅读
0 评论
2 点赞
2021-03-11
C#直接连接MySql
1. 引入MySql.data.dll首先在创建工程后要引入MySql.Data.dll文件。在创建的项目上右键找到Nuget程序包。然后按照红框内的方式搜索,一般第一个即为MySql.data.dll文件,点击下载导入即可。SDK引入之后下面我们就可以进行对MySql的操作啦。。。 注:一定要先下载好MySql之后才可以呀,最好先创建一个表作为测试表,不然测试都不好测试。2. 与数据库建立连接先进行一个简单的连接,在这里,建立连接用到的是MySqlConnection这个类。 第一个string值中的值分别代表:server:ip地址 port:端口号 database:数据库名称 user:用户名 password:密码 数据库在本地的话ip可以写成127.0.0.1或者localhost,这两个都代表是本地IPclass Program { static void Main(string[] args) { //这是用来连接数据库的信息, string connect = "server=127.0.0.1;port=3306;database=mygame;user=root;password=root;"; //注册连接信息 MySqlConnection conn = new MySqlConnection(connect); conn.Open();//开始连接数据库 conn.Close();//关闭连接数据库 } }在open()开始连接的时候是可能报错的,比如端口号写错等等,为了捕捉异常可以这么修改。class Program { static void Main(string[] args) { //这是用来连接数据库的信息, string connect = "server=127.0.0.1;port=3306;database=mygame;user=root;password=root;"; //注册连接信息 MySqlConnection conn = new MySqlConnection(connect); try { conn.Open();//开始连接数据库 } catch (Exception e) { Console.WriteLine(e); } finally { conn.Close();//关闭连接数据库 } } }3. 操作数据库查询现在已经建立好连接了,下面进行操作数据库的部分。用到MySqlCommand类来根据命令进行操作,利用MySqlDataReader类进行获取读到的数据。 reader.Reader()方法调用后,reader读取了一行数据,调用一次向下读一行,重复调用会一直往下读,利用reader[0]、reader[1]。。。可以获取这一行某一列的数据。 reder的放回值为bool值,如果返回为false即已经读到了最后一行了。 try { conn.Open();//开始连接数据库 string sql = "select * from tablename";//sql命令 MySqlCommand cmd = new MySqlCommand(sql, conn); MySqlDataReader reader = cmd.ExecuteReader(); reader.Read(); Console.WriteLine(reader[0]);//打印第一行第一列的数据 }插入插入即“增”数据,设定好MySql命令后,使用command命令即可实现增加数据的功能。 void Insert() { string connectStr = "server=127.0.0.1;port=3306;database=mygame;user=root;password=root;"; MySqlConnection conn = new MySqlConnection(connectStr); try { conn.Open(); string sqlCmd = "insert into tablename(colname,colname...) values(value,value...)"; MySqlCommand mySqlCommand = new MySqlCommand(sqlCmd, conn); int result = mySqlCommand.ExecuteNonQuery();//返回值为影响了几行数据 } catch (Exception e) { Console.WriteLine(e); } finally { conn.Close(); } }更新数据更新数据即“改”数据,使用update的sql命令即可。 注意,要更新的行数使用id或者不重复的值来区分一下。void update() { string connectStr = "server=127.0.0.1;port=3306;database=mygame;user=root;password=root;"; MySqlConnection conn = new MySqlConnection(connectStr); try { conn.Open(); string sqlCmd = "update tablename set colname='' ,colname='' where id= ";// MySqlCommand mySqlCommand = new MySqlCommand(sqlCmd, conn); int result = mySqlCommand.ExecuteNonQuery();//返回值为影响了几行数据 } catch (Exception e) { Console.WriteLine(e); } finally { conn.Close(); } }删除“删”数据,也很简单,使用delete命令指定表和行数之后就可以删除了。void delete() { string connectStr = "server=127.0.0.1;port=3306;database=mygame;user=root;password=root;"; MySqlConnection conn = new MySqlConnection(connectStr); try { conn.Open(); string sqlCmd = "delete from tablename where id= "; MySqlCommand mySqlCommand = new MySqlCommand(sqlCmd, conn); int result = mySqlCommand.ExecuteNonQuery();//返回值为影响了几行数据 } catch (Exception e) { Console.WriteLine(e); } finally { conn.Close(); } }
2021年03月11日
150 阅读
0 评论
6 点赞
2021-03-10
RabbitMq C# .NET 接收广播 消费者 订阅者 简单使用 ~~
其实RabbitMq的使用挺简单。。官网的实例,我加点解释大家看看就行。。。 using System; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System.Text; class ReceiveLogs { public static void Main() { // 声明方法1 var factory = new ConnectionFactory() { HostName = "服务器ip(不带端口的哦,例子 192.168.0.1 )", UserName = "用户名", Password = "密码", Port = 0000 // 端口号 int值哦 }; // 声明方法2 var factory = new ConnectionFactory() { Uri = "amqp://用户名:密码@服务器IP地址:端口号/"}; using(var connection = factory.CreateConnection()) using(var channel = connection.CreateModel()) { channel.ExchangeDeclare(exchange: "问后端要", type: "问后端要信息类型"); var queueName = channel.QueueDeclare().QueueName;// 随机名字 channel.QueueBind(queue: queueName, exchange: "问后端要", routingKey: "问后端要"); Console.WriteLine(" [*] Waiting for logs."); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); Console.WriteLine(" [x] ", message); }; channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); } } }
2021年03月10日
381 阅读
0 评论
0 点赞
2021-03-10
C#调用RabbitMQ实现消息队列
前言我在刚接触使用中间件的时候,发现,中间件的使用并不是最难的,反而是中间件的下载,安装,配置才是最难的。所以,这篇文章我们从头开始学习RabbitMq,真正的从头开始。关于消息队列其实消息队列没有那么神秘,我们这样想一下,用户访问网站,最终是要将数据以HTTP的协议的方式,通过网络传输到主机的某个端口上的。那么,接收数据的方式是什么呢?自然是端口监听啦。那消息队列是什么就很好解释了?它就是端口监听,接到数据后,将数据排列起来。那这件事,我们不用中间件能做吗?当然能做啦,写个TCP/UDP/Socket的软件就可以做啦。举个简单的例子,如下图:既然自己可以做消息队列,那为什么要用RabbitMQ?因为,RabbitMQ成熟的开源中间件,可靠性有保证,bug少,性能也非常好。而C#代码默认是使用托管内存的,所以,想写出媲美RabbitMQ性能的消息队列,就必须离开我们常用的托管内存,使用非托管内存,但这个代价就太大了;而且最终能否达到RabbitMQ的性能水平还是个未知数。还有就是RabbitMQ除了基础的消息队列管理,还有很多很强大的额外功能,而自己开发消息队列,很难如此尽善尽美。----------------------------------------------------------------------------------------------------我们还会发现,在消息队列里有很多概念,什么消息总线啊,什么工作队列啊等等。要怎么理解这些概念呢?很简单,不要去理解。这些概念其实是人家代码架构的模式,不要去理解他们,【记】就完了,人家的中间件就是按照这个模式工作的。比如,我写了一个接收消息的总控制器,然后我为他命名为总线,那这个控制器就是总线,没有理由,这就是定义。准备工作首先,我们访问官网【https://www.rabbitmq.com/】,点击Get Started。然后,网站会自动跳转到当前首页Get Started的锚点位置,如下图:Get Started锚点:然后我们点击DownLoad+Installation,进入到下载界面。在下载页面中,我们找到安装指南,然后在点击官网推荐的Windows系统的安装包,如下图:现在,我们进入了Windows安装指南界面了。首先,我们看一下预览信息,如下图:在预览里,我们得知,安装RabbitMQ有两种方法,一种是使用Chocolatey安装,一种是使用官方安装包安装。Chocolatey是什么呢?随手百度一下,原来他是一个软件包管理工具,也就是说,Chocolatey是类似于Nuget的一种工具。由于Chocolatey的使用,我不是很熟悉,所以,这里选择使用官方安装包安装。点击【Using the official installer】,我们进入了【Using the official installer】对应的锚点,如下图。在【Using the official installer】段落里找到有推荐标志的安装包,然后下载。 下载完成后,我们可以得到这样一个安装包,如下图:除了下载安装包,我们还会发现,在【Using the official installer】段落里,有提醒我们,RabbitMQ是有依赖的,依赖一个Erlang语言的框架(类似于C#语言的NetFramework)。我们可以发现,在依赖的段落里,官网非常坑的给出了三个链接网址,如下:supported version of Erlang:https://www.rabbitmq.com/which-erlang.htmlWindows installer:https://www.erlang.org/downloadsErlang Solutions:https://www.erlang-solutions.com/resources/download.html因为,我们是无法通过文字描述来判断,哪一个是真的依赖框架的下载地址,所以只好每个都点击进去看看。。。打开网址后发现,在后两个网址中都可以找到框架下载地址,但第二个地址明显更友好一点,所以我们在第二个网址内下载Erlang的框架。 下载完成得到如下图文件: PS:这里下载的是OTP的22.1的版本,我的理解是Erlang等于C#语言,而OTP等于NetFramework。安装Erlang\OTP首先,我们运行otp_win64_22.1.exe,安装依赖框架Erlang\OTP。安装完成后,设置环境变量如下:然后运行CMD,输入erl,测试安装是否成功,如下图:安装成功。安装rabbitmq-server安装完依赖后,我们接着安装rabbitmq-server-3.8.0.exe。【rabbitmq-server-3.8.0.exe】?从这个文件名上,我们发现了一个问题,那就是,我们即将安装的RabbitMQ,是一个服务端啊。什么?服务端?难道还有客户端???其实这也很好理解,想一下最开始我举的那个例子,消息队列是需要一个监听端口的服务端的,然后客户端向这个服务端发送请求。这样是不是就很好的理解RabbitMQ了呢:)----------------------------------------------------------------------------------------------------安装完RabbitMQ服务端后,我们还是启动CMD,用命令行来查看下安装状态。首先输入下面的命令,将路径定位到RabbitMQ的路径下:【CD /D C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.0\sbin】然后输入rabbitmqctl status查看状态。启动管理工具的命令行:rabbitmq-plugins enable rabbitmq_management。启动成功后,在浏览器输入地址http://127.0.0.1:15672/,进入管理页面,账户密码都是guest。RabbitMQ还有很多常用命令,大家可以自行百度。----------------------------------------------------------------------------------------------------到此,RabbitMQ服务端的环境配置好了,正常情况,这些配置应该在服务器进行,但我为了测试方便,就把服务端也安装在本机了,因此我下面调用RabbitMQ时,连接的主机IP都是localhost。RabbitMQ应用首先创建两个控制台应用程序,KibaRabbitMQSend和KibaRabbitMQReceived。然后引入RabbitMQ的开源类库。在C#里使用RabbitMQ开源类库非常简单,可以去官网下载一个.NET版本的RabbitMQ客户端类库,也可以直接在Nuget上搜索RabbitMQ,然后安装,如下图:KibaRabbitMQSend安装完RabbitMQ开源类库后,我们编写代码,实现向RabbitMQ服务器发送消息,代码如下:`static` `void` `Main(``string``[] args)` `{` `var` `factory = ``new` `ConnectionFactory();` `factory.HostName = ``"localhost"``;``//主机名,Rabbit会拿这个IP生成一个endpoint,这个很熟悉吧,就是socket绑定的那个终结点。` `factory.UserName = ``"guest"``;``//默认用户名,用户可以在服务端自定义创建,有相关命令行` `factory.Password = ``"guest"``;``//默认密码` `using` `(``var` `connection = factory.CreateConnection())``//连接服务器,即正在创建终结点。` `{` `//创建一个通道,这个就是Rabbit自己定义的规则了,如果自己写消息队列,这个就可以开脑洞设计了` `//这里Rabbit的玩法就是一个通道channel下包含多个队列Queue` `using` `(``var` `channel = connection.CreateModel())` `{` `channel.QueueDeclare(``"kibaQueue"``, ``false``, ``false``, ``false``, ``null``);``//创建一个名称为kibaqueue的消息队列` `var` `properties = channel.CreateBasicProperties();` `properties.DeliveryMode = 1;` `string` `message = ``"I am Kiba518"``; ``//传递的消息内容` `channel.BasicPublish(``""``, ``"kibaQueue"``, properties, Encoding.UTF8.GetBytes(message)); ``//生产消息` `Console.WriteLine($``"Send:"``);` `}` `}` `}` 然后我们使用命令行rabbitmqctl list_queues,去RabbitMQ的服务器查看当前消息队列,如下图:运行代码。可以看到,我们的消息已经发送成功了。KibaRabbitMQReceived现在我们编写接收消息代码,如下:`static` `void` `Main(``string``[] args)` `{` `var` `factory = ``new` `ConnectionFactory();` `factory.HostName = ``"localhost"``;` `factory.UserName = ``"guest"``;` `factory.Password = ``"guest"``;` `using` `(``var` `connection = factory.CreateConnection())` `{` `using` `(``var` `channel = connection.CreateModel())` `{` `channel.QueueDeclare(``"kibaQueue"``, ``false``, ``false``, ``false``, ``null``);` `/* 这里定义了一个消费者,用于消费服务器接受的消息` `* C#开发需要注意下这里,在一些非面向对象和面向对象比较差的语言中,是非常重视这种设计模式的。` `* 比如RabbitMQ使用了生产者与消费者模式,然后很多相关的使用文章都在拿这个生产者和消费者来表述。` `* 但是,在C#里,生产者与消费者对我们而言,根本算不上一种设计模式,他就是一种最基础的代码编写规则。` `* 所以,大家不要复杂的名词吓到,其实,并没那么复杂。` `* 这里,其实就是定义一个EventingBasicConsumer类型的对象,然后该对象有个Received事件,` `* 该事件会在服务接收到数据时触发。` `*/` `var` `consumer = ``new` `EventingBasicConsumer(channel);``//消费者` `channel.BasicConsume(``"kibaQueue"``, ``true``, consumer);``//消费消息` `consumer.Received += (model, ea) =>` `{` `var` `body = ea.Body;` `var` `message = Encoding.UTF8.GetString(body);` `};` `}` `}` `}`运行代码。 然后我们使用命令行rabbitmqctl list_queues,去RabbitMQ的服务器查看当前消息队列,如下图:可以看到,消息已经被使用了。----------------------------------------------------------------------------------------------------现在我们在发送代码出做一个for循环,看看消息接收速度是什么样的,代码如下,for循环了100次,每次间隔3秒。`for` `(``int` `i = 0; i < 100; i++)` `{` `channel.QueueDeclare(``"kibaQueue"``, ``false``, ``false``, ``false``, ``null``);``//创建一个名称为kibaQueue的消息队列` `var` `properties = channel.CreateBasicProperties();` `properties.DeliveryMode = 1;` `string` `message = ``"I am Kiba518"``; ``//传递的消息内容` `channel.BasicPublish(``""``, ``"kibaQueue"``, properties, Encoding.UTF8.GetBytes(message)); ``//生产消息` `Console.WriteLine($``"Send:"``);` `Thread.Sleep(3000);` `}`效果图如下: 可以看到,发送消息和接收消息,几乎是同步的,效果非常理想。服务器端应用在上文,我们的RabbitMQ服务是安装在我的本机上的;现在我们把服务移植到服务器上,然后再来测试一下。在服务器端安装RabbitMQ和在本机安装的步骤是一样的,但是安装完成后,我们需要设置下防火墙的入站规则和出站规则,将5672的UDP端口开放一下。为什么要开放端口是5672?因为RabbitMQ的默认的消息接收和发送端口就是5672,我们可以使用断点查看一下。如上图,可以看到,在我们没有设置端口的时候,Endpoint的端口的默认值是5672。配置完端口后,我们修改代码中的HostName为我们的服务器地址,如下。factory.HostName = `"1.1.1.1"`;重新运行代码,会发现在运行到factory.CreateConnection()的时候,系统提示一个异常【RabbitMQ.Client.Exceptions.BrokerUnreachableException:“None of the specified endpoints were reachable”】,如下图:这是因为我们使用的账号是guest,guest账号默认是不支持远程连接的。解决办法很简单,新建一个账户即可。创建用户在服务器端打开浏览器,输入http://127.0.0.1:15672/,进入管理页面。点击菜单栏的Admin选项,进入用户管理界面创建用户kiba,密码123456,如下图:创建完用户后,得到如下界面。如上图所示,刚刚创建的用户还没有任何访问权限。现在我们点击用户名,进入权限管理页面设置权限。如上图所示,页面默认为我们设置了一个可读,可写,可管理配置的权限;所以,我们只要点击Set premission就可以了。设置完权限,我们回到用户管理页面。 如上图所示,权限设置成功。现在我们回到代码,修改用户名密码如下。`factory.HostName = ``"1.1.1.1"``;` `factory.UserName = ``"kiba"``;` `factory.Password = ``"123456"``;`运行代码,不再抛异常,接受发送消息正常。 设置用户权限也可以通过命令的方式设置,如下: rabbitmqctl set_permissions -p "/" kiba "." "." ".*"
2021年03月10日
108 阅读
0 评论
0 点赞
2021-03-10
Rabbmq(什么是RabbmitMQ,RabbmitMQ的六种工作模式)
RabbitMQ 使用场景什么是RabbmitMQRabbitMQ是支持持久化消息队列的消息中间件。应用在上下游的层次级业务逻辑中,上级业务逻辑相当于生产者发布消息,下级业务逻辑相当于消费者接受到消息并且消费消息。RabbitMQ的使用场景服务解耦流量削峰异步调用rabbitmq 基本概念RabbitMQ是一种消息中间件,用于处理来自客户端的异步消息。服务端将要发送的消息放入到队列池中。接收端可以根据RabbitMQ配置的转发机制接收服务端发来的消息。RabbitMQ依据指定的转发规则进行消息的转发、缓冲和持久化操作,主要用在多服务器间或单服务器的子系统间进行通信,是分布式系统标准的配置。Exchange接受生产者发送的消息,并根据Binding规则将消息路由给服务器中的队列。ExchangeType决定了Exchange路由消息的行为。在RabbitMQ中,ExchangeType常用的有direct、Fanout和Topic三种。Message Queue消息队列。我们发送给RabbitMQ的消息最后都会到达各种queue,并且存储在其中(如果路由找不到相应的queue则数据会丢失),等待消费者来取。Binding Key它表示的是Exchange与Message Queue是通过binding key进行联系的,这个关系是固定。Routing Key生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则。这个routing key需要与Exchange Type及binding key联合使用才能生,我们的生产者只需要通过指定routing key来决定消息流向哪里。rabbitmq六种工作模式简单模式发送消息的程序是生产者队列就代表一个邮箱。虽然消息会流经RbbitMQ和你的应用程序,但消息只能被存储在队列里。队列存储空间只受服务器内存和磁盘限制,它本质上是一个大的消息缓冲区。多个生产者可以向同一个队列发送消息,多个消费者也可以从同一个队列接收消息.消费者等待从队列接收消息工作模式工作队列(即任务队列)背后的主要思想是避免立即执行资源密集型任务,并且必须等待它完成。相反,我们将任务安排在稍后完成。 我们将任务封装为消息并将其发送到队列。后台运行的工作进程将获取任务并最终执行任务。当运行多个消费者时,任务将在它们之间分发。发布订阅模式RabbitMQ消息传递模型中的核心思想是生产者从不将任何消息直接发送到队列。实际上,生产者经常甚至根本不知道是否将消息传递到任何队列。相反,生产者只能将消息发送到交换机。交流是一件非常简单的事情。一方面,它接收来自生产者的消息,另一方面,将它们推入队列。交易所必须确切知道如何处理收到的消息。是否应将其附加到特定队列?是否应该将其附加到许多队列中?还是应该丢弃它。规则由交换类型定义 。 路由模式使用的是扇出交换,它并没有给我们太大的灵活性-它只能进行无意识的广播。我们将使用直接交换。直接交换背后的路由算法很简单-一条消息进入其绑定密钥与该消息的路由密钥完全匹配的队列 。为了说明这一点,请考虑以下设置: 在此设置中,我们可以看到绑定了两个队列的直接交换X。第一个队列由绑定键orange绑定,第二个队列有两个绑定,一个绑定键为black,另一个绑定为green。在这样的设置中,使用路由键橙色发布到交换机的消息 将被路由到队列Q1。路由键为黑色 或绿色的消息将转到Q2。所有其他消息将被丢弃。主题模式发送到主题交换的消息不能具有任意的 routing_key-它必须是单词列表,以点分隔。这些词可以是任何东西,但通常它们指定与消息相关的某些功能。一些有效的路由关键示例:“ stock.usd.nyse ”,“ nyse.vmw ”,“ quick.orange.rabbit ”。路由密钥中可以包含任意多个单词,最多255个字节。绑定密钥还必须采用相同的形式。主题交换背后的逻辑类似于直接交换的逻辑 -使用特定路由密钥发送的消息将传递到所有使用匹配绑定密钥绑定的队列。但是,绑定键有两个重要的特殊情况:*(星号)可以代替一个单词。 #(哈希)可以替代零个或多个单词。RPC模式我们的RPC将像这样工作:客户端启动时,它将创建一个匿名排他回调队列。对于RPC请求,客户端发送一条消息,该消息具有两个属性: reply\_to(设置为回调队列)和correlation\_id(设置为每个请求的唯一值)。 该请求被发送到rpc_queue队列。RPC工作程序(又名:服务器)正在等待该队列上的请求。出现请求时,它将使用reply_to字段中的队列来完成工作,并将消息和结果发送回客户端。客户端等待回调队列上的数据。出现消息时,它将检查correlation_id属性。如果它与请求中的值匹配,则将响应返回给应用程序。
2021年03月10日
156 阅读
0 评论
0 点赞
2021-03-09
C#—RabbitMQ指南之发布/订阅模式(Publish/Subscribe)
先决条件\本教程假定 RabbitMQ 已经安装,并运行在localhost标准端口(5672)。如果你使用不同的主机、端口或证书,则需要调整连接设置。发布/订阅我们创建了一个工作队列,假设在工作队列中的每一个任务都只被分发给一个 Worker。那么在这一章节,我们要做与之完全不同的事,那就是我们将要把一条消息分发给多个消费者。这种模式被称为"发布/订阅"。为了说明、体现这种模式,我们将会建一个简单的日志系统。它将会包含两个程序 - 第一个用来发送日志消息,第二个用来接收并打印它们。在我们建立的日志系统中,每个接收程序的运行副本都会收到消息。这样我们就可以运行一个接收程序接收消息并将日志写入磁盘;同时运行另外一个接收程序接收消息并将日志打印到屏幕上。实质上,发布的日志消息将会被广播给所有的接收者。交换器在教程的前几部分,我们是发送消息到队列并从队列中接收消息。现在是时候介绍 Rabbit 中完整的消息传递模型了。让我们快速回顾一下前面教程中的内容:生产者是发送消息的用户应用程序。队列是存储消息的缓冲区。消费者是接收消息的用户应用程序。在 RabbitMQ 中,消息传递模型的核心理念是生产者从来不会把任何消息直接发送到队列,其实,通常生产者甚至不知道消息是否会被分发到任何队列中。然而,生产者只能把消息发送给交换器。交换器非常简单,一方面它接收来自生产者的消息,另一方面又会把接收的消息推送到队列中。交换器必须明确知道该如何处理收到的消息,应该追加到一个特定队列中?还是应该追加到多个队列中?或者应该把它丢弃?这些规则都被定义在交换器类型中。目前交换器类型有这几种:direct,topic,headers和fanout。我们先重点关注最后一个fanout,我们创建一个这种类型的交换器,将其命名为logs:channel.ExchangeDeclare("logs", "fanout"); fanout类型交换器非常简单,正如您可能从名字中猜出的那样,它会把收到的所有消息广播到它已知的所有队列中。这恰巧是我们的日志系统目前所需要的。列举交换器 要列举出服务器上的交换器,您可以使用非常有用的rabbitmqctl命令行工具:sudo rabbitmqctl list_exchanges 执行上述命令后,出现的列表中将会有一些amq.*交换器和默认(未命名)交换器。这些是默认创建的,不过目前您可能用不到它们。默认交换器 在教程的前些部分,我们对交换器这一概念还一无所知,但仍然可以把消息发送到队列。之所以这样,是因为我们使用了一个用空字符串("")标识的默认交换器。回顾一下我们之前如何发布消息:var message = GetMessage(args); var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: null, body: body); 第一个参数就是交换器的名称,空字符串表示默认或匿名交换器:将消息路由到routingKey指定的队列(如果存在)中。现在,我们可以把消息发布到我们指定的交换器:var message = GetMessage(args); var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "logs", routingKey: "", basicProperties: null, body: body); 临时队列您是否还记得之前我们使用过的队列,它们都有一个特定的名称(记得应该是hello和task_queue吧)。给队列命名对我们来说是至关重要的 -- 因为我们可能需要多个 Worker 指向同一个队列;当您想要在生产者和消费者之间共享队列时,给队列一个名称也是非常重要的。但是,我们创建的日志系统并不希望如此。我们希望监听所有的日志消息,而不仅仅是其中一部分。我们也只对目前流动的消息感兴趣,而不是旧消息。为解决这个问题,我们需要做好两件事。首先,我们无论何时连接 Rabbit,都需要一个新的、空的队列。要做到这一点,我们可以使用随机名称来创建队列,或许,甚至更好的方案是让服务器为我们选择一个随机队列名称。其次,一旦我们与消费者断开连接,与之相关的队列应该被自动删除。在 .NET 客户端中,如果不向QueueDeclare()方法提供任何参数,实际上就是创建了一个非持久化、独占、且自动删除的随机命名队列:var queueName = channel.QueueDeclare().QueueName; 您可以在 队列指南 中了解更多关于exclusive参数和其他队列属性的信息。此时,queueName包含一个随机队列名称。例如,它看起来可能像amq.gen-JzTY20BRgKO-HjmUJj0wLg。绑定我们已经创建好了一个fanout交换器和一个队列。现在我们需要告诉交换器把消息发送到我们的队列。而交换器和队列之间的关系就称之为绑定。// 把一个队列绑定到指定交换器。 channel.QueueBind(queue: queueName, exchange: "logs", routingKey: ""); 从现在起,logs交换器会把消息追加到我们的队列中。列举绑定\您可以使用(您或许已经猜到了),列举出现有的绑定。sudo rabbitmqctl list_bindings 组合在一起生产者程序负责分发消息,这与之前的教程看起来没有太大区别。最重要的变化是我们现在想把消息发布到我们的logs交换器,而不是匿名交换器。在发送时我们需要提供一个路由键routingKey,但是对于fanout交换器,它的值可以被忽略。这里是EmitLog.cs文件的代码:using System; using RabbitMQ.Client; using System.Text; class EmitLog { public static void Main(string[] args) { var factory = new ConnectionFactory() ; using(var connection = factory.CreateConnection()) using(var channel = connection.CreateModel()) { channel.ExchangeDeclare(exchange: "logs", type: "fanout"); var message = GetMessage(args); var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "logs", routingKey: "", basicProperties: null, body: body); Console.WriteLine(" [x] Sent ", message); } Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); } private static string GetMessage(string[] args) { return ((args.Length > 0) ? string.Join(" ", args) : "info: Hello World!"); } } (EmitLog.cs 源码)如你所见,在建立连接后,我们声明了交换器。这一步非常有必要,因为发布消息到一个不存在的交换器,这种情况是被禁止的。如果没有队列绑定到交换器上,消息将会丢失,但这对我们来说并没有什么没问题;如果没有消费者正在监听,我们是可以放心地把消息丢弃的。ReceiveLogs.cs的代码:using System; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System.Text; class ReceiveLogs { public static void Main() { var factory = new ConnectionFactory() ; using(var connection = factory.CreateConnection()) using(var channel = connection.CreateModel()) { channel.ExchangeDeclare(exchange: "logs", type: "fanout"); var queueName = channel.QueueDeclare().QueueName; channel.QueueBind(queue: queueName, exchange: "logs", routingKey: ""); Console.WriteLine(" [*] Waiting for logs."); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); Console.WriteLine(" [x] ", message); }; channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); } } } (ReceiveLogs.cs 源码)按照 [教程[1]](https://www.cnblogs.com/esofar/p/rabbitmq-hello-world.html)中的设置说明生成EmitLogs和ReceiveLogs 项目。如果您想把日志保存到文件中,只需打开一个控制台并输入:cd ReceiveLogs dotnet run > logs_from_rabbit.log 如果你想在屏幕上看到日志,我可以新开一个终端并运行:cd ReceiveLogs dotnet run 当然,分发日志需要输入:cd EmitLog dotnet run 使用rabbitmqctl list_bindings命令,您可以验证代码是否真正创建了我们想要的绑定和队列。当有两个ReceiveLogs.cs程序运行时,您应该看到如下所示的内容:sudo rabbitmqctl list_bindings # => Listing bindings ... # => logs exchange amq.gen-JzTY20BRgKO-HjmUJj0wLg queue [] # => logs exchange amq.gen-vso0PVvyiRIL2WoV3i48Yg queue [] # => ...done. 对执行结果的解释简洁明了:来自logs交换器的数据转发到了两个由服务器随机分配名称的队列。这正是我们期待的结果。写在最后本文翻译自 RabbitMQ 官方教程 C# 版本。如本文介绍内容与官方有所出入,请以官方最新内容为准。水平有限,翻译的不好请见谅,如有翻译错误还请指正。原文链接:RabbitMQ tutorial - Publish/Subscribe实验环境:RabbitMQ 3.7.4 、.NET Core 2.1.3、Visual Studio Code最后更新:2018-06-11
2021年03月09日
105 阅读
0 评论
1 点赞
1
...
4
5