前言

  • 最近学习了尚硅谷-RabbitMQ
  • 受益匪浅,根据自己的理解做了下笔记,不正确的地方欢迎指正

正文

  • RabbitMQ是一个消息中间件,相当于一个中转站;用于接收、存储、转发消息数据

  • RabbitMQ的作用:

    1. 流量消峰:当服务器处理不了过多的请求时,在进入服务器之前先进入MQ,MQ会对请求做排序,防止服务器宕机
    2. 应用解耦:当系统的某个子系统出现故障无法正常工作时,该子系统要处理的内存会被缓存到消息队列中,当该子系统正常后再继续处理;提高用户体验,避免用户再次请求
    3. 异步处理:有些服务间的调用是异步的,当某个服务在工作时,其他服务不能调用该服务,可使用消息队列来进行监听管理调用
  • MQ的核心:

    1. 生产者:产生数据发送消息的模块
    2. 交换机:用于接收生产者的消息、将消息推送到队列中、处理消息
    3. 队列:相当于消息缓存区
    4. 消费者:用于接收消息的模块
    5. 一个应用程序既可以是生产者,又可以是消费者;比如一个通讯工具,既可以发送信息,也可以接收信息
  • CentOS安装RabbitMQ:

vi /etc/yum.repos.d/rabbitmq_erlang.repo          # 配置 centos8 Erlang的下载源
yum install erlang # 安装Erlang
# 下载rabbitmq的rpm,传输centos
yum install socat # 安装socat依赖
rpm -ivh rabbitmq-server-3.8.1-1.el8.noarch.rpm # 安装rabbitmq
rabbitmq-plugins enable rabbitmq_management # 安装web插件
vi /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.1/ebin/rabbit.app # 设置可远程访问
firewall-cmd --add-port=15672/tcp --permanent # 开放端口
firewall-cmd --add-port=5672/tcp --permanent # 开放端口
firewall-cmd --reload # 使防火墙生效
rabbitmq-server -detached # 后台启动
http://ip:15672/ # 浏览器访问rabbitmq页面
sudo rabbitmq-server # 控制台启动

详情查看:https://www.jianshu.com/p/8aece9517533

RabbitMQ启动时报错:error: node with name "rabbit" already running on "bogon"

错误原因:后台进程被占用

解决方案:

ps -ef|grep rabbitmq       # 查看进程
kill <进程id> # 杀死进程
# 再次启动

启动时报错:Warning: PID file not written; -detached was passed.

错误原因:警告信息,不影响

  • 创建账号:
rabbitmqctl add_user <用户名> <密码>
rabbitmqctl set_user_tags <用户名> administrator # 为当前账号设置超级管理员角色权限
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*" # 表示admin用户在"/"这个主机中具有配置、读、写权限
# 设置格式:set_permissions [-p <vhostpath>] <user> <conf> <write> <read> "/"表示主机路径,也可自定义其他路径
rabbitmqctl list_users # 查看所有账户和对应的角色
# 此时可在window系统的浏览器中访问Linux的rabbitmq,输入创建的账号
rabbitmqctl stop_app # 关闭
rabbitmqctl reset # 重启
rabbitmqctl start_app # 启动
  • window10上RabbitMQ环境配置:
1. 安装erlang,配置环境变量
i. ERLANG_HOME = 安装路径
ii. path中添加:%ERLANG_HOME%\bin
iii. cmd输入erl查看版本验证是否安装成功
2. 安装RabbitMQ
i. 进入rabbitMQ安装路径的sbin文件夹,打开cmd
ii. rabbitmq-plugins enable rabbitmq_management # 安装可视化插件
iii. 浏览器输入:http://localhost:15672/ # 访问RabbitMQ页面,用户名、密码为guest
3. RabbitMQ常用命令:
i. net start RabbitMQ # 启动
ii. net stop RabbitMQ # 停止
iii. rabbitmqctl status # 查看状态

