rabbitmq简介,安装,api操作

本文介绍了RabbitMQ,一个基于AMQP协议的开源消息队列系统,用于组件解耦。详细讲解了RabbitMQ的基本概念,如ConnectionFactory、Connection和Channel,并阐述了RabbitMQ的安装过程。此外,还通过Java API展示了RabbitMQ的简单模式、工作队列模式、发布订阅模式、路由模式和Topics模式的使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

rabbitmq介绍

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。 AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。 下面将重点介绍RabbitMQ中的一些基础概念,了解了这些概念,是使用好RabbitMQ的基础。
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。 Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。

rabbitmq原理图解

这里写图片描述

1.安装rabbitmq
rabbitmq适合安装在linux系统上
安装过程 参考 (http://www.rabbitmq.com/install-rpm.html

安装命令:yum -y install epel-release.noarch 
直接无法安装需要安装类似maven的私服叫epel-release.noarch

查看是否存在rabbitmq 然后安装

yum search rabbitmq-server  
yum -y install rabbitmq-server

这里写图片描述

搜索包 rpm -ql rabbitmq-server
控制的命令在 /sbin/rabbitmqct

默认没有配置文件
这里写图片描述

查看rabbitmq-server被安装的所有文件的位置

/etc/logrotate.d/rabbitmq-server  
/etc/rabbitmq  
/etc/rabbitmq/rabbitmq.config  
/usr/lib/ocf/resource.d/rabbitmq/rabbitmq-server  
/usr/lib/rabbitmq/bin  
/usr/lib/rabbitmq/bin/rabbitmq-defaults  
/usr/lib/rabbitmq/bin/rabbitmq-env  
/usr/lib/rabbitmq/bin/rabbitmq-plugins  
/usr/lib/rabbitmq/bin/rabbitmq-server  
/usr/lib/rabbitmq/bin/rabbitmqctl  
其中比较重要的两个参考文件(这两个只是参考)
运行配置文件:rabbitmq.config.example
环境配置文件:/usr/share/man/man5/rabbitmq-env.conf.5.gz 
默认该两文件需要配置在 /etc/rabbitmq目录下 默认只有一个
配置文件在 rabbitmq.config-example中需要将改目录考到 cd  /etc/rabbitmq目录下
默认安装过程中会自动到操作系统创建一个账号rabbitmq改账号默认在 /etc/passwd 目录下

rabbitmq默认安装后 会添加账号rabbitmq 默认以该账号运行

这里写图片描述

2.启动rabbitmq
启动后 查看默认的端口 5672
启动 命令

service rabbitmq-server start

Starting rabbitmq-server: SUCCESS启动成功

查看端口是否启动命令
windows中查看端口命令将grep换成find即可

[root@hyp]# netstat -aon | grep 5672  
tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      off (0.00/0/0)  
tcp6       0      0 :::5672                 :::*                    LISTEN      off (0.00/0/0)  

默认会在 cd/etc/init.d目录下会创建一个文件叫rabbitmq-server
这里写图片描述
cd/etc/init.d服务的路径
查看运行状态

[root@hyp]# service rabbitmq-server status  
Redirecting to /bin/systemctl status  rabbitmq-server.service  
● rabbitmq-server.service - RabbitMQ broker  
   Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled; vendor preset: disabled)  
   Active: active (running) since Tue 2017-11-07 05:52:27 PST; 6min ago  
 Main PID: 8507 (beam)  
   CGroup: /system.slice/rabbitmq-server.service  
           ├─8507 /usr/lib64/erlang/erts-5.10.4/bin/beam -W w -K true -A30 -P 1048576 -- -root /usr/lib64/erlang -progname...  
           ├─8522 /usr/lib64/erlang/erts-5.10.4/bin/epmd -daemon  
           ├─8579 inet_gethost 4  
           └─8580 inet_gethost 4  

Nov 07 05:52:24 node3 systemd[1]: Starting RabbitMQ broker...  
Nov 07 05:52:24 node3 systemd[1]: rabbitmq-server.service: Got notification message from PID 8522, but reception on...ID 8507  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: RabbitMQ 3.3.5. Copyright (C) 2007-2014 GoPivotal, Inc.  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: ##  ##  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: ##########  Logs: /var/log/rabbitmq/rabbit@node3.log  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: ######  ##        /var/log/rabbitmq/rabbit@node3-sasl.log  
Nov 07 05:52:26 node3 rabbitmq-server[8507]: ##########  
Nov 07 05:52:27 node3 systemd[1]: Started RabbitMQ broker.  
Nov 07 05:52:27 node3 rabbitmq-server[8507]: Starting broker... completed with 0 plugins.  
Hint: Some lines were ellipsized, use -l to show in full.  

