RabbitMQ简单介绍

RabbitMQ项目中的使用场景
1.系统间解耦
2.异步处理,提高性能
3.流量削峰
4.最终一致性问题
在我们的支付系统中,主要是起系统解耦的作用。
在通道计算平台中,起流量削峰作用。
RabbitMQ采用的理由
1.Exchange、Queue、Message都可以持久化,高可用性
2.RabbitMQ支持消息确认机制,能报保证消息可靠传输和可靠消费。
3.路由灵活
4.集群部署,保证可靠性
5.UI管理界面
6.erlang语言开发,高并发处理性能比较好
RabbitMQ简单实用
//连接方法
public void connect() {
    //1.实例化一个连接工厂(ConnectFactory)
    connectionFactory = new ConnectionFactory();
    //2.指定连接主机地址
    connectionFactory.setHost(RABBITMQ_URL);
    //3.指定端口
    connectionFactory.setPort(RABBITMQ_PORT);
    //4.用户名
    connectionFactory.setUsername(RABBITMQ_USERNAME);
    //5.密码
    connectionFactory.setPassword(RABBITMQ_PASSWORD);
    //6.指定虚拟主机(相当于命名空间,指定Exchange和Queue在哪个Virtual host中)
    connectionFactory.setVirtualHost(RABBITMQ_VirtualHost);
    //7.设置连接超时时间
    connectionFactory.setConnectionTimeout(30000);

    try {
        //8.通过connectionFactory新建一个连接
        connection = connectionFactory.newConnection();
        //9.为当前连接指定一个通道
        channel = connection.createChannel();
        /**
         *
         *  String exchange,    Exchange名称
         *  BuiltinExchangeType type,   exchange类型[DIRECT("direct"), FANOUT("fanout"), TOPIC("topic"), HEADERS("headers")]
         *  boolean durable,    是否持久化(高可用的保证,保证交换机持久化)
         *  boolean autoDelete, 是否自动删除,当它不被使用的Exchange服务器会自动删除
         *  boolean internal,   是否内部存在,如果为true那么这个Exchange不能直接给客户端使用
         *  Map<String, Object> arguments   额外参数
         */
        //10.声明一个Exchange,如果MQ服务器中没有则新建。
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true, false, false, null);
        /**
         *
         *  String queue,    Queue名称
         *  boolean durable, 是否持久化(高可用的保证,保证队列持久化)
         *  boolean exclusive,   是否时独占的,true为独占即为该连接中才可使用
         *  boolean autoDelete,  是否自动删除,当它不被使用的Queue服务器会自动删除
         *  Map<String, Object> arguments    额外参数
         */
         Map<String, Object> arguments = new HashedMap();
            //设置过期时间
            arguments.put("x-message-ttl", 60000);
            //设置队列长度
            arguments.put("x-max-length", 2);
            //设置死信队列
            arguments.put("x-dead-letter-exchange", "letter_dead_queue");
        //11.声明一个Queue,如果MQ服务器中没有则新建。
        channel.queueDeclare(QUEUE_NAME, true, false, false, arguments);
        /**
         *  String queue,   Queue名称
         *  String exchange,    Exchange名称
         *  String routingKey,  Queue与Exchange绑定Key
         *  Map<String, Object> arguments   额外参数,在spring与rabbitMQ整合的代码中,该参数为空
         *
         */
        //12.建立绑定关系
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTINGKEY, null);
    } catch (TimeoutException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


//关闭方法
public void close() {
    try {
        channel.close();
        connection.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
}


//producter发送消息
public void send(Object object) throws Exception {
    //序列化对象
    byte[] bytes = SerializeUtil.serialize(object);

    /***
     *
     *  Return机制:
     *      确保消息发送到Queue中,当发送失败,当前方法回调
     *  Confirm机制:
     *      需要在channel中开启 channel.confirmSelect()
     *      确保消息发送到Exchange中,当数据发送到Exchange,第一个参数会回调,发送失败第二个参数回调
     *
     */
    //13.开启Confirm机制
    channel.confirmSelect();
    try {
        channel.addReturnListener(returnMessage -> {
            System.out.println("Exchange:" + returnMessage.getExchange());
            System.out.println("RoutingKey:" + returnMessage.getRoutingKey());
            System.out.println("ReplyCode:" + returnMessage.getReplyCode());
            System.out.println("ReplyText:" + returnMessage.getReplyText());
            System.out.println("Body:" + SerializeUtil.unSerialize(returnMessage.getBody()).toString());
        });
        channel.addConfirmListener((deliveryTag, multiple) -> {
            System.out.println("deliveryTag1:" + deliveryTag);
            System.out.println("multiple1:" + multiple);
        }, (deliveryTag, multiple) -> {
            System.out.println("deliveryTag2:" + deliveryTag);
            System.out.println("multiple2:" + multiple);
        });
        //14.发送数据,第三个参数保证了Message的持久化
        channel.basicPublish(EXCHANGE_NAME, ROUTINGKEY, true, MessageProperties.PERSISTENT_TEXT_PLAIN, bytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
}


//consumer接收消息
public void receive() throws IOException {

    /**
     *
     * 消费者接收消息后需通过该方法回调进行消息处理
     *
     */
    DeliverCallback deliverCallback = (consumer, deliver) -> {
        System.out.println("consumer:" + consumer);
        //对象反序列化
        Object object = SerializeUtil.unSerialize(deliver.getBody());
        System.out.println("接收到的数据:" + object.toString());

        /**
         *
         * long deliveryTag,  消息投递唯一标识
         * boolean multiple
         *                 true:确认所有的消息包括已经接受的投递标识,
         *                 false:确认已经接受的投递标识
         */
        //消息确认被确认
        channel.basicAck(deliver.getEnvelope().getDeliveryTag(), true);

        /**
         * long deliveryTag,    消息投递唯一标识
         * boolean multiple,
         *                  true:拒绝所有的消息包括已经接受的投递标识,
         *              *   false:拒绝已经接受的投递标识
         * boolean requeue  是否重新放入队列
         *
         */
        //消息没有被确认
        channel.basicNack(deliver.getEnvelope().getDeliveryTag(), true, true);
    };

    /**
     * 设置通道的请求数,其实这里指的是在消费端消息最大的存储数(也就是没有被消费者确认消费的消息)
     */
    channel.basicQos(3);
    /**
     * String queue,    队列名称
     * boolean autoAck, 是否主动确认(不太建议,可能会造成消息丢失情况,当)
     * DeliverCallback deliverCallback, 消息被投递时的回调函数
     * CancelCallback cancelCallback    消费者被取消是的回调函数
     */
    //接受消息
    channel.basicConsume(QUEUE_NAME, false, deliverCallback, (CancelCallback) null);
}
死信队列(DLX dead-letter-exchange)
(1)消息被拒绝并且没有重新放到队列中
(2)消息超时(通过Arguments对象设置x-message-ttl Time To Live简称TTL)
(3)超过队列长度限制的消息

通过这种特性可以做延时队列。
集群方式
主从集群
    一般一台主要的,两台次要服务器。主服务器上,存储元数据以及消息,从服务器上存储元数据。当客户端连接到从服务器上时,从服务器会跟主服务器获取消息,然后再给消费者。确定时,一旦主服务器宕机,消息存在丢失情况。
镜像集群
    我们公司采用HaProxy作为集群负载,使用了KeepAlived工具将两台HaProxy服务器做热备组,通过镜像队列模式设置集群,每个节点上都存在队列服务,一个节点宕机故障失效转移,从而避免了单点问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值