Publisher:消息的生产者。
Virtual Host:虚拟主机。各个主机拥有自己的配置(队列、交换机)。
Exchange:交换器:接受消息,转发给队列。
Banding:绑定。将消息绑定至路由。
Queue:消息队列。
Channel:信道,复用TCP连接,独立的双向数据流通道。包括旗下的Connection(一个TCP连接)
Consumer:消息的消费者
public class ConnectionUtil {
public static Connection getConnection() throws Exception{
ConnectionFactory factory = new ConnectionFactory();
//设置连接信息
factory.setHost("IP");
factory.setPort(5672);
factory.setVirtualHost("/lagou");
factory.setUsername("zz");
factory.setPassword("123456");
//获得连接
Connection connection = factory.newConnection();
return connection;
}
public static void main(String[] args) throws Exception {
Connection connection = getConnection();
System.out.println(connection);
//amqp://zz@IP:5672//lagou
}
}
单纯的存储、转发消息。
生产者:
public class sender {
public static void main(String[] args) throws Exception {
//获取连接
Connection connection = ConnectionUtil.getConnection();
//创建信道
Channel channel = connection.createChannel();
//声明队列
//队列名、是否持久化、是否排外、是否自动删除(连接为0时删除)、队列参数
channel.queueDeclare("no1", false, false, false, null);
//发布消息
String msg = new String("hello2 RabbitMQ");
//交换机名、队列名、消息属性、字节内容
channel.basicPublish("", "no1", null, msg.getBytes());
System.out.println("已发送:" + msg);
//资源释放
channel.close();
connection.close();
}
}
消费者:
public class Recer {
public static void main(String[] args) throws Exception {
//获取连接
Connection connection = ConnectionUtil.getConnection();
//创建信道
Channel channel = connection.createChannel();
//从信道中获取消息
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override //交付处理(收件人信息,包裹上的快递标签,协议的配置,消息)
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));//body为消息内容
}
};
//监听队列 ACK机制 true自动确认
channel.basicConsume("no1", true, consumer);
}
}
这里生产者发布100条消息,不同消费者处理速度不同。
生产者:
//省略获取连接、创建信道、声明队列、与关闭资源
for (int i = 0; i < 100; i++) {
String msg = new String("hello " + i);
//发布100条消息到no1队列上
channel.basicPublish("", "no1", null, msg.getBytes());
System.out.println("已发送:" + msg);
}
消费者(两台消费者):
public class Recer1 {
static int i = 1; // 记录执行次数
public static void main(String[] args) throws Exception {
//获取队列
channel.queueDeclare("no1", false, false, false, null);
//指定分配方式(按效率来)
channel.basicQos(1);
//手动确认
hannel.basicAck(envelope.getDeliveryTag(), false);
//手动确认
channel.basicConsume("no1", false, consumer);
}
}
声明路由关键字:fanout
P为生产者、红色为具体队列、bind为绑定。
X是路由:将生产者发布的信息,绑定到不同的队列。
运行过程:启动生产者(创建路由)、启动消费者、再次启动生产者。
public class sender {
public static void main(String[] args) throws Exception {
//声明路由
/*fanout:
不处理路由键(只需要将队列绑定到路由上,发送到路由的消息都会被转发到与该
路由绑定的所有队列上)*/
channel.exchangeDeclare("exchange","fanout");
String msg="hello 消息订阅模式";
channel.basicPublish("exchange","",null,msg.getBytes());
}
}
//获取连接、创建信道
//声明队列
channel.queueDeclare("no3", false, false, false, null);
/*
参数1:队列名
参数2:交换器名称
参数3:路由键(暂时无用,""即可)
*/
//将消息队列绑定路由
channel.queueBind("no3", "exchange", "");
声明路由关键字:direct。
根据路由键,定向分发消息给不同的队列。
//声明路由
// direct:根据路由键进行定向分发消息
channel.exchangeDeclare("exchange_direct","direct");
String msg="hello 路由模式";
channel.basicPublish("exchange_direct","delete",null,msg.getBytes());
channel.queueDeclare("no1",false,false,false,null);
//绑定路由.路由键是delete绑定到队列1
channel.queueBind("no1","exchange_direct","delete");
channel.queueDeclare("no2",false,false,false,null);
//绑定路由.路由键是insert绑定到队列1
channel.queueBind("no2","exchange_direct","insert");
声明路由关键字:topic
路由键支持模糊匹配:
*:一个字符
#:N
在消费者未确认前、未消费前。防止信息丢失。
路由和队列均持久化
生产者:
channel.exchangeDeclare("exchange_topic","topic",true);//路由持久化
String msg="hello 通配符模式";
//参数3:消息持久化
channel.basicPublish("exchange_topic","user.select", MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes());
消费者:
channel.queueDeclare("no5",true,false,false,null);
//绑定路由 路由键:user.开头
channel.queueBind("no5","exchange_topic","user.#");
<rabbit:queue name="queue1"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:topic-exchange name="spring_topic_exchange">
<rabbit:bindings>
<rabbit:binding queue="queue1" pattern="msg.#" >rabbit:binding>
rabbit:bindings>
rabbit:topic-exchange>
<bean id="jsonMessageConverter"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter"/>
<rabbit:template
id="rabbitTemplate"
connection-factory="connectionFactory"
exchange="spring_topic_exchange"
message-converter="jsonMessageConverter"
/>
public class Sender {
public static void main(String[] args) {
//加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//从容器中获得模板对象
RabbitTemplate template = context.getBean(RabbitTemplate.class);
//消息发送
HashMap<String, String> map = new HashMap();
map.put("name", "张三");
map.put("age", "18");
//转换并发送
template.convertAndSend("msg.user", map);
context.close();
}
}
配置连接、配置队列、配置队列管理。前三步骤与生产端一致。
注解扫描、配置监听、
<context:component-scan base-package="listener"/>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="consumerListener" queue-names="queue1"/>
rabbit:listener-container>
public class ConsumerListener implements MessageListener {
//json装换类 序列化与反序列化 使用最多的类,用来转换json的
private static final ObjectMapper MAPPER = new ObjectMapper();
public void onMessage(Message message) {
try {
//message->json
JsonNode jsonNode = MAPPER.readTree(message.getBody());
String name = jsonNode.get("name").asText();
String age = jsonNode.get("age").asText();
System.out.println("获取到:" + name + age);
} catch (IOException e) {
e.printStackTrace();
}
}
}
channel.txSelect(): 开启事务
channel.txCommit() :提交事务
channel.txRollback() :回滚事务
命令控制。在Spring的封装下,使用Confirm机制。
<rabbit:connection-factory
publisher-confirms="true"
/>
<rabbit:template
confirm-callback="msgSendConfirmCallback"
/>
<bean class="confirm.MsgSendConfirm" id="msgSendConfirmCallback"/>
@Component
public class MsgSendConfirm implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
/*
correlationData 消息id
b 确认状态
s 失败原因
*/
if (b) {
System.out.println("确认成功!");
} else {
System.out.println("发送失败!");
}
}
}
<rabbit:listener-container connection-factory="connectionFactory"
prefetch="3" acknowledge="manual">
<rabbit:listener ref="consumerListener" queuenames="test_spring_queue_1" />
rabbit:listener-container>
<rabbit:queue name="queue_ttl" auto-declare="true"> <rabbit:queue-arguments>
<entry key="x-message-ttl" value-type="long" value="5000">entry>
rabbit:queue-arguments>
rabbit:queue>
RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
// 创建消息配置对象
MessageProperties messageProperties = new MessageProperties();
// 设置消息过期时间
messageProperties.setExpiration("6000");
// 创建消息
Message message = new Message("6秒后自动删除".getBytes(),
messageProperties);
// 发送消息
rabbitTemplate.convertAndSend("msg.user", message);
<rabbit:connection-factory
id="connectionFactory"
host="IP"
port="5672"
username="zz"
password="123456"
virtual-host="/lagou"
publisher-confirms="true"
/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:template
id="rabbitTemplate"
connection-factory="connectionFactory"
exchange="exchange1"
/>
<rabbit:direct-exchange name="exchange1">
<rabbit:bindings>
<rabbit:binding key="dlx_ttl" queue="ttl_quque"/>
rabbit:bindings>
rabbit:direct-exchange>
<rabbit:queue name="ttl_quque">
<rabbit:queue-arguments>
<entry key="x-message-ttl" value-type="long" value="5000" />
<entry key="x-dead-letter-exchange" value="dlx_exchange"/>
rabbit:queue-arguments>
rabbit:queue>
<rabbit:direct-exchange name="dlx_exchange">
<rabbit:bindings>
<rabbit:binding key="dlx_ttl" queue="qlx_quque"/>
rabbit:bindings>
rabbit:direct-exchange>
<rabbit:queue name="qlx_quque"/>
<rabbit:listener-container connection-factory="connectionFactory" prefetch="3"
acknowledge="manual">
<rabbit:listener ref="consumerListener" queue-names="dlx_queue" />
rabbit:listener-container>
# erlang
rpm -ivh erlang-21.3.8.16-1.el7.x86_64.rpm
# socat
rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm
# RabbitMQ
rpm -ivh rabbitmq-server-3.8.6-1.el7.noarch.rpm
#启动管理插件
rabbitmq-plugins enable rabbitmq_management
# 启动RabbitMQ
systemctl start rabbitmq-server.service
systemctl status rabbitmq-server.service
systemctl restart rabbitmq-server.service
systemctl stop rabbitmq-server.service
# 创建账号
rabbitmqctl add_user laosun 123456
# 设置用户角色
rabbitmqctl set_user_tags laosun administrator
# 设置用户权限
[root@localhost opt]# rabbitmqctl set_permissions -p "/" laosun ".*" ".*" ".*"
127.0.0.1 name1 localhost localhost.localdomain localhost4
localhost4.localdomain4
::1 nam1 localhost localhost.localdomain localhost6
localhost6.localdomain6
192.168.204.141 nam1
192.168.204.142 name2
scp /var/lib/rabbitmq/.erlang.cookie 192.168.204.142:/var/lib/rabbitmq
# 重启服务器
reboot
# 启动rabbitmq服务
systemctl start rabbitmq-server
# 加入集群节点
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@A
rabbitmqctl start_app
# 查看节点状态
rabbitmqctl cluster_status
rabbitmqctl set_policy xall "^" '{"ha-mode":"all"}'
+ name1、name2对应各服务器的主机名
2. 拷贝.erlang.cookie
```cmd
scp /var/lib/rabbitmq/.erlang.cookie 192.168.204.142:/var/lib/rabbitmq
# 重启服务器
reboot
# 启动rabbitmq服务
systemctl start rabbitmq-server
# 加入集群节点
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@A
rabbitmqctl start_app
# 查看节点状态
rabbitmqctl cluster_status
rabbitmqctl set_policy xall "^" '{"ha-mode":"all"}'