查看已经安装的插件

rabbitmq-plugins list

默认在rabbitmq-plugins

这里写图片描述

rabbitmq默认提供了一个web管理工具(rabbitmq_management)参考官方http://www.rabbitmq.com/management.html 默认已经安装 是一个插件
查看所有插件

这里写图片描述

启动rabbitmq的界面插件

./rabbitmq-plugins enable rabbitmq_management

重启rabbitmq-server

 service rabbitmq-server restart

加入插件后会有一个默认端口15672 浏览器访问(当前机器ip )http://192.168.73.130:15672/
输入用户名和密码 guest和guest
这里写图片描述

登录后效果
这里写图片描述

3.rabbitmq api调用
参考官方文档 http://www.rabbitmq.com/getstarted.html
rabbitmq 官方操作api提供了n多种语言 前面几种都会 java是本职 所以使用java
这里写图片描述

rabbitmq支持6种消息接受和转发机制
1.简单模式http://www.rabbitmq.com/tutorials/tutorial-one-java.html
Queue(队列)是RabbitMQ的内部对象,用于存储消息,用下图表示。

这里写图片描述

RabbitMQ中的消息都只能存储在Queue中,生产者(下图中的P)生产消息并最终投递到Queue中,消费者(下图中的C)可以从Queue中获取消息并消费。

这里写图片描述

eclipse添加maven的jar项目添加依赖

<!-- rabbitmq的配置 -->
<dependency>
   <groupId>com.rabbitmq</groupId>
   <artifactId>amqp-client</artifactId>
   <version>4.2.0</version>
</dependency>

生产者代码

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 *  简单模式
 * @author Administrator
 *
 */
public class Pub_Email {
    /**
     * 序列化
     * 将对象序列化转为字节数组
     */
    public static byte[] ser(Object obj)throws Exception{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(obj);
        return bos.toByteArray();
    }
    /**
     * 反序列化
     * 将字节数组反序列化转为字节数组
     */
    public static Object dser(byte[] src)throws Exception{
        ByteArrayInputStream bis=new ByteArrayInputStream(src);
        ObjectInputStream ois=new ObjectInputStream(bis);
        ois.readObject();
        return ois.readObject();
    }
    /**
     * 任务被发送的队列名称
     */
    static String QUEUE_NAME="MAIL_QUEUE";
    public static void main(String[] args) throws Exception, TimeoutException {
        // 模拟一个任务消息
        Map<String, String> map=new HashMap<String, String>();
        map.put("sendTo","hyp2549882772@126.com");
        map.put("subject", "测试邮件");
        map.put("content", "注册成功您的验证马是123456");
        //推送到队列服务器
        //连接远程rabbit-server服务器  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.73.130");  
        factory.setPort(5672);  
        //通过ConnectionFactory创建一个连接connection
        Connection connection = factory.newConnection();  
        //通过connection创建一个频道channel
        Channel channel = connection.createChannel();  

        //定义创建一个队列  
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //发送的消息
        String message="Hello World";
        //生产者向消费这发送消息(pulsh) 注意发送和接收段相同字符集则出现乱码
        channel.basicPublish("", QUEUE_NAME, null, ser(map));
        System.out.println(" [x] Sent 5 message"); 
        //关闭频道
        channel.close();
        //关闭连接
        connection.close();  
    }
}

消费者代码

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


/**
 *  简单模式
 * @author Administrator
 *
 */
