RabbitMQ笔记

1、项目中使用的Direct方式,云端和子系统均有自己的ID,使用ID在MQ上注册队列,云端管理子系统端的关系,每个子系统同步与自己相关的其他系统的ID到本地,同步完成后,在MQ上绑定对应的Key,这样,当子系统发送消息的routekey为自己的ID时,所有与其相关的子系统均会收到该条消息,间接的实现了群发。每个子系统同时绑定ID+"_recv”到队列的Exchange上,这样当其他系统发送消息到该系统时,可以直接使用该routekey。

2、使用AMQP方式操作rabbitMQ,使用Spring对AMQP的xml配置发现太不灵活,在项目中自己声明队列,绑定EXchange,使用的是单例。

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;

public class AmqpFactory {
	
	private static AmqpFactory amqpFactory = new AmqpFactory();
	
	private boolean started = false;
	
	private static String MQUSERNAME;
	private static String MQPASSWORD ;
	private static String MQHOST;
	private static String MQDIRECTEXCHANGENAME;
	
	private List<String> routeKeyList = new ArrayList<String>();
	private List<String> oldRoutingkeyList = null;
	
	private RabbitTemplate rabbitTemplate = null;
	
	private String mqQueueName;
	
	private CachingConnectionFactory cf = null;
	
	private  SimpleMessageListenerContainer container = null;
	
	public static AmqpFactory getInstance(){
		return amqpFactory;
	}
	
	public void setMQQueueName(String mQQueueName) {
		mqQueueName = mQQueueName;
	}
	
	public void setRouteKeyList(List<String> routeKeyList) {
		this.routeKeyList = routeKeyList;
	}
	
	public void setOldRoutingkeyList(List<String> oldRoutingkeyList) {
		this.oldRoutingkeyList = oldRoutingkeyList;
	}

	public String getMQHOST() {
		return MQHOST;
	}

	public String getExchange(){
		return MQDIRECTEXCHANGENAME;
	}

	public synchronized void initCofig(){
		if (Strings.isBlank(CommonConfig.LOCAL_HOSPOTAL_ID)){
			return ;
		}
		mqQueueName = CommonConfig.LOCAL_HOSPOTAL_ID;
		if (started == false){
			List<String> routekeyList = refreshHospitalIdAndRouteKeyList();
			if(routekeyList == null || routekeyList.size() == 0){
				return ;
			}
			this.setRouteKeyList(routekeyList);
			refreshRabbitConfig();
		}
		started = true;
	}
	
	public synchronized void reladCofig(){
		if (started == true){
			List<String> routekeyList = refreshHospitalIdAndRouteKeyList();
			if(routekeyList == null || routekeyList.size() == 0){
				return ;
			}
			this.setRouteKeyList(routekeyList);
			refreshRabbitConfig();
		}
	}
	
	
	/**
	 * 加载mq的配置文件
	 */
	public static void loadProperties(){
		Properties p = CommonConfig.loadProperties("mq.properties");
		
		MQUSERNAME = p.getProperty("MQUSERNAME");
		MQPASSWORD = p.getProperty("MQPASSWORD");
		MQHOST = p.getProperty("MQHOST");
		MQDIRECTEXCHANGENAME = p.getProperty("MQDIRECTEXCHANGENAME");
	}
	
	/**
	 * 注册到MQ服务器
	 */
	private void refreshRabbitConfig(){
		if (container != null){
			container.stop();
		}
		
		cf = new CachingConnectionFactory(MQHOST);
		cf.setUsername(MQUSERNAME);
		cf.setPassword(MQPASSWORD);
		cf.setRequestedHeartBeat(20);
		cf.setChannelCacheSize(2);
		cf.setChannelCheckoutTimeout(20000);
		
	    // set up the queue, exchange, binding on the broker
	    RabbitAdmin admin = new RabbitAdmin(cf);
	    //设置队列持久化和不自动删除
	    Queue queue = new Queue(mqQueueName, true, false, false);
	    log.info("queue name : "+mqQueueName);
	    admin.declareQueue(queue);
	    DirectExchange exchange = new DirectExchange(MQDIRECTEXCHANGENAME,true,false);
	    admin.declareExchange(exchange);
	    
	    if (routeKeyList == null || routeKeyList.size() == 0) return;
	    
	    //删除绑定路由
	    if (oldRoutingkeyList != null){
	    	this.deleteAllBinding(admin, oldRoutingkeyList,queue,exchange);
	    }
	    //重新绑定
	    for (String routekey : routeKeyList){
	    	admin.declareBinding(
	    	        BindingBuilder.bind(queue).to(exchange).with(routekey));
	    }
	    
	    // set up the listener and container
	    container = new SimpleMessageListenerContainer(cf);
	    MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageHandler());
	    container.setMessageListener(adapter);
	    container.setQueueNames(mqQueueName);
	    container.start();
	    
	    // send template
	    rabbitTemplate = new RabbitTemplate(cf);
	}
	
	//获取到发送模板
	public RabbitTemplate getTemplate(){
		return rabbitTemplate;
	}
	
	public List<String> refreshClientIdAndRouteKeyList(){
		List<String> clientIdList = getAllClientId();
		
		if( clientIdList == null || clientIdList.size() == 0){
                }
		List<String> routeKeyList = new ArrayList<String>();
		if (routeKeyList != null){
			for (String clientId : clientIdList ){
				routeKeyList.add(clientId);
			}
		}
		//云端的广播key
		routeKeyList.add(CommonConfig.CLOUD_SENT_KEY);
		
		//自己队列的接收key
		routeKeyList.add(CommonConfig.ID + "_recv");
		return routeKeyList;
	}
	
	public void deleteAllBinding(RabbitAdmin admin,List<String> routingkeyList, Queue queue, DirectExchange exchange){
	    for (String routekey : routingkeyList){
	    	admin.removeBinding(BindingBuilder.bind(queue).to(exchange).with(routekey));
	    }
	}
}


3、项目中的消息内容均是json串,结构为{type:"com.zz.AAMessage",data:""},type为class类名,data为class的内容,当收到消息后,使用反射获取到类,根据类的类型进处理。再加新的消息类型的时候,只需要继承父类,实现处理方法,然后注册到解析类中。


4、子系统中,由于可能会断网,所以增加了一个消息表,发送消息和接收消息都经过一次中转,有定时器定时处理消息表。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值