详情查看:https://blog.csdn.net/qq_39915083/article/details/107034747

  • 消息传递入门案例:

    1. 导入所需依赖,新建一个类作为消息生产者,定义一个队列,创建连接工厂,创建连接,生成队列,发送消息
    2. 运行后发现massage发送到了rabbitmq,可在rabbitmq中查看
    3. 新建一个类作为消息消费者,创建连接工厂,创建连接,接收rabbitmq中的消息,可指定回调方法用于处理成功和失败的情况
  • 工作队列是为了避免立即执行大量任务,生产者发送大量消息到rabbitmq的队列,队列将消息缓存、排序、分发到不同的消费者

  • 轮训分发消息案例:

    1. 抽取连接的步骤抽取到一个工具类,新建生产者类和消费者类,消费者类启动多个线程
    2. 当生产者发送消息时,消息被多个线程(消费者类)平均接收
  • 消息应答:消费者接收消息并处理完成后,会告诉rabbitmq,这时rabbitmq会把消息删除了

  • 自动应答:建议不要使用,若消费者不能即使处理消息,会导致消息丢失

  • 手动应答:自定义应答方法

Channel.basicAck:用于肯定确认,RabbitMQ 已知道该消息并且成功的处理消息,可以将其丢弃了
Channel.basicNack:用于否定确认
Channel.basicReject:用于否定确认,与 Channel.basicNack 相比少一个参数Multiple
Multiple为true表示批量应答,即消费者同时处理多个消息,其中一个消息处理完成后,则告诉rabbitmq全处理完了
Multiple为false表示不批量应答,即消费者同时处理多个消息,其中一个消息处理完成后,则告诉rabbitmq处理完的那个消息
  • 消息自动重新入队,消息会保存在rabbitmq中,直到被消费者处理后、应答后才会删除,当消费者出现异常或者宕机时导致处理失败,rabbitmq会将消息分发给另一个消费者处理

  • 手动应答 + 自动重新入队案例:

    1. 新建一个类作为消息生产者
    2. 新建一个类作为消息消费者:让该线程睡眠1秒后打印出接收到消息,再新建一个消息消费者类:让该线程睡眠30秒后打印出接收的消息,是为了模拟处理复杂的消息;在两个消费者类中设置为手动应答
    3. 测试:生产者发送消息,两个消费者轮训接收消息,当第二个消费者在接收消息时突然关闭服务,这时消息没处理完,又被自动分配到第一个消费者处理
  • 队列持久化:

    在生产者类中设置

    消息应答机制确保了rabbitmq正常的情况下消息不会丢失

    队列设置持久化后,rabbitmq即使宕机或重启后,该队列中的消息依然存在于rabbitmq

    若将一个未持久化的队列设置成持久化后,重启会报错,这时由于该队列已经在rabbitmq中存在,在rabbitmq页面删除该队列,再重启线程,

    这时该队列在rabbitmq显示的持久化

    在rabbitmq控制台可查看设置了队列持久化的消息带有一个大写的D

  • 消息持久化:

    rabbitmq中的队列持久化了,发送的消息也需设置持久化,否则rabbitmq重启后,队列存在,队列中的消息丢失了

    在生产者类中发送消息时添加:MessageProperties.PERSISTENT_TEXT_PLAIN

  • 不公平分发:

    即处理速度快的消费者多分配消息,确保消费者不会出现空闲状态

    在消费者类添加:channel.basicQos(1) # 默认为0表示轮训,1表示不公平分发

  • 预取值:

    即指定消费者处理多少消息

    在消费者类添加:channel.basicQos(5) # 这就表示分发5条,表示该消费者类会一直堆着5条,当该消费者类处理了1条,只剩4条时,又会接收1条消息

参考代码