public class Mail_Cons {
    /**
     * 序列化
     * 将对象序列化转为字节数组
     */
    public static byte[] ser(Object obj)throws Exception{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(obj);
        return bos.toByteArray();
    }
    /**
     * 反序列化
     * 将字节数组反序列化转为字节数组
     */
    public static Object dser(byte[] src)throws Exception{
        ByteArrayInputStream bis=new ByteArrayInputStream(src);
        ObjectInputStream ois=new ObjectInputStream(bis);
        return ois.readObject();
    }
    /**
     *异步接收
     */
    static String QUEUE_NAME="MAIL_QUEUE";
    public static void main(String[] args) throws Exception, TimeoutException {
        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
            Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);  
            //定义回调抓取消息  
            Consumer consumer = new DefaultConsumer(channel) {  
                @Override  
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,  
                        byte[] body) throws IOException {  
                       try {
                        Map map=(Map)Mail_Cons.dser(body);
                        System.out.println(map.get("content"));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }  
            };  
       //为channel指定消费者
        channel.basicConsume(QUEUE_NAME, true, consumer);  
    }
}

消费这发送邮件

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

@RestController
public class Mail_Cons {
    @Autowired
    private  JavaMailSender jms;
    /**
     * 序列化
     * 将对象序列化转为字节数组
     */
    public static byte[] ser(Object obj)throws Exception{
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(obj);
        return bos.toByteArray();
    }
    /**
     * 反序列化
     * 将字节数组反序列化转为字节数组
     */
    public static Object dser(byte[] src)throws Exception{
        ByteArrayInputStream bis=new ByteArrayInputStream(src);
        ObjectInputStream ois=new ObjectInputStream(bis);
        return ois.readObject();
    }
    /**
     *异步接收
     */
    static String QUEUE_NAME="MAIL_QUEUE";
    @GetMapping("/send")
    public String send() throws Exception{

        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
            Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);  
            //定义回调抓取消息  
            Consumer consumer = new DefaultConsumer(channel) {  

                @Override  
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,  
                        byte[] body) throws IOException {  

                       try {
                        Map map=(Map)Mail_Cons.dser(body);
                        System.out.println(map.get("content"));
                        //真实发送邮件
                        SimpleMailMessage mailMessage  =   new  SimpleMailMessage();
                        mailMessage.setFrom("hyp2549882772@126.com");
                        mailMessage.setTo(map.get("sendTo").toString());
                        mailMessage.setSubject(map.get("subject").toString());
                        mailMessage.setText(map.get("content").toString());
                        jms.send(mailMessage);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }  
            };  
            //为channel指定消费者
            channel.basicConsume(QUEUE_NAME, true, consumer); 
            return "1";
    }
}
application.properties

spring.mail.host=smtp.126.com
spring.mail.username= hyp2549882772
spring.mail.password= yyz123456
spring.mail.port= 25
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
spring.application.name=SENDMAIL
server.port=8080
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.et</groupId>
  <artifactId>Rabbitmq-Cons</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
   <dependencies>
    <!-- rabbitmq的配置 -->
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>4.2.0</version>
    </dependency>
    <!-- 发送邮件配置 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <!-- 将发送邮件的为服务注册到eureka注册中心的配置 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
  </dependencies>
</project>

生产者启动后

这里写图片描述

消费者启动后

这里写图片描述
2. 工作队列模式(http://www.rabbitmq.com/tutorials/tutorial-two-java.html
对于资源密集型任务,我们等待其处理完成在很多情况下是不现实的,比如无法在http的短暂请求窗口中处理大量耗时任务,
为了达到主线程无需等待,任务异步执行的要求,我们可以将任务加入任务队列,如图,多个workers可以共享
工作队列一般用于任务分配 发布者发布任务到队列 多个消息接受者 接受消息 谁接受到某个消息 其他接受者就只能消费其他消息 队列中的
工作队列一般用于任务分配 发布者发布任务到队列 多个消息接受者 接受消息 谁接受到某个消息 其他接受者就只能消费其他消息 队列中的
一个消息只能被一个接受者消费
这里写图片描述

生产者代码

import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * 工作队列模式
 * @author Administrator
 *
 */
public class Pub_Work {

    /**
     * 任务被发送的队列名称
     */
    static String QUEUE_NAME="WORK_QUEUE";
    public static void main(String[] args) throws Exception, TimeoutException {
        //推送到队列服务器
        //连接远程rabbit-server服务器  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.73.130");  
        factory.setPort(5672);  
        //通过ConnectionFactory创建一个连接connection
        Connection connection = factory.newConnection();  
        //通过connection创建一个频道channel
        Channel channel = connection.createChannel();  
        //定义创建一个队列  
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //发送的消息
        String message="Hello World";
        for(int i=0;i<10;i++){
             //生产者向消费这发送消息(pulsh) 注意发送和接收段相同字符集则出现乱码
            channel.basicPublish("", QUEUE_NAME, null,("这是"+i).getBytes("UTF-8"));
        }
        System.out.println(" [x] Sent 5 message"); 

        //关闭频道
        channel.close();
        //关闭连接
        connection.close();  
    }
}

消费者代码

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


/**
 *  工作队列模式
 * @author Administrator
 *
 */

public class Mail_Work {
     /**
     *异步接收
     */
    static String QUEUE_NAME="WORK_QUEUE";
    public static void main(String[] args) throws Exception, TimeoutException {
        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
            Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);  
            //定义回调抓取消息  
            Consumer 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,"UTF-8"));
                }  
            };  
       //为channel指定消费者
        channel.basicConsume(QUEUE_NAME, true, consumer);  
    }
}

