RabbitMq 发布订阅 Publish/Subscribe fanout/direct

目录

 

概述

交换机

临时队列

代码


概述

在上篇中了解到rabbitmq 生产者生产消息到队列,多个消费者可以接受。这篇文章主要记录广播类型为fanout。生产者不在将产生的消息发送到队列,而是将消息发送到交换机exchange,交换机会根据不同的交换规则,将消息发送到不同的队列。交换器必须知道她所接收的消息是什么?它应该将消息放到哪个队列中或者还是应该丢弃?这些规则都是按照交换机的规则来确定的。

           

交换机

Exchange(交换机):生产者会将消息发送到交换机,然后交换机通过路由策略(规则)将消息路由到匹配的队列中去

交换规则:

Fanout 不处理路由。需要简单的将队列绑定到交换机上。一个发送到该类型交换机的消息都会被广播到与该交换机绑定的所有队列上。(本篇文章)

direct:它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。

channel.basicPublish(“direct”, “warn”, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

我们定义direct交换机,绑定路由warn 这时候发送消息只能发送的绑定的队列中 如队列1 队列2 但是如果绑定路由为info 则只有队列2可以收到。

topic:direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似。

定义

//参数1 名称 参数2 类型
channel.exchangeDeclare("fanout", "fanout");

临时队列

在生产者和消费者之间创建一个新的队列,这时候又不想使用原来的队列,临时队列就是为这个场景而生的:

首先,每当我们连接到RabbitMQ,我们需要一个新的空队列,我们可以用一个随机名称来创建,或者说让服务器选择一个随机队列名称给我们,一旦我们断开消费者,队列应该立即被删除。

在Java客户端,提供queuedeclare()为我们创建一个非持久化、独立、自动删除的队列名称。

队列绑定

 BindOk com.rabbitmq.client.Channel.queueBind(String queue, String exchange, String routingKey) throws IOException


Bind a queue to an exchange, with no extra arguments.

Parameters:
      queue the name of the queue
      exchange the name of the exchange
      routingKey the routine key to use for the binding
Returns:
      a binding-confirm method if the binding was successfully created
Throws:
       java.io.IOException - if an error is encountered

代码

该代码为fanout模式

生产者

package com.ll.mq.hellomq.queue;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * 
 * @author ll 生产者
 *
 */
public class Producer {

	private static final String EXCHANGE_NAME = "fanoutStudy";

    public static void main(String[] argv) throws Exception {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
		factory.setPort(5672);
		factory.setUsername("kysc");
		factory.setPassword("123456");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");

//      分发消息
        for(int i = 0 ; i < 5; i++){
            String message = "Hello World! " + i;
             channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
             System.out.println(" send'" + message + "'");
        }
        channel.close();
        connection.close();
    }

}

消费者1

package com.ll.mq.hellomq.fanout;

import java.io.IOException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
/**
 * 
 * @author ll 消费者1
 *
 */
public class ConsumerOne {

	private static final String EXCHANGE_NAME = "fanoutStudy";

	public static void main(String[] argv) throws Exception {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("localhost");
		factory.setPort(5672);
		factory.setUsername("kysc");
		factory.setPassword("123456");
		Connection connection = factory.newConnection();
		Channel channel = connection.createChannel();
		// 声明交换机类型
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
		// 获取临时队列
		String queueName = channel.queueDeclare().getQueue();
		// 绑定
		channel.queueBind(queueName, EXCHANGE_NAME, "");

		System.out.println(" [*] Waiting for messages");

		Consumer consumer = new DefaultConsumer(channel) {
			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
					byte[] body) throws IOException {
				String message = new String(body, "UTF-8");
				System.out.println("  ConsumerOne '" + message + "'");
			}
		};
		channel.basicConsume(queueName, true, consumer);
	}
}

消费者2

package com.ll.mq.hellomq.fanout;

import java.io.IOException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class ConsumerTwo {

	
	 private static final String EXCHANGE_NAME = "fanoutStudy";

	    public static void main(String[] argv) throws Exception {
	        ConnectionFactory factory = new ConnectionFactory();
	        factory.setHost("127.0.0.1");
	    	factory.setPort(5672);
			factory.setUsername("kysc");
			factory.setPassword("123456");
	        Connection connection = factory.newConnection();
	        Channel channel = connection.createChannel();
	        //声明交换机类型
	        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
	        //获取临时队列
	        String queueName = channel.queueDeclare().getQueue();
	        //绑定
	        channel.queueBind(queueName, EXCHANGE_NAME, "");

	        System.out.println(" [*] Waiting for messages");

	        Consumer consumer = new DefaultConsumer(channel) {
	            @Override
	            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
	                String message = new String(body, "UTF-8");
	                System.out.println(" ConsumerTwo '" + message + "'");
	            }
	        };
	        channel.basicConsume(queueName, true, consumer);
	    }
}

结果:

生产者: send'Hello World! 0'
               send'Hello World! 1'
               send'Hello World! 2'
               send'Hello World! 3'
               send'Hello World! 4'

消费者1    ConsumerOne 'Hello World! 0'
               ConsumerOne 'Hello World! 1'
               ConsumerOne 'Hello World! 2'
              ConsumerOne 'Hello World! 3'
              ConsumerOne 'Hello World! 4'

