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.因为直连会消 ...
随机推荐
- Python 入门【一】Python 初识及学习资料
Python 初识及学习路线: CodeCademy Python 在线教学: 廖雪峰 Python 2.7 教程: 廖雪峰 Python 3.0 教程: Python 官方文档(2.7~3.7:英文 ...
- 创建本地yum源仓库
更新本地yum源 yum仓库服务端配置如下 : 1. 创建yum仓库目录 mkdir -p /data/yum_data/ cd /data/yum_data/ #可以上传rpm包到此目录,此目录下面 ...
- vue组件引入
/src/route/index.js import Demo2 from '@/pages/demo2/index.vue' { path : '/demo2', name : 'demo2', c ...
- 第三十篇 玩转数据结构——字典树(Trie)
1.. Trie通常被称为"字典树"或"前缀树" Trie的形象化描述如下图: Trie的优势和适用场景 2.. 实现Trie 实现Trie的业务无 ...
- Git 从远端指定分支克隆代码到本地
不指定分支默认是master git clone + clone 地址 # 例如 git clone https://amc-msra.visualstudio.com/xxx/_xx/xxxxxx ...
- MySQL学习(五)事务隔离
文章部分图片和总结来自参考资料,侵删 概述 MySQL的可重复读隔离级别,事务T启动的时候会创建一个视图read-view,之后事务T执行期间,即使有其他事务修改了数据,事务T看到的仍然跟在启动时看到 ...
- Linux - Shell - find - 进阶: 时间与大小
概述 继续 find 这次的内容, 参数稍微要 复杂那么一丢丢 背景 刚学会了 基础 的参数 现在来了解一些 时间 和 空间 的参数 一说到操控时间空间, 感觉立马起来了... 准备 OS cento ...
- Books Exchange (hard version)
The only difference between easy and hard versions is constraints. There are nn kids, each of them i ...
- Linux服务器时间设置及同步
闲余:夏日将到,园区计划五一期间进行大面积的电网停电检修,运维同学因此将公司测试服务器提前关闭了.收假后,测试告诉我,他发现一个bug--一段定时任务程序未执行,我的第一反应就是--会不会是假期测试服 ...
- IntelliJ IDEA 2017.3尚硅谷-----如何创建模块