RabbitMQ学习

RabbitMQ学习

rabbitmq和kafka选择

1.吞吐量比较:kafka的吞吐量更大
2.可靠性比较:kafka存在丢数据的情况,适合做日志系统; rabbitmq更可靠,适合做数据系统和金融系统.
3.kafka使用分布式,rabbitmq比kafka更适合大文件

linux系统下安装rabbitmq

安装Erlang
rabbitmq是erlang语言编写的,需要先安装erlang环境,kafka是java开发的

 # 启动EPEL源
 $ sudo yum install epel-release 
 # 安装erlang
 $ sudo yum install erlang 

安装RabbitMQ

 # 下载rabbitmq安装包
 wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el7.noarch.rpm
 # 使用yum安装上面的安装包
 yum install rabbitmq-server-3.6.6-1.el7.noarch.rpm 

基本命令

命令作用
sudo chkconfig rabbitmq-server on添加开机启动RabbitMQ服务
sudo /sbin/service rabbitmq-server start启动服务
sudo /sbin/service rabbitmq-server status停止服务
sudo rabbitmqctl list_users查看所有用户
sudo rabbitmqctl list_user_permissions guest查看默认用户guest 的权限
sudo rabbitmqctl delete_user guest删除用户
sudo rabbitmqctl add_user username password添加用户
sudo rabbitmqctl set_user_tags username administrator添加用户tag
sudo rabbitmqctl set_permissions -p / username “." ".” “.*”添加所有权限
sudo rabbitmqctl list_user_permissions username查看用户权限
sudo rabbitmq-plugins enable rabbitmq_management安装web管理页面

web管理页面

//安装web管理插件
sudo rabbitmq-plugins enable rabbitmq_management 
//访问url,guest(密码默认也是guest)只能通过localhost访问;
//如果需要远程访问,需要删掉guest,创建新的用户
http://localhost:15672
普通项目java调用rabbitmq

创建生产者

 public static void main(String[] args) {
        ConnectionFactory connectionFactory= new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.25.23");
        //设置端口
        connectionFactory.setPort(5672);
        //设置密码用户名
        connectionFactory.setUsername("username");
        connectionFactory.setPassword("password");
        //设置虚拟机,每个虚拟机相当于一个小的mq
        connectionFactory.setVirtualHost("/");
        Connection connection =null;
        try {
            //建立连接
            connection = connectionFactory.newConnection();
            //建立通道,生产着和消费者都是在通道中完成
            Channel channel = connection.createChannel();
            channel.queueDeclare(Queue,true,false,false,null);
            String message="hello maxchen";
            channel.basicPublish("",Queue,null,message.getBytes());//注意:第一个参数不能为null
            System.out.println("send xiaoxi");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }

    }
//扩展
 /*
参数1,声明队列
参数2 是否持久化
参数3 是否排他,是否独战连接,队列只允许该链接中访问,如果连接关闭,队列也就删除了
参数4:是否自动删除,如果将此参数设置true,那么就变成零时队列
参数5 :扩展参数,例如存活时间
channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)*/
 //所有的队列需要制定默认的交换机
/* 
参数1: 交换机,如果使用默认交换机,那么就为空,不可以设置为null
参数二:路由key.交换机根据key来将消息发送到制定搞得队列,如果私用默认交互机,就应该设置为队列名称
channel.basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body)
throws IOException;
 */

创建消费者

 private  static  final  String Queue="world";
