RabbitMQ(一):入门
前言
- 最近学习了尚硅谷-RabbitMQ
- 受益匪浅,根据自己的理解做了下笔记,不正确的地方欢迎指正
正文
RabbitMQ是一个消息中间件,相当于一个中转站;用于接收、存储、转发消息数据
RabbitMQ的作用:
- 流量消峰:当服务器处理不了过多的请求时,在进入服务器之前先进入MQ,MQ会对请求做排序,防止服务器宕机
- 应用解耦:当系统的某个子系统出现故障无法正常工作时,该子系统要处理的内存会被缓存到消息队列中,当该子系统正常后再继续处理;提高用户体验,避免用户再次请求
- 异步处理:有些服务间的调用是异步的,当某个服务在工作时,其他服务不能调用该服务,可使用消息队列来进行监听管理调用
MQ的核心:
- 生产者:产生数据发送消息的模块
- 交换机:用于接收生产者的消息、将消息推送到队列中、处理消息
- 队列:相当于消息缓存区
- 消费者:用于接收消息的模块
- 一个应用程序既可以是生产者,又可以是消费者;比如一个通讯工具,既可以发送信息,也可以接收信息
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
消息传递入门案例:
- 导入所需依赖,新建一个类作为消息生产者,定义一个队列,创建连接工厂,创建连接,生成队列,发送消息
- 运行后发现massage发送到了rabbitmq,可在rabbitmq中查看
- 新建一个类作为消息消费者,创建连接工厂,创建连接,接收rabbitmq中的消息,可指定回调方法用于处理成功和失败的情况
工作队列是为了避免立即执行大量任务,生产者发送大量消息到rabbitmq的队列,队列将消息缓存、排序、分发到不同的消费者
轮训分发消息案例:
- 抽取连接的步骤抽取到一个工具类,新建生产者类和消费者类,消费者类启动多个线程
- 当生产者发送消息时,消息被多个线程(消费者类)平均接收
消息应答:消费者接收消息并处理完成后,会告诉rabbitmq,这时rabbitmq会把消息删除了
自动应答:建议不要使用,若消费者不能即使处理消息,会导致消息丢失
手动应答:自定义应答方法
Channel.basicAck:用于肯定确认,RabbitMQ 已知道该消息并且成功的处理消息,可以将其丢弃了
Channel.basicNack:用于否定确认
Channel.basicReject:用于否定确认,与 Channel.basicNack 相比少一个参数Multiple
Multiple为true表示批量应答,即消费者同时处理多个消息,其中一个消息处理完成后,则告诉rabbitmq全处理完了
Multiple为false表示不批量应答,即消费者同时处理多个消息,其中一个消息处理完成后,则告诉rabbitmq处理完的那个消息
消息自动重新入队,消息会保存在rabbitmq中,直到被消费者处理后、应答后才会删除,当消费者出现异常或者宕机时导致处理失败,rabbitmq会将消息分发给另一个消费者处理
手动应答 + 自动重新入队案例:
- 新建一个类作为消息生产者
- 新建一个类作为消息消费者:让该线程睡眠1秒后打印出接收到消息,再新建一个消息消费者类:让该线程睡眠30秒后打印出接收的消息,是为了模拟处理复杂的消息;在两个消费者类中设置为手动应答
- 测试:生产者发送消息,两个消费者轮训接收消息,当第二个消费者在接收消息时突然关闭服务,这时消息没处理完,又被自动分配到第一个消费者处理
队列持久化:
在生产者类中设置
消息应答机制确保了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(一):入门的更多相关文章
- [转][RabbitMQ+Python入门经典] 兔子和兔子窝
[转][RabbitMQ+Python入门经典] 兔子和兔子窝 http://blog.csdn.net/linvo/article/details/5750987 RabbitMQ作为一个工业级的消 ...
- RabbitMQ基础入门篇
下载安装 Erlang RabbitMQ 启动RabbitMQ管理平台插件 DOS下进入到安装目录\sbin,执行以下命令 rabbitmq-plugins enable rabbitmq_manag ...
- RabbitMQ从入门到精通
RabbitMQ从入门到精通 学习了:http://blog.csdn.net/column/details/rabbitmq.html RabbitMQ是AMQP(advanced message ...
- 中小研发团队架构实践之RabbitMQ快速入门及应用
原文:中小研发团队架构实践之RabbitMQ快速入门及应用 使用过分布式中间件的人都知道,程序员使用起来并不复杂,常用的客户端API就那么几个,比我们日常编写程序时用到的API要少得多.但是分布式中间 ...
- RabbitMQ(一):RabbitMQ快速入门
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要对RabbitMQ有所了解,本文是RabbitMQ快速入门文章. RabbitMQ ...
- ASP.NET Core消息队列RabbitMQ基础入门实战演练
一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...
- RabbitMQ由浅入深入门全总结(二)
写在最前面 距离上一次发文章已经很久了,其实这段时间一直也没有停笔,只不过在忙着找工作还有学校结课的事情,重新弄了一下博客,后面也会陆陆续续会把文章最近更新出来~ 这篇文章有点长,就分了两篇 PS:那 ...
- RabbitMQ由浅入深入门全总结(一)
写在最前面 距离上一次发文章已经很久了,其实这段时间一直也没有停笔,只不过在忙着找工作还有学校结课的事情,重新弄了一下博客,后面也会陆陆续续会把文章最近更新出来~ 这篇文章有点长,就分了两篇Q PS: ...
- [RabbitMQ+Python入门经典] 兔子和兔子窝
原文联接: http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/ RabbitMQ作为一个工业级的消息队列服务器,在其客户端手册列表的P ...
- rabbitmq(1)-入门
参考: documentation: https://www.rabbitmq.com/documentation.htmldemo: https://www.rabbitmq.com/getstar ...
随机推荐
- 每天五分钟Go - Map
map的定义 var m map[type]type fmt.Println(m) 此种方法定义的m为nil //打印的结果为: map[] map的创建 1.使用make创建 var m1 = ma ...
- windows下python -m pip install --upgrade pip升级后报错的解决方法
前言: 笔者装某库的时候提示需要升级pip版本,就python -m pip install --upgrade pip默认升级了,结果升级之后只要输入pip就有报错(如下图),网上百度了很多解决方法 ...
- Java8 Lambda表达式(一)
目录 一.应用场景引入 优化一:使用策略模式 优化二:使用匿名内部类 优化三:使用Lambda表达式 优化四:使用Stream API 二.Lambda运算符和对应语法 语法格式 Lambda表达式需 ...
- TypeScript学习笔记(一)环境搭建和数据类型
目录 一.学习TypeScript的缘由 二.学习环境的搭建 1. TypeScript的编译环境 2. vscode自动编译的配置 三.TypeScript中的数据类型 1. 简单变量的定义和初始化 ...
- 算法竞赛中的常用JAVA API :HashMap 和 TreeMap(转载)
算法竞赛中的常用JAVA API :HashMap 和 TreeMap 摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实 ...
- VScode安装配置
一.安装VScode 进入VScode官网Visual Studio Code下载 安装 二.设置中文 打开vscode 重启vscode 三.美化 四.安装拓展插件 Auto Close Tag ( ...
- elsa-core—2.Hello World: HTTP
在本快速入门中,我们将了解一个执行工作流的最小 ASP.NET Core 应用程序.工作流将侦听传入的 HTTP 请求并写回一个简单的响应. 我们将: 创建 ASP.NET Core 应用程序. 使用 ...
- MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用
转载自 MyBatis-Plus QueryWrapper及LambdaQueryWrapper的使用 LambdaQueryWrapper https://blog.csdn.net/lt32603 ...
- ECDSA—模加减模块
如果a,b GF(P),则加法运算a+b=r (mod p),其中r满足0<r<p-1,即a+b除以p的余数,该操作成为模p加法.对于模减运算可以视为另类的模加运算,即a+(-b)=k ( ...
- Spring全家桶--单数据源的配置
前言 spring数据源的配置网络上有很多例子,这里我也来介绍一下单数据源配置的例子,基于SpringBoot的方式和原生的Spring的方式. 一.生成项目骨架(SpringBoot),运行一个简单 ...