// 连接rabbitmq工具类
public class RabbitMqUtils {
//得到一个连接的 channel
public static Channel getChannel() throws Exception{
//创建一个连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("182.92.234.71"); // rabbitmq的ip和账户密码
factory.setUsername("admin");
factory.setPassword("123");
Connection connection = factory.newConnection(); // 创建连接
Channel channel = connection.createChannel();
return channel; // 返回信道
}
} // 生产者
public class Task02 {
private static final String TASK_QUEUE_NAME = "ack_queue"; // 创建队列
public static void main(String[] argv) throws Exception {
try (Channel channel = RabbitMqUtils.getChannel()){ // 获取连接rabbitmq
/**
* 生成一个队列
* 1.队列名称
* 2.队列持久化
* 3.该队列是否只供一个消费者进行消费 是否进行共享 true 可以多个消费者消费
* 4.是否自动删除 最后一个消费者端开连接以后 该队列是否自动删除 true 自动删除
* 5.其他参数
*/
channel.queueDeclare(TASK_QUEUE_NAME, false, false, false, null);
Scanner sc = new Scanner(System.in);
System.out.println("请输入信息");
while (sc.hasNext()) {
String message = sc.nextLine(); // 从控制台获取消息
/**
* 发送一个消息
* 1.发送到那个交换机
* 2.路由的 key 是哪个
* 3.消息持久化
* 4.发送消息的消息体
*/
channel.basicPublish("", TASK_QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8")); // 发送消息到rabbitmq
System.out.println("生产者发出消息" + message);
}
}
}
} // 消费者
public class Work03 {
private static final String ACK_QUEUE_NAME="ack_queue";
public static void main(String[] args) throws Exception{
Channel channel = RabbitMqUtils.getChannel();
System.out.println("C1 等待接收消息处理时间较短");
//消息消费的时候如何处理消息
DeliverCallback deliverCallback=(consumerTag,delivery)->{
String message= new String(delivery.getBody());
SleepUtils.sleep(1);
System.out.println("接收到消息:"+message);
/**
* 消息应答的具体处理:
* 1.消息标记 tag
* 2.是否批量应答未应答消息
*/
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
};
// 不公平分发
//channel.basicQos(1)
// 预取值
channel.basicQos(5)
//采用手动应答
boolean autoAck=false;
/**
* 1.队列名称
* 2.是否手动应答
* 3.接收成功的处理
* 4.接收消息失败的回调
*/
channel.basicConsume(ACK_QUEUE_NAME,autoAck,deliverCallback,(consumerTag)->{
System.out.println(consumerTag+"消费者取消消费接口回调逻辑");
});
}
} // 模拟处理时间的睡眠工具类
public class SleepUtils {
public static void sleep(int second){
try {
Thread.sleep(1000*second);
} catch (InterruptedException _ignored){
Thread.currentThread().interrupt();
}
}
}

RabbitMQ(一):入门的更多相关文章

  1. [转][RabbitMQ+Python入门经典] 兔子和兔子窝

    [转][RabbitMQ+Python入门经典] 兔子和兔子窝 http://blog.csdn.net/linvo/article/details/5750987 RabbitMQ作为一个工业级的消 ...

  2. RabbitMQ基础入门篇

    下载安装 Erlang RabbitMQ 启动RabbitMQ管理平台插件 DOS下进入到安装目录\sbin,执行以下命令 rabbitmq-plugins enable rabbitmq_manag ...

  3. RabbitMQ从入门到精通

    RabbitMQ从入门到精通 学习了:http://blog.csdn.net/column/details/rabbitmq.html RabbitMQ是AMQP(advanced message ...

  4. 中小研发团队架构实践之RabbitMQ快速入门及应用

    原文:中小研发团队架构实践之RabbitMQ快速入门及应用 使用过分布式中间件的人都知道,程序员使用起来并不复杂,常用的客户端API就那么几个,比我们日常编写程序时用到的API要少得多.但是分布式中间 ...

  5. RabbitMQ(一):RabbitMQ快速入门

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要对RabbitMQ有所了解,本文是RabbitMQ快速入门文章. RabbitMQ ...

