RabbitMQ连接池、生产者、消费者实例
1、本文分享RabbitMQ的工具类,经过实际项目长期测试,在此分享给发家,各位大神有什么建议请指正 !!!
2、下面是链接池主要代码:
import java.util.HashMap;
import java.util.Map; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; /**
* 获取RabbitMq连接
* @author skyfeng
*/
public class RabbitMqConnectFactory {
static Logger log = LoggerFactory.getLogger(RabbitMqConnectFactory.class);
/**
* 缓存连接工厂,将建立的链接放入map缓存
*/
private static Map<String, ConnectionFactory> connectionFactoryMap = new HashMap<String, ConnectionFactory>();
/**
* 根据rabbitMqName获取一个连接,使用完记得要自己关闭连接 conn.close()
*/
public static Connection getConnection(String rabbitMqName) {
if(StringUtils.isEmpty(rabbitMqName)){
log.error("rabbitMqName不能为空!");
throw new java.lang.NullPointerException("rabbitMqName为空");
}
if(connectionFactoryMap.get(rabbitMqName)==null){
initConnectionFactory(rabbitMqName);
}
ConnectionFactory connectionFactory = connectionFactoryMap.get(rabbitMqName);
if(connectionFactory==null){
log.info("没有找到对应的rabbitmq,name={}",rabbitMqName);
}
try {
return connectionFactory.newConnection();
}catch (Exception e) {
log.error("创建rabbitmq连接异常!",e);
return null;
}
}
/**
* 初始化一个连接工厂
* @param rabbitMqName
*/
private static void initConnectionFactory(String rabbitMqName){ try {
ConnectionFactory factory = new ConnectionFactory();
//新增代码,如果连接断开会自动重连
//factory.setAutomaticRecoveryEnabled(true);
factory.setHost("127.0.0.1");
factory.setPort(5672);
//factory.setVirtualHost(vhost);
factory.setUsername("test");
factory.setPassword("test");
connectionFactoryMap.put(rabbitMqName, factory);
} catch (Exception e) {
e.printStackTrace();
}finally{
}
} }
3、消费端的代码:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer; /**
* RabbitMQq客户端代码
* @author skyfeng
*
*/
public class CustomerMqClient { final static Logger log = LoggerFactory.getLogger(CustomerMqClient.class);
private final static String RABBITMQ_NAME = "mq_name";
private final static String EXCHANGE_NAME = "Exchange_name";
private final static String QUEUE_NAME = "queue_name";
private static Channel channel = null;
private static Connection connection = null; /**
* 初始化客户端代码
*/
public static void initClient() {
//重新链接时判断之前的channel是否关闭,没有关闭先关闭
if(null != channel && channel.isOpen()){
try {
channel.close();
} catch (Exception e) {
log.error("mq name =[" +RABBITMQ_NAME+"] close old channel exception.e={}",e);
}finally {
channel = null;
}
}
//重新链接时判断之前的connection是否关闭,没有关闭先关闭
if (null != connection && connection.isOpen()) {
try {
connection.close();
} catch (Exception e) {
log.error("mq name =[" +RABBITMQ_NAME+"] close old connection exception.e={}",e);
}finally{
connection = null;
}
}
//从链接池中获取链接
connection = RabbitMqConnectFactory.getConnection(RABBITMQ_NAME);
try {
channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "#");//#号接收所有的数据
Consumer consumer = new CustomerMqConsumer(channel);//具体的业务逻辑在CustomerMqConsumer中
channel.basicConsume(QUEUE_NAME, false, consumer);
} catch (Exception e) {
log.error("CustomerMqClient mq client connection fail .....{}", e);
//发生异常时,重连
reConnect();
}
} // 异常时,重连的方法
public static void reConnect() {
log.error("等待5s后重连");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
initClient();
} }
4、生产端代码:
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.rabbitmq.client.AlreadyClosedException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; /**
* 把数据发送到rabbitmq的exchange,
*/
public class SendToExchange {
static Logger log = LoggerFactory.getLogger(SendToExchange.class); final static String TYPE = "topic";
final static String CHARSET_UTF8 = "UTF-8";
//MQ生产者exchange,把数据发给这个exchange
final static String rabbitExchangeName = "ExchangeName";
static boolean mqConnected = false;//mq当前处于连接状态 static Channel channel=null;
static{
init();
}
public static void init(){
log.info(" rabbit mq init begin...");
try {
//在mq连接中断后,发送程序判断已经断开,启动重连的时候会执行
if(channel!=null){
try {
channel.close();
} catch (Exception e) {
log.error("关闭老channel 异常",e);
}finally{
channel = null;
}
}
Connection connection = RabbitMqConnectFactory.getConnection("connection");
channel = connection.createChannel();
/*
*这里只定义exchange,因为每个业务模块都会从这里接入数据,所以不在这里定义队列
*队列的定义在各个业务模块自己的消费端定义
*/
channel.exchangeDeclare(rabbitExchangeName, TYPE, true, false, null);
log.info(" rabbit mq init OK");
mqConnected = true;
} catch (Exception e) {
log.error("rabbitmq初始化错误",e);
mqConnected = false;
}
}
/**
* 往rabbitmq发数据
* @param message
*/
public static void sendToRabbitMq(String message,String routingKey){
try {
if(StringUtils.isEmpty(message)){
log.debug("message is empty");
return;
}
channel.basicPublish(rabbitExchangeName, routingKey, null, message.getBytes(CHARSET_UTF8));
}catch(AlreadyClosedException ex){
log.error("往rabbitmq发数据报错,可能连接已关闭,尝试重连,data:",message,ex);
init();
}catch (Exception e) {
log.error("往rabbitmq发数据报错,data:",message,e);
}
}
}
RabbitMQ连接池、生产者、消费者实例的更多相关文章
- Linux 进程间通信(包含一个经典的生产者消费者实例代码)
前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...
- 线程锁,threadinglocal,线程池,生产者消费者模型
1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...
- Java 线程池 +生产者消费者+MySQL读取300 万条数据
1.1需求 数据库300 万条用户数据 ,遍历获取所有用户, 各种组合关联, 获取到一个新的json ,存到redis 上. 1.2 难点 数据库比较多, 不可能单线程查询所有的数据到内存. 1.3解 ...
- Go语言协程并发---生产者消费者实例
package main import ( "fmt" "strconv" "time" ) /* 改进生产者消费者模型 ·生产者每秒生产一 ...
- Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...
- JDBC连接池。。。转载
1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架 ...
- 用连接池提高Servlet访问数据库的效率
Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本.Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据.本文介绍 ...
- (转)websphere线程池 连接池设置
原文:http://www.talkwithtrend.com/Article/207511 池(Pool)是WebSphere中最常涉及的概念之一.从网络.Web 服务器.Web 容器.EJB 容器 ...
- 为什么要用Jedis连接池+浅谈jedis连接池使用
为什么要使用Jedis连接池 Redis作为缓存数据库理论上和MySQL一样需要客户端和服务端建立起来连接进行相关操作,使用MySQL的时候相信大家都会使用一款开源的连接池,例如C3P0.因为直连会消 ...
随机推荐
- Codeforces Round #570 (Div. 3) B. Equalize Prices
原文链接https://codeforces.com/contest/1183/problem/B 题意:进行Q组测试,在每组中有长度为n的数组a[i],然后现在给你一个K,问你找到一个bi使得|ai ...
- leetcode 869. Reordered Power of 2
function reorderedPowerOf2(N) { var a1 = N.toString().split('') a1.sort((a, b) => a.localeCompare ...
- Django - installing mysqlclient error: mysqlclient 1.3.13 or newer is required; you have 0.9.3
环境 Deepin Linux 15.11 Django 2.2 pymysql0.9.3 原因 因为用pymysql替换了默认的mysqlclient,Django官方推荐的数据库API drive ...
- python面试的100题(10)
18.反转一个整数,例如-123 --> -321 class Solution(object): def reverse(self,x): if -10<x<10: return ...
- DE1-LINUX运行
在官网下载.img文件:网址:http://download.terasic.com/downloads/cd-rom/de1-soc/linux_BSP/ 写入DE1_SOC_SD.img文件: 打 ...
- FastDFS :java.lang.Exception: getStoreStorage fail, errno code: 28
FastDFS 服务正常,突然报错:java.lang.Exception: getStoreStorage fail, errno code: 28 答:错误代码28表示 No space left ...
- Stream中的map
#map可以让一个对象A的流转换为宁外一种对象B的流(其实也是A对象元素组成的流) 1.对象转换为List集合 //若Eticket是一个对象,其中orderId是String类型 //eticket ...
- Dreamoon and WiFi
Dreamoon is standing at the position 0 on a number line. Drazil is sending a list of commands throug ...
- HTML学习(7)格式化标签
对文本格式进行编辑的标签.常用: <b>加粗文本</b> <strong>加重语气</strong> 与<b>效果一样,<stro ...
- python+selenium:浏览器webdriver操作(1)--基本对象定位
1.简单对象的定位-----自动化测试的核心 对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象.一个对象就是一个人一样,他会有各种的特征(属性),如比我们可以通过一个人的身份证 ...