RabbitMQ安装配置
环境说明:Centos7
由于 RabbitMQ 使用通过 Erlang 来开发的,因此需要提前安装Erlang。Erlang 和 RabbitMQ 的对应关系:官网。一定要注意版本配合否则有误。
安装Erlang
yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
wget https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
yum -y install epel-release
sudo yum install erlang
检验
yum info erlang
安装RabbitMQ
官方下载地址:https://www.rabbitmq.com/install-rpm.html#downloads
下载
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.4/rabbitmq-server-3.8.4-1.el7.noarch.rpm
安装
yum -y install socat
rpm -ivh rabbitmq-server-3.8.4-1.el7.noarch.rpm
开机启动及启动
chkconfig rabbitmq-server on
systemctl start rabbitmq-server
检查
rabbitmqctl status
添加用户
默认的是guest用户,还是习惯自己进行添加用户并且赋予权限。
查看用户
rabbitmqctl list_users
添加用户 admin是用户名,123456是密码,任意设置。
rabbitmqctl add_user admin123456
配置权限,这里给了全部的权限
rabbitmqctl set_permissions -p "/" charmsongo ".*" ".*" ".*"
设置 tag 为 administrator
rabbitmqctl set_user_tags charmsongo administrator
补充说明
- 服务器用户记得要在安全组里面开启5672/15672两个端口
- 同时要对防火墙设置,允许这两个端口访问
最后可以在浏览器中访问:serviceip:15672,就可以看到rabbitmq的管理界面了。
RabbitMQ 结构模型
-
ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用;
-
Channel(信道):消息推送使用的通道;
-
Exchange(交换器):用于接受、分配消息;
-
Queue(队列):用于存储生产者的消息;
-
RoutingKey(路由键):用于把生成者的数据分配到交换器上;
-
BindingKey(绑定键):用于把交换器的消息绑定到队列上;
看到上面的解释,最难理解的路由键和绑定键了,那么他们具体怎么发挥作用的,请看下图:
Exchange四种
- direct exchange
根据消息的 route key 来将消息分发到相对应的queue 中 - fanout exchange
将消息分发给所有绑定到此 exchange 的 queue 中 - topic exchange
根据 route key 将消息分发到与此消息的 route key 相匹配的并且绑定到此 exchagne 中的 queue 中 - header exchange
不使用 route key 作为路由的依据, 而是使用消息头属性来路由消息.
SpringBoot整合
导入依赖
<!--RabblitMq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
系统配置
根据自己的实际情况进行相关设置。
#rabbitmq
spring:
rabbitmq:
host: ***
port: 5672
username: ***
password: ***
virtual-host: /
#连接超时,单位毫秒,0表示无穷大,不超时
connection-timeout: 5000
template:
retry:
#发送重试是否可用
enabled: false
receive-timeout: 30000
reply-timeout: 30000
发送者
/**
* 发送秒杀信息,使用derict模式的交换机。(包含秒杀用户信息,秒杀商品id)
*/
public void sendSeckillMessage(SeckillMessage mmessage) {
// 将对象转换为字符串
String msg = RedisService.beanToString(mmessage);
log.info("send message:" + msg);
// 第一个参数队列的名字,第二个参数发出的信息
amqpTemplate.convertAndSend(MQConfig.SECKILL_QUEUE, msg);
}
接收者
注意这个注解@RabbitListener
,他就指明了是在监听哪个Queue
在这个类里面我们进行了最终的秒杀业务。
//秒杀的业务实际上都是在这里完成的
@RabbitListener(queues=MQConfig.SECKILL_QUEUE)//指明监听的是哪一个queue
public void receiveSeckillMessage(String message) {
log.info("receiveMiaosha message:"+message);
//通过string类型的message还原成bean
//拿到了秒杀信息之后。开始业务逻辑秒杀,
SeckillMessage mm=RedisService.stringToBean(message, SeckillMessage.class);
SkUser user=mm.getUser();
long goodsId=mm.getGoodsId();
SkGoods skGoods= skGoodsService.getGoodsByGoodsId(goodsId);
//注意此时查的是数据库
int stockcount=skGoods.getStockCount();
//1.判断库存不足
if(stockcount<=0) {//失败
//model.addAttribute("errorMessage", CodeMsg.MIAOSHA_OVER_ERROR);
return;
}
//2.判断这个秒杀订单形成没有,判断是否已经秒杀到了,避免一个账户秒杀多个商品
SkOrder order = skOrderService.queryOrderByUserIdAndGoodsId(user.getId(), goodsId);
if (order != null) {// 重复下单
// model.addAttribute("errorMessage", CodeMsg.REPEATE_MIAOSHA);
return;
}
//原子操作:1.库存减1,2.下订单,3.写入秒杀订单--->是一个事务
//miaoshaService.miaosha(user,goodsvo);
secKillService.seckill(user,skGoods);
}