  6. ASP.NET Core消息队列RabbitMQ基础入门实战演练

    一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...

  7. RabbitMQ由浅入深入门全总结(二)

    写在最前面 距离上一次发文章已经很久了,其实这段时间一直也没有停笔,只不过在忙着找工作还有学校结课的事情,重新弄了一下博客,后面也会陆陆续续会把文章最近更新出来~ 这篇文章有点长,就分了两篇 PS:那 ...

  8. RabbitMQ由浅入深入门全总结(一)

    写在最前面 距离上一次发文章已经很久了,其实这段时间一直也没有停笔,只不过在忙着找工作还有学校结课的事情,重新弄了一下博客,后面也会陆陆续续会把文章最近更新出来~ 这篇文章有点长,就分了两篇Q PS: ...

  9. [RabbitMQ+Python入门经典] 兔子和兔子窝

    原文联接: http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/ RabbitMQ作为一个工业级的消息队列服务器,在其客户端手册列表的P ...

  10. rabbitmq(1)-入门

    参考: documentation: https://www.rabbitmq.com/documentation.htmldemo: https://www.rabbitmq.com/getstar ...

随机推荐

  1. 手把手教你实现Android编译期注解

    一.编译期注解在开发中的重要性 从早期令人惊艳的ButterKnife,到后来的以ARouter为首的各种路由框架,再到现在谷歌大力推行的Jetpack组件,越来越多的第三方框架都在使用编译期注解这门 ...

  2. Linux CentOS 7 在Apache服务器上安装SSL证书

    在开发微信小程序的时候,wx.request请求的地址必须是https的,所以只能重新配置服务器. 域名和服务器都是在阿里云上买的,系统是CentOS7,安装了Apache服务器.网上也找了一下,很多 ...

  3. Webstorm 快速补全

    el-row>el-col*3>[:span='7'] 按Tab <el-row> <el-col> <div :span="">& ...

  4. phpMyAdmin 4.0.x—4.6.2 远程代码执行漏洞(CVE-2016-5734)

    影响范围 4.0.10.16之前4.0.x版本 4.4.15.7之前4.4.x版本 4.6.3之前4.6.x版本(实际上由于该版本要求PHP5.5+,所以无法复现本漏洞) 需要登录,且能够写入数据 p ...

  5. 零基础涂鸦智能面板SDK开发记录(一)

    前言 本人基础背景:在学校学了点JS,在blbl上看过几节node.js视频,现在是一名Android开发工程师,因公司需要学习涂鸦面板SDK开发.说真的除了官方的一些文档外,我真的找不到其他的资料. ...

  6. 从零开始学习JAVA(入门基础)

    目录 博主从零开始学习JAVA(入门基础) 1.搭建JAVA开发环境 卸载JDK(未安装的请忽略) 安装JDK 2.编程语言中,何为编译型与解释型 编译型 解释型 3.第一个JAVA应用程序 4.JA ...

  7. shell中cmd1 && cmd2 || cmd3的含义

    在某些情况下,很多指令我想要一次输入去执行,而不想要分次去执行时,就要用到 && || 了.cmd 1 && cmd21,若cmd1执行完毕之后且正确执行($?=0), ...

  8. CVE-2018-12613总结

    1.漏洞基础介绍 1.1漏洞背景 phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库.借由此We ...

  9. mapboxgl 互联网地图纠偏插件(三)

    先说结论,结论当然是:大功告成,喜大普奔.看效果图: 好了,接下来说一下过程 先回顾一下这个系列的第一篇和第二篇 第一篇是直接改的 mapboxgl 源码,在源码里面对瓦片的位置进行纠偏,遇到的问题是 ...

  10. JavaScript学习04(标准对象)

    标准对象 在JavaScript的世界里,一切都是对象. 但是某些对象还是和其他对象不太一样.为了区分对象的类型,我们用 typeof 操作符获取对象的类型,它总是返回一个字符串: typeof 12 ...