测试先同时启动两个任务接受者
可以通过 webgui 查看 是否出现了两个连接 一个队列(监听同一个队列mywork)

这里写图片描述
运行 发布者 查看两个接受者的控制台 发现一个接收到三条消息

第一个接受者

这是0
这是2
这是4
这是6
这是8

第二个接受者

这是1
这是3
这是5
这是7
这是9

3.发布订阅模式http://www.rabbitmq.com/tutorials/tutorial-three-java.html
RabbitMQ消息模型的核心理念是生产者永远不会直接发送任何消息给队列,一般的情况生产者甚至不知道消息应该发送到哪些队列。
相反的,生产者只能发送消息给转发器(Exchange)。转发器是非常简单的,一边接收从生产者发来的消息,另一边把消息推送到队列中。转发器必须清楚的知道消息如何处理它收到的每一条消息。是否应该追加到一个指定的队列?是否应该追加到多个队列?或者是否应该丢弃?这些规则通过转发器的类型进行定义。
这里写图片描述
发布订阅模式 引入了交换器的概念 消息发布者发布消息到交换器 订阅者定义一个队列(每个订阅者定义一个)用于接受消息 交换器 起到了
交换器 有以下几种类型 direct, topic, headers and fanout

发布订阅模式 应该使用fanout(广播)

通过命令 rabbitmqctl list_exchanges 或者查看webgui 查看exchange
这里写图片描述
列表中有很多amq.*开头的交换器 第一个是默认 之前的两种简单模式和工作队列模式未定义交换器 使用的是第一个defalt

发布者代码

import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 *发布订阅模式
 * @author Administrator
 *
 */
public class Pub_Log {
    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log";
    public static void main(String[] args) throws Exception, TimeoutException {
        //推送到队列服务器
        //连接远程rabbit-server服务器  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.73.130");  
        factory.setPort(5672);  
        //通过ConnectionFactory创建一个连接connection
        Connection connection = factory.newConnection();  
        //通过connection创建一个频道channel
        Channel channel = connection.createChannel();  
        //发布订阅模式 没有key  为空       类型(fanout) 
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout",true);  
        String message = null;  
        //同时发送5条消息  
        for(int i=0;i<10;i++){  
            message="发送第"+i+"消息";  
            //第二个参数就是routingkey  不填 默认会转发给所有的订阅者队列  
            channel.basicPublish(EXCHANGE_NAME, "", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));  
        }   
        System.out.println(" [x] Sent 6 message");  
    }
}

订阅者代码

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 *  发布订阅模式
 * @author Administrator
 *
 */

public class Log_Cons {
    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log";
    public static void main(String[] args) throws Exception, TimeoutException {
        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
             Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.exchangeDeclare(EXCHANGE_NAME, "fanout",true);  
            //channel.basicQos(1);
            //产生一个随机的队列 该队列用于从交换器获取消息
            String queueName = channel.queueDeclare().getQueue();
            //将队列和某个交换机丙丁 就可以正式获取消息了 routingkey和交换器的一样都设置成空
            channel.queueBind(queueName, EXCHANGE_NAME, "");

            //定义回调抓取消息
            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");
                    System.out.println(message);
                    //参数2 true表示确认该队列所有消息  false只确认当前消息 每个消息都有一个消息标记
                }
            };
            //参数2 表示手动确认
            channel.basicConsume(queueName, true, consumer);
    }
}