消费者2   ConsumerTwo'Hello World! 0'
               ConsumerTwo'Hello World! 1'
               ConsumerTwo'Hello World! 2'
              ConsumerTwo'Hello World! 3'
              ConsumerTwo'Hello World! 4'

rabbitmq结果:

 

下一篇 https://blog.csdn.net/lilongwangyamin/article/details/105117288 rabbitmq topic

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <amqp.h> #include <amqp_tcp_socket.h> int main(int argc, char *argv[]) { char const *hostname; int port, status; char const *exchange; char const *bindingkey; amqp_socket_t *socket = NULL; amqp_connection_state_t conn; hostname = "localhost"; port = 5672; exchange = "amq.topic"; bindingkey = "hello"; conn = amqp_new_connection(); socket = amqp_tcp_socket_new(conn); if (!socket) { printf("Error creating TCP socket\n"); return -1; } status = amqp_socket_open(socket, hostname, port); if (status) { printf("Error opening TCP socket\n"); return -1; } amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest"); amqp_channel_open(conn, 1); amqp_get_rpc_reply(conn); amqp_exchange_declare(conn, 1, amqp_cstring_bytes(exchange), amqp_cstring_bytes("topic"), 0, 0, 0, 0, amqp_empty_table); amqp_get_rpc_reply(conn); amqp_basic_publish(conn, 1, amqp_cstring_bytes(exchange), amqp_cstring_bytes(bindingkey), 0, 0, NULL, "Hello World!"); amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); amqp_connection_close(conn, AMQP_REPLY_SUCCESS); amqp_destroy_connection(conn); return 0; }我已经写好了一段代码,可以实现 RabbitMQ 发布模式。它使用 C 语言编写,你可以根据自己的需求来改进它。 ### 回答2: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <rabbitmq-c/rabbitmq.h> #define QUEUE_NAME "my_queue" #define MESSAGE "Hello, RabbitMQ!" int main() { // 建立连接 amqp_connection_state_t conn; conn = amqp_new_connection(); // 打开通道 amqp_socket_t *socket = amqp_tcp_socket_new(conn); amqp_socket_open(socket, "localhost", 5672); // 登录认证 amqp_login(conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest"); amqp_channel_open(conn, 1); amqp_get_rpc_reply(conn); // 声明一个持久化的队列 amqp_queue_declare(conn, 1, amqp_cstring_bytes(QUEUE_NAME), 0, 1, 0, 0, amqp_empty_table); amqp_get_rpc_reply(conn); // 发布消息 amqp_basic_properties_t props; props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG; props.content_type = amqp_cstring_bytes("text/plain"); props.delivery_mode = 2; // 持久化消息 amqp_basic_publish(conn, 1, amqp_cstring_bytes(""), amqp_cstring_bytes(QUEUE_NAME), 0, 0, &props, amqp_cstring_bytes(MESSAGE)); amqp_get_rpc_reply(conn); // 关闭通道 amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); amqp_get_rpc_reply(conn); // 关闭连接 amqp_connection_close(conn, AMQP_REPLY_SUCCESS); amqp_destroy_connection(conn); return 0; } ### 回答3: RabbitMQ是一种广泛使用的消息队列中间件,它支持多种消息传输模式,包括发布/订阅(Publish/Subscribe)模式。在C语言中,我们可以使用RabbitMQ的C客户端库来编写一个发布模式的代码示例。 首先,我们需要安装RabbitMQ的C客户端库,并通过头文件引入相关函数和结构体。接下来,我们可以创建一个发布者(publisher)的代码,用于向RabbitMQ发送消息。 下面是一个简单的RabbitMQ发布模式的代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <amqp.h> int main() { // 连接到RabbitMQ服务器 amqp_connection_state_t conn = amqp_new_connection(); amqp_socket_t* socket = amqp_tcp_socket_new(conn); amqp_socket_open(socket, "localhost", 5672); // 创建一个通道 amqp_channel_open(conn, 1); amqp_get_rpc_reply(conn); // 创建一个交换机,用于消息发布 amqp_exchange_declare(conn, 1, amqp_cstring_bytes("my_exchange"), amqp_cstring_bytes("fanout"), false, true, false, false, amqp_empty_table); // 发布消息 const char* message = "Hello, RabbitMQ!"; amqp_basic_publish(conn, 1, amqp_cstring_bytes("my_exchange"), amqp_cstring_bytes(""), 0, 0, NULL, amqp_cstring_bytes(message)); // 关闭通道和连接 amqp_channel_close(conn, 1, AMQP_REPLY_SUCCESS); amqp_connection_close(conn, AMQP_REPLY_SUCCESS); amqp_destroy_connection(conn); return 0; } ``` 以上代码中,我们首先通过`amqp_connection_state_t`类型的`conn`变量创建RabbitMQ连接,并通过`amqp_tcp_socket_new`函数创建一个TCP socket与RabbitMQ服务器建立连接。接下来,我们通过`amqp_channel_open`函数创建一个通道,并使用`amqp_exchange_declare`函数声明一个名为`my_exchange`的交换机,用于消息的发布。然后,我们调用`amqp_basic_publish`函数发布一条消息到交换机。 最后,通过`amqp_channel_close`和`amqp_connection_close`函数关闭通道和连接,并通过`amqp_destroy_connection`函数释放连接资源。 这是一个基本的RabbitMQ发布模式的示例代码。根据实际需求,你可以进一步扩展代码,添加错误处理和异常情况的处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值