public static void main(String[] args) {
        ConnectionFactory connectionFactory= new ConnectionFactory();
        //设置连接地址
        connectionFactory.setHost("192.168.25.23");
        //设置端口
        connectionFactory.setPort(5672);
        //设置密码用户名
        connectionFactory.setUsername("username");
        connectionFactory.setPassword("password");
        //设置虚拟机,每个虚拟机相当于一个小的mq
        connectionFactory.setVirtualHost("/");
        Connection connection =null;
        try {
            //建立连接
            connection = connectionFactory.newConnection();
            //建立通道,生产着和消费者都是在通道中完成
            Channel channel = connection.createChannel();
            channel.queueDeclare(Queue,true,false,false,null);
/*
参数一:队列名称
参数二:自动回复
参数三 消费者方法
String basicConsume(String queue, boolean autoAck, Consumer callback)*/
            DefaultConsumer defaultConsumer=new DefaultConsumer(channel) {
                //当接受到消息时候,此方法被调用
                /**
                 * @Author cxy
                 * @Description //TODO
                 * @Date  2019/3/24
                 * @Param [consumerTag, envelope, properties, body]
                 * @return void
                 *
                 * consumerTag 用来标识.可以再监听队列时候设置
                 * envelope 信封,通过envelope可以通过这个获取到很多东西
                 * properties 额外的消息属性
                 * body:消息体
                 **/
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //获取交换机
                    String exchange = envelope.getExchange();
                    //消息id,用来表示那个消息消费了
                    long deliveryTag = envelope.getDeliveryTag();
                    String message=new String(body,"utf-8");
                    System.out.println("receive:"+message);
                }
            };
            channel.basicConsume(Queue,true ,defaultConsumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
springboot整合rabbitmq,并实现持久化
//配置文件
#rabbitmq
spring.rabbitmq.host=192.168.25.23
spring.rabbitmq.port=5672
#默认的v-host
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=username
spring.rabbitmq.password=password
#生产者手动确认
spring.rabbitmq.publisher-confirms=true
#生产者接受mq返回的信息
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.dynamic=true
#消费者持久化配置
spring.rabbitmq.cache.connection.mode=channel
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual

生产者

@Component
public class Producer implements RabbitTemplate.ReturnCallback,RabbitTemplate.ConfirmCallback{
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Scheduled(fixedDelay = 10000L)
    public void send() {
        this.rabbitTemplate.setReturnCallback(this);
        this.rabbitTemplate.setConfirmCallback(this);
        this.rabbitTemplate.setMandatory(true);
        CorrelationData correlationData = new CorrelationData("007");
        //exchange有4个类型:direct,topic,fanout,header,路由规则,routingkey需要完全相同才匹配
        //rabbitTemplate.convertAndSend("amq.direct","hello","kkk",correlationData);
        rabbitTemplate.convertAndSend("world","kkk");
    }

    @Override
    public void confirm(@Nullable CorrelationData correlationData, boolean ack, @Nullable String cause) {
        //如果消息没有到exchange,则confirm回调,ack=false
        //如果消息到达exchange,则confirm回调,ack=true;但是exchange到queue失败,ack还是true,要注意
        //System.out.println("correlationData:"+correlationData.getId());
        System.out.println("ack:"+ack);
        System.out.println("cause:"+cause);
        if (ack){
            System.out.println("成功");
        }else {
            System.out.println("失败");
        }
    }

    @Override
    public void returnedMessage(Message message, int replycode, String replytext, String exchange, String routingkey) {
        //exchange到queue成功,则不回调return
        //exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
        System.out.println("message:"+message);
        System.out.println("replycode:"+replycode);
        System.out.println("replytext:"+replytext);
        System.out.println("exchange:"+exchange);
        System.out.println("routingkey:"+routingkey);//路由
    }
}

消费者

import java.util.concurrent.TimeoutException;

@Component
public class RabbitConsumer {

    private  static  final  String Queue="world";


    @RabbitHandler
    //@RabbitListener(queues = "world")//简单配置,可以消费生产者创建的queue
    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(value = "direct.hlm2"),
                    exchange = @Exchange(value = "hlm2.direct", type = ExchangeTypes.DIRECT),
                    key = "hlm2.*"
            )//这样如果mq中不存在该queue,会为消费者创建一个新的queue
    )//FANOUT模式,符合amq.*格式的queue都可以消费消息,direct要rountingkey完全匹配才消费
    public void process(@Payload String foo) {
        System.out.println("消费消息:"+new Date() + ": " + foo);
    }
//持久化消费者
//消费者使用手动应答模式,如果没有应答,消息状态变成了unacked,断开消费者客户端链接后,消息重新变成ready;消息处于unacked的时候其他消费者是不能消费的
@RabbitListener(queues = "world")
    public void listerQueueR1(Channel channel, String message, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        System.out.println("here:"+message);
        /**参数一deliveryTag:该消息的index
   		参数二multiple:是否批量.true:将一次性ack所有小于deliveryTag的消息。*/
        channel.basicAck(tag,false);
    }
    }

配置config类

@Configuration
public class RabbitConfig {
    @Bean
    public Queue Queue() {
        //如果生产者和消费者都没有创建queue,生产者发送的消息会丢到黑洞,消费者会报错
        return new Queue("world");//创建queue,默认是持久化的,没有binding任何exchange和routingkey
    }
}

在这里插入图片描述
通过rabbitmq客户端查看到创建的queue参数druable为true
在这里插入图片描述
在这里插入图片描述
重启rabbitmq,会发现消息还存在mq中
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值