JAVA-RabbitMq的应用

发送端:
package cn.rabbitmq.project.started;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ConfirmType;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

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

public class Application {
	public static void main(String[] args) {
		String hostName = "home.cn";
		int port = 5672;
		String virtualHost = "host";
		String userName = "user";
		String password = "password";

		String exchange = "ex.sit";
		String routingKey = "k.sit";
		String queueName = "q.sit";
        String msg = "{\"id\":193375,\"authorization\":\"test_123\",\"accountNo\":\"62270088\",\"code\":\"bf\"}";

		CachingConnectionFactory connectionFactory = new CachingConnectionFactory(hostName, port);
		connectionFactory.setUsername(userName);
		connectionFactory.setPassword(password);
		connectionFactory.setVirtualHost(virtualHost);
		// 消息的确认机制(confirm);
		connectionFactory.setPublisherConfirmType(ConfirmType.CORRELATED);
		connectionFactory.setPublisherReturns(true);
		// setCacheMode:设置缓存模式,共有两种,CHANNEL和CONNECTION模式。
		// 1、CONNECTION模式,这个模式下允许创建多个Connection,会缓存一定数量的Connection,每个Connection中同样会缓存一些Channel,
		// 除了可以有多个Connection,其它都跟CHANNEL模式一样。
		// 2、CHANNEL模式,程序运行期间ConnectionFactory会维护着一个Connection,
		// 所有的操作都会使用这个Connection,但一个Connection中可以有多个Channel,
		// 操作rabbitmq之前都必须先获取到一个Channel,
		// 否则就会阻塞(可以通过setChannelCheckoutTimeout()设置等待时间),
		// 这些Channel会被缓存(缓存的数量可以通过setChannelCacheSize()设置);
		connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL); // 设置CONNECTION模式,可创建多个Connection连接
		// 设置每个Connection中缓存Channel的数量,不是最大的。操作rabbitmq之前(send/receive message等)
		// 要先获取到一个Channel.获取Channel时会先从缓存中找闲置的Channel,如果没有则创建新的Channel,
		// 当Channel数量大于缓存数量时,多出来没法放进缓存的会被关闭。
		connectionFactory.setChannelCacheSize(100);
		// 单位:毫秒;配合channelCacheSize不仅是缓存数量,而且是最大的数量。
		// 从缓存获取不到可用的Channel时,不会创建新的Channel,会等待这个值设置的毫秒数
		// 同时,在CONNECTION模式,这个值也会影响获取Connection的等待时间,
		// 超时获取不到Connection也会抛出AmqpTimeoutException异常。
		connectionFactory.setChannelCheckoutTimeout(600);
		// 仅在CONNECTION模式使用,设置Connection的缓存数量。
		connectionFactory.setConnectionCacheSize(3);
		// setConnectionLimit:仅在CONNECTION模式使用,设置Connection的数量上限。
		connectionFactory.setConnectionLimit(10);

		RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
		// 当mandatory 参数设为true 时,交换器无法根据自身的类型和路由键找到一个符合条件的队列,那么RabbitM Q 会调用Basic.Return
		// 命令将消息返回给生产者。
		// 当mandatory 参数设置为false 时,出现上述情形,则消息直接被丢弃。
		rabbitTemplate.setMandatory(true);
		rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
			@Override
			public void confirm(CorrelationData correlationData, boolean ack, String cause) {
				String id = correlationData != null ? correlationData.getId() : "";
				if (ack) {
					System.out.println("交换机已经收到消息 id:" + id);
				} else {
					System.out.println("交换机还未收到消息 id:" + id);
					System.out.println("原因:" + cause);
				}
			}
		});
		// 1。方式一发送
		// rabbitTemplate.convertAndSend(exchange, routingKey, "rabbitmq方式一",new
		// org.springframework.amqp.rabbit.connection.CorrelationData(UUID.randomUUID().toString()));

		// 2.方式二发送(延迟发送至死信队列,消费端去消费)
		//DLX ,全称为Dead-Letter-Exchange,可以称之为死信交换器,也有人称之为死信邮箱。当
		//消息在一个队列中变成死信( dead message )之后,它能被重新被发送到另一个交换器中,这个
		//交换器就是DLX ,绑定DLX 的队列就称之为死信队列。
		//消息变成死信一般是由于以下几种情况:
		//〈〉消息被拒绝( Basic.Reject/Basic.Nack ),井且设置requeue 参数为false;
		//〈〉消息过期;
		//令队列达到最大长度。
		//DLX 也是一个正常的交换器,和一般的交换器没有区别,它能在任何的队列上被指定,实
		//际上就是设置某个队列的属性。当这个队列中存在死信时, RabbitMQ 就会自动地将这个消息重
		//新发布到设置的DLX 上去,进而被路由到另一个队列,即死信队列。可以监听这个队列中的消
		//息、以进行相应的处理,这个特性与将消息的TTL 设置为0 配合使用可以弥补immediate 参数的功能。
		Message message = MessageBuilder.withBody(msg.getBytes()).setDeliveryMode(MessageDeliveryMode.PERSISTENT)
				.build();
        //message.getMessageProperties().setExpiration(String.valueOf(10 * 1000)); // 设置消息延迟时间:单位毫秒;如果没有再过期时间内消费的话,就会进入到死信队列进行消费
		message.getMessageProperties().setHeader("Message-Type", "account-auth");
		message.getMessageProperties().setHeader("Version", "1.0.0");
		message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_JSON);
		message.getMessageProperties().setCorrelationId(UUID.randomUUID().toString());
		rabbitTemplate.send(exchange, routingKey, message,
				new org.springframework.amqp.rabbit.connection.CorrelationData(UUID.randomUUID().toString()));
		System.out.println("sent msg: " + msg);

		// -------------------------------------------------------------------------------------------------------------------------------------------
		// 3.方式三发送
		/*
		 * ConnectionFactory factory = null; Connection connection = null; Channel
		 * channel = null; try { factory = new ConnectionFactory();
		 * factory.setUri("amqp://userName:password@ipAddress:portNumber/virtualHost");
		 * connection = factory.newConnection(); channel = connection.createChannel();
		 * channel.exchangeDeclare(exchange, "direct", true, false, null); //
		 * channel.exchangeBind(exchange, exchange, routingKey); //可以交换器绑定交换器
		 * channel.queueDeclare(queueName, true, false, false, null);
		 * channel.queueBind(queueName, exchange, routingKey);// 绑定交换器下面指定的队列 //
		 * 当mandatory 参数设为true 时,交换器无法根据自身的类型和路由键找到一个符合条件的队列,那么RabbitM Q 会调用Basic.Return
		 * // 命令将消息返回给生产者。 // 当mandatory 参数设置为false 时,出现上述情形,则消息直接被丢弃。 //
		 * 那么生产者如何获取到没有被正确路由到合适队列的消息呢?这时候可以通过调用channel.
		 * addReturnListener来添加ReturnListener监昕器实现。 channel.basicPublish(exchange,
		 * routingKey, true, null, "rabbitmq方式三".getBytes(Charset.forName("UTF-8"))); }
		 * catch (KeyManagementException e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); } catch (NoSuchAlgorithmException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } catch (URISyntaxException
		 * e) { // TODO Auto-generated catch block e.printStackTrace(); } catch
		 * (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
		 * finally { try { channel.close(); connection.close(); } catch (IOException |
		 * TimeoutException e) { // TODO Auto-generated catch block e.printStackTrace();
		 * } }
		 */
	}
}
消费端:
package cn.rabbitmq.project.consumer;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;

@Component
public class RabbitMqListener {

	/*
	 * @RabbitListener(bindings = @QueueBinding(value = @Queue(value =
	 * "${rabbit_mq_queue_name}", durable = "true"), exchange = @Exchange(value =
	 * "${rabbit_mq_exchange}", durable = "true"), key =
	 * "${rabbit_mq_routing_key}")) public void consumerMqMessage(String message) {
	 * System.out.println("消费rabbitmq:" + message); }
	 */
	
	@RabbitListener(queues = "${proxy.generating.queue.name}")
	public void consumer(Message message, Channel channel) throws IOException {
		String data = new String(message.getBody(), StandardCharsets.UTF_8);
		System.out.println(LocalDateTime.now()+"--消费rabbitmq被拒:" + data);
		channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);//basicNack拒绝响应,设置requeue 参数为false,不回到原队列
	}
	
    //监控死信队列消息
	@RabbitListener(queues = "${proxy.dl.generating.queue.name}")
	public void process(Message message, Channel channel) throws IOException {
		String data = new String(message.getBody(), StandardCharsets.UTF_8);
		System.out.println(LocalDateTime.now()+"--死信消费rabbitmq:" + data);
		channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);// manual确认消费然后删除,可以设置配置spring.rabbitmq.listener.simple.acknowledge-mode=manual  
	}
}
消费端启动应用的时候,会自动加载配置文件里面的MQ参数配置。

配置文件:
spring.rabbitmq.addresses=dd.cn:5672
spring.rabbitmq.host=dd
spring.rabbitmq.virtual-host=host
spring.rabbitmq.port=5672
spring.rabbitmq.username=sd
spring.rabbitmq.password=pd
# 60
spring.rabbitmq.requested-heartbeat=60
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
# 60
spring.rabbitmq.connection-timeout=300000

# cache
spring.rabbitmq.cache.channel.size=10
spring.rabbitmq.cache.channel.checkout-timeout=60

# customer's parameter 
proxy.generating.queue.name=q.sit
proxy.generating.exchange.name=ex.sit
proxy.generating.routerkey.name=k.sit

# DLX(Dead-Letter-Exchange)
proxy.dl.generating.queue.name=q.sit.dl
proxy.dl.generating.exchange.name=ex.sit
proxy.dl.generating.routerkey.name=k.sit.dl

# customer's parameter 延迟10s
proxy.generating.timeout.batch.small.tts=10000


# consumer 
# 100
spring.rabbitmq.listener.simple.prefetch=10
# 1
spring.rabbitmq.listener.simple.transaction-size=1
# 1
spring.rabbitmq.listener.simple.concurrency=1
# 3
spring.rabbitmq.listener.simple.max-concurrency=3
#manual ack mode 
spring.rabbitmq.listener.simple.acknowledge-mode=manual  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值