Rabbitmq 是对AMQP协议的一种实现。使用范围也比较广泛,主要用于消息异步通讯。

一,默认情况下Rabbitmq使用轮询(round-robin)方式转发消息。为了较好实现负载,可以在消息接收方指定,每次接收到一条,这样可以缓解单一服务器压力。

代码如下:

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.basicQos(1);//设置每次接收一条
为了保证消息不丢失,取消自动ACK,改为只有在完全处理消息后再ACK。
如:
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");
try {
Thread.sleep(10000);
}
catch(Exception ex)
{ }
System.out.println("received Message:" + message);
channel.basicAck(envelope.getDeliveryTag(), false);//处理完成后ACK
}
};
channel.basicConsume(QUEUE_NAME, false, consumer);//取消自动ACK
二,为了保证在Rabbitmq在宕机后,仍不丢失消息,需要将队列和发布的消息都声明为可持久化的。
如:
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, bytes);

三,Rabbitmq 的MessageModel(消息模型)
在Rabbitmq的消息模型中,我们决不应该将消息直接发送到queue.事实上,消息发送者并不关心消息是否被路由或被入队列或被接收并处理。
生产者应只与Exchange(交换器)打交道,
Exchange的作用:从生产者接受消息,向消费者发送消息。
The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.【所以交换器必须准确地知道怎样处理消息,是否应该加到一个指定的队列,还是发送到多个队列,还是应该抛弃该消息。】
指定Exchange的Rule,即以何种方式转发消息。
Rabbitmq共有四种:direct,topic ,headers和 fanout,NamelessExchange.
fanout,这种方式很简单,就是一个广播,把消息转给所有的订阅者;有几个订阅者,消息就会被复制几份。
NamelessExchange,无Exchange,消息以轮询(round-robin)方式,发送给消费者,通过routingKey识别对应的消费者。
【提示】:
rabbitmqctl list_exchanges ,用于查看当前Rabbitmq正在运行的交换器;rabbitmqctl list_bindings,查看当前绑定数
eg:
生产者只负责发送消息,而不关心这些消息是否被处理,也不关心消息是否被抛弃;消息由Exchange根据具体rule处理。
private static final String EXCHANGE_NAME = "logs";
private static final String EXCHANGE_TYPE="fanout"; public static void main(String[] argv)
throws java.io.IOException { ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME,EXCHANGE_TYPE); String message = getMessage(argv); channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'"); channel.close();
connection.close();
}
 如:以fanout方式处理消息:消息会发送给所有的订阅者,(与routingKey无关)
    private static final String exchangeName="logs";
private static final String exchangeType = "fanout";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
Connection connection = null;
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
connection = factory.newConnection();
final Channel channel = connection.createChannel();
int prefetchCount = 1;
channel.basicQos(prefetchCount);
channel.exchangeDeclare(exchangeName,exchangeType);
//创建一个队列,用于接收消息
String queueName= channel.queueDeclare().getQueue();
channel.queueBind(queueName,exchangeName,"");
System.out.println("Waiting for messages...,over it ,Press CTRL+C ");
Consumer consumer = new DefaultConsumer(channel) { public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println("received Message:" + message);
try {
doWork(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
channel.basicAck(envelope.getDeliveryTag(), false);
} }
};
channel.basicConsume(queueName, false, consumer); } finally { }
}
Bindings,将队列绑定到Exchange,说明可以从Exchange接收消息。【A binding is a relationship between an exchange and a queue. This can be simply read as: the queue is interested in messages from this exchange.】
channel.queueBind(queueName, EXCHANGE_NAME, "routingKey");

direct,只有当routingKey,与bindingKey相同Exchange才能会推送消息。
如:
生产者:
channel.basicPublish(exchangeName, "routingKey", MessageProperties.PERSISTENT_TEXT_PLAIN, bytes);//片断
生产者在发送消息时指定routingKey.

消费者:可以绑定多个Key,以接收来自多个routingKey的消息
for (String bindingKey : typeArr) {
channel.queueBind(queueName, exchangeName, bindingKey);
}
//接收者绑定Key. topic ,生产者在发送消息时,指定准确的routingKey(多个单词以.号分隔),当bindingKey模式匹配到routingKey时,则接收消息。
注意:routingKey和bindingKey的长度不能超过255.
*(star),只匹配一个单词。#(hash),能匹配0个或多个单词 三RPC
分布式远程调用。
 
 
												