先启动两个订阅者 Rec
发送者Pub执行
发现两个订阅者都获取到了消息

发送第0消息
发送第1消息
发送第2消息
发送第3消息
发送第4消息
发送第5消息
发送第6消息
发送第7消息
发送第8消息
发送第9消息

4.路由模式http://www.rabbitmq.com/tutorials/tutorial-three-java.html
不同机器用来做不同的事情 类型 direct
路由模式其实和订阅模式差不多,只不过交换机的类型不同而已
前面第三种发布订阅模式 每个订阅者都会收到交换器发出的消息 因为发布者发布消息的routingkey是空 订阅者接受消息队列的routingkey也是空

发布者发布的消息 所有的订阅者都能接收到 路由模式表示 发布者发布的消息的routingkey和订阅者接受消息队列的routingkey都不为空 相同的则可以
这里写图片描述
发布者代码

import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 *路由模式
 * @author Administrator
 *
 */
public class Pub_Log_Route {

    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log_route";
    public static void main(String[] args) throws Exception, TimeoutException {

        //推送到队列服务器
        //连接远程rabbit-server服务器  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.73.130");  
        factory.setPort(5672);  
        //通过ConnectionFactory创建一个连接connection
        Connection connection = factory.newConnection();  
        //通过connection创建一个频道channel
        Channel channel = connection.createChannel();  
        //路由模式       类型(direct) 
        channel.exchangeDeclare(EXCHANGE_NAME, "direct",true);  
        String message = null;  
        //第二个参数就是routingkey  不填 默认会转发给所有的订阅者队列  
        channel.basicPublish(EXCHANGE_NAME, "error", MessageProperties.PERSISTENT_TEXT_PLAIN, "系统奔溃,内存溢出".getBytes("UTF-8"));
        channel.basicPublish(EXCHANGE_NAME, "info", MessageProperties.PERSISTENT_TEXT_PLAIN, "张三于2018-1-11号访问该页面".getBytes("UTF-8"));  
        channel.basicPublish(EXCHANGE_NAME, "info", MessageProperties.PERSISTENT_TEXT_PLAIN, "李四于2018-1-11号登录该网页".getBytes("UTF-8"));  
        System.out.println(" [x] Sent 6 message");  
    }
}

订阅者代码

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 *  路由模式 类型 direct
 * @author Administrator
 *
 */

public class Log_Cons_Route {
    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log_route";
    public static void main(String[] args) throws Exception, TimeoutException {
        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
             Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.exchangeDeclare(EXCHANGE_NAME, "direct",true);  
            //channel.basicQos(1);
            //产生一个随机的队列 该队列用于从交换器获取消息
            String queueName = channel.queueDeclare().getQueue();
            //将队列和某个交换机丙丁 就可以正式获取消息了 routingkey和交换器的一样都设置成空
            channel.queueBind(queueName, EXCHANGE_NAME, "info");
          //  channel.queueBind(queueName, EXCHANGE_NAME, "error");
            //定义回调抓取消息
            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");
                    System.out.println(message);
                    //参数2 true表示确认该队列所有消息  false只确认当前消息 每个消息都有一个消息标记
                }
            };
            //参数2 表示手动确认
            channel.basicConsume(queueName, true, consumer);    
    }
}

先启动两个订阅者 Rec
发送者Pub执行

第一个订阅者获取到消息

张三于2018-1-11号访问该页面
李四于2018-1-11号登录该网页

第二个订阅者获取到消息

系统奔溃,内存溢出

5.Topics路由模式http://www.rabbitmq.com/tutorials/tutorial-three-java.html
该种模式和路由模式类似 只是消息的routingkey 是通过.隔开的多个字符组成 订阅者的消息队列绑定的routingkey可以使用通配符通配所有满足
条件的交换机消息 匹配上则接受消息 这种类型的消息 使用的交换器类型是 topic
这里写图片描述

接受者接受消息可以设置routingkey为表达式模糊匹配 
*可以匹配一个标识符。
#可以匹配0个或多个标识符。

l比如 1610.# 表示 1610班所有学生 获取到 两条
比如 1607.*.girl 表示1701的所有女生 获取到一条

发布者代码块

import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 *topic模式  特殊的路由模式
 * @author Administrator
 *
 */
public class Pub_Log_TopicRoute {

    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log_topic";
    public static void main(String[] args) throws Exception, TimeoutException {

        //推送到队列服务器
        //连接远程rabbit-server服务器  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("192.168.73.130");  
        factory.setPort(5672);  
        //通过ConnectionFactory创建一个连接connection
        Connection connection = factory.newConnection();  
        //通过connection创建一个频道channel
        Channel channel = connection.createChannel();  
        //topic模式       类型(topic) 系统名.error 
        channel.exchangeDeclare(EXCHANGE_NAME, "topic",true);  
        String message = null;  
        //第二个参数就是routingkey  不填 默认会转发给所有的订阅者队列  
        //如果a系统下有子系统用c.c1.info表示
        channel.basicPublish(EXCHANGE_NAME, "a.error", MessageProperties.PERSISTENT_TEXT_PLAIN, "系统奔溃,内存溢出".getBytes("UTF-8"));
        channel.basicPublish(EXCHANGE_NAME, "a.info", MessageProperties.PERSISTENT_TEXT_PLAIN, "张三于2018-1-11号访问该页面".getBytes("UTF-8"));  
        channel.basicPublish(EXCHANGE_NAME, "a.info", MessageProperties.PERSISTENT_TEXT_PLAIN, "李四于2018-1-11号登录该网页".getBytes("UTF-8"));  
        channel.basicPublish(EXCHANGE_NAME, "b.error", MessageProperties.PERSISTENT_TEXT_PLAIN, "系统奔溃,内存溢出".getBytes("UTF-8"));
        channel.basicPublish(EXCHANGE_NAME, "b.info", MessageProperties.PERSISTENT_TEXT_PLAIN, "张三于2018-1-11号访问该页面".getBytes("UTF-8"));  
        channel.basicPublish(EXCHANGE_NAME, "b.info", MessageProperties.PERSISTENT_TEXT_PLAIN, "李四于2018-1-11号登录该网页".getBytes("UTF-8")); 
        channel.basicPublish(EXCHANGE_NAME, "c.c1.info", MessageProperties.PERSISTENT_TEXT_PLAIN, "李四于2018-1-11号登录该网页".getBytes("UTF-8"));  
        System.out.println(" [x] Sent 6 message");     
    }
}

消费者代码

import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


/**
 *  路由模式 类型 direct
 * @author Administrator
 *
 */
public class Log_Cons_TopicRoute {  
    /**
     *交换器的名字 交换器有很多类型
     */
    private static String EXCHANGE_NAME="amp_log_topic";
    public static void main(String[] args) throws Exception, TimeoutException {
        //创建一个ConnectionFactory连接工厂
         ConnectionFactory factory = new ConnectionFactory();
         //通过ConnectionFactory设置Rabbitmq所在ip等信息
            factory.setHost("192.168.73.130");
            //通过ConnectionFactory创建一个连接connection
            Connection connection = factory.newConnection();
            //通过connection创建一个频道channel
             Channel channel = connection.createChannel();  
            //消费者也需要定义队列 有可能消费者先于生产者启动   
            channel.exchangeDeclare(EXCHANGE_NAME, "topic",true);  
            //channel.basicQos(1);
            //产生一个随机的队列 该队列用于从交换器获取消息
            String queueName = channel.queueDeclare().getQueue();
            //将队列和某个交换机丙丁 就可以正式获取消息了 routingkey和交换器的一样都设置成空
            //消费者定义的key 可以使用通配符 通配交换器的消息       a.*代表两个中的一段 c.#代表多段    
            channel.queueBind(queueName, EXCHANGE_NAME, "c.#");

            //定义回调抓取消息
            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");
                    System.out.println(message);
                    //参数2 true表示确认该队列所有消息  false只确认当前消息 每个消息都有一个消息标记
                }
            };
            //参数2 表示手动确认
            channel.basicConsume(queueName, true, consumer);    
    }
}

先启动两个订阅者 Rec
发送者Pub执行

a.*的Rec输出

系统奔溃,内存溢出
张三于2018-1-11号访问该页面
李四于2018-1-11号登录该网页

c.#l的Rec输出

李四于2018-1-11号登录该网页

6.RPC模式
这里写图片描述
该模式是rpc 远程方法调用 这里不介绍 http协议调用更经典

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值