Rabbitmq实现负载均衡与消息持久化的更多相关文章

  1. RabbitMq+Haproxy负载均衡

    HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性.负载均衡,以及基于TCP和HTTP的应用程序代理. HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保 ...

  2. RabbitMQ客户端负载均衡算法

    负载均衡(Load balance)是一种计算机网络技术,用于在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载,以达到最佳资源使用.最大化吞吐率.最小响应时间以及避免过载的 ...

  3. SAP Netweaver的负载均衡消息服务器 vs CloudFoundry的App Router

    Message server for ABAP Netweaver SAP传统应用经典的三层架构: 起到负载均衡的消息服务器(Message Server)在图中没有得到体现.然后,消息服务器在我们每 ...

  4. 动态负载均衡(Nginx+Consul+UpSync)环境搭建

    首先 安装好 Consul upsync 然后: 1.配置安装Nginx 需要做配置,包括分组之类的,创建目录,有些插件是需要存放在这些目录的 groupadd nginx useradd -g ng ...

  5. 深入剖析 RocketMQ 源码 - 负载均衡机制

    RocketMQ作为一款流行的消息中间件在各大互联网应用广泛,本文主要分析RocketMq在消息生产和消费过程中的负载均衡机制,并创新提出消费端负载均衡策略的改写以实现固定IP消费的可能.

  6. RabbitMQ (十五) 镜像集群 + HAProxy1.7.8 负载均衡

    RabbitMQ 默认的集群模式,也就是普通模式,最大的问题就在于存储队列完整数据的节点一旦宕机, 如果是非持久化队列,则消息丢失;如果是持久化队列+持久化消息,则必须等该节点恢复. 所以后来 Rab ...

  7. 解决 RabbitMQ 集群 Channel shutdown: connection error 错误(HAProxy 负载均衡)

    相关文章:搭建 RabbitMQ Server 高可用集群 具体错误信息: 2018-05-04 11:21:48.116 ERROR 60848 --- [.168.0.202:8001] o.s. ...

  8. 【python】-- RabbitMQ 队列消息持久化、消息公平分发

    RabbitMQ 队列消息持久化 假如消息队列test里面还有消息等待消费者(consumers)去接收,但是这个时候服务器端宕机了,这个时候消息是否还在? 1.队列消息非持久化 服务端(produc ...

  9. RabbitMQ基本用法、消息分发模式、消息持久化、广播模式

    RabbitMQ基本用法 进程queue用于同一父进程创建的子进程间的通信 而RabbitMQ可以在不同父进程间通信(例如在word和QQ间通信) 示例代码 生产端(发送) import pika c ...

随机推荐

  1. Python制作统计图形

    转载自:http://www.dcharm.com/?p=15 Python一般使用Matplotlib制作统计图形,用它自己的说法是‘让简单的事情简单,让复杂的事情变得可能’.(你说国外的“码农”咋 ...

  2. 正则表达式学习笔记(附:Java版示例代码)

    具体学习推荐:正则表达式30分钟入门教程 .         除换行符以外的任意字符\w      word,正常字符,可以当做变量名的,字母.数字.下划线.汉字\s        space,空白符 ...

  3. [BZOJ1056][BZOJ1862][HAOI2008][Zjoi2006]排名系统

    [BZOJ1056][BZOJ1862][HAOI2008][Zjoi2006]排名系统 试题描述 排名系统通常要应付三种请求:上传一条新的得分记录.查询某个玩家的当前排名以及返回某个区段内的排名记录 ...

  4. 贴一下WC总结里提到的那道裸题吧。。。

    [bzoj4034][HAOI2015]T2 试题描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 ...

  5. homework160809207刘兆轩

    # include <stdio.h> int main() { float a,b,c,m,n,l,k,j,i; printf("请输入三个数:\n"); scanf ...

  6. 多版本python共存

    当不同版本python之间相互不能兼容时,可以使用virtualenv创建不同版本python的虚拟环境 当没有指定python解释器时(如下-p 即为指定的python版本),将使用默认的全局pyt ...

  7. SQL Sever2008r2 数据库服务各种无法启动的解决办法

    一.Sql Server服务远程过程调用失败解决 以前出现过这个问题,那时候是因为把实例安装在了D盘,后来D盘被格式化了.然后,这些就没了.今天早上打开电脑,竟然又出现这个问题,可是Server200 ...

  8. zookeeper部署及集群测试

    zookeeper部署及集群测试 环境 三台测试机 操作系统: centos7 ; hostname: c1 ; ip: 192.168.1.80 操作系统: centos7 ; hostname: ...

  9. 一步步搭建docker私有仓库并从私有仓库中下载镜像

    一步步搭建docker私有仓库 #下载镜像 docker pull registry#查看镜像 docker images #运行私有仓库,指定端口和数据卷 docker run -d -p : -v ...

  10. cf555b

    题意:按顺序给出多个互不相交的区间(表示一些小岛),和一些可以连接区间的桥,每个桥有固定的长度.区间和桥的数量都是2*10^5. 两个相邻的小岛之间的桥的长度必须小于等于最远点距离,大于等于最近点距离 ...