RabbitMQ

RabbitMQ

先来看一张流程图:

         e91a33f66e9a662619ade41d516adb7342d.jpg

说明:消息生产者将消息发送到对应的Exchange中,exchange根据消息路由规则将消息发送到指定的message queue中,然后发给消息消费者。

linux环境安装: yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz

安装:erlang语言环境    www.rabbitmq.com/releases/erlang/erlang-18.3-1.el7.centos.x86_64.rpm

          密钥安装:http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm

          rabbbitMQ安装:https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm

           rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm
           rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm
           rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

安装完之后 配置文件在 /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin  修改里面的   {loopback_users, [guest]}  即可。

启动应用:rabbitmqctl start_app    节点状态:rabbitmqctl status   添加用户:rabbitmqctl add_user username password  用户列表:rabbitmqctl list_user   删除用户:rabbitmqctl delete_user username
关闭应用:rabbitmqctl stop_app    清除用户权限:rabbitmqctl clear_permissions -p vhostpath username   修改密码:rabbitmqctl change_password  username newPassword
创建虚拟主机:rabbitmqctl add_vhost vhostpath   虚拟主机列表:rabbitmq  list_vhosts     虚拟主机权限列表:rabbimqctl list_permissions -p vhostpath    删除:rabbbtmqctl delete_vhost vhostpath 
队列列表:rabbitmqctl list_queues    清除队列消息:tabbitmqctl -p vhostpath purge_queue blue

启动时遇到问题时重启下服务器就好了  # service rabbitmq-server stop
                                                    # service rabbitmq-server start

第一次访问官方提供的web管理界面需要执行以下命令:rabbitmq-plugins enable rabbitmq_management
                                                                   开放端口:iptables -I INPUT -p tcp --dport 15672 -j ACCEPT

rabbitmq官方申明:创建新的用户和guest用户都没有远程访问权限,如果我们自己创建新用户,需要设置权限。步骤如下:

创建用户密码:rabbitmqctl add_user mq 123456
赋予用户管理者:rabbitmqctl set_user_tags mq administrator

设置用户管理权限:rabbitmqctl set_permissions -p "/" mq ".*" ".*" ".*"

Exchange

交换机模式:direct exchange:所有发送的direct exchange将会把消息发送到routekey指定的queue中。注意:direct模式时rabbitmq自动的exchange:default exchange,所以不需要将exchange进行banding操作,消息传递时,routekey完全被queuename完全匹配才会被接收,否则被遗弃。

topic exchange:所有发送到topic exchange的消息被转发到所关心Routekey中指定的topic 的queue中。exchange将routekey和某个topic进行模糊匹配,此时队列需要绑定一个topic。

fanout exchange:不处理路由键,只需要简单的将队列绑定到交换机上,发送到交换机的消息都会被转发到与该交换机绑定的所有队列上,fanout交换机转发消息是最快的。

在producer端进行设置

channel.confirmSelect();//启动发行者通道确认
channel.addConfirmListener(new ConfirmListener() {
    @Override
    public void handleAck(long deliveryTag, boolean multiple) throws IOException { //只要将消息发送到Exchange上就会回调确认ack,即使路由失败也能回调
        System.out.println(deliveryTag);
        System.out.println(multiple);
        System.out.println("action is success");
    }

    @Override
    public void handleNack(long deliveryTag, boolean multiple) throws IOException {//消息丢失才会回调此方法,发送到错误的exchange上不会回调
        System.out.println(deliveryTag);
        System.out.println(multiple);
        System.out.println("action is failed");
    }
});
channel.addReturnListener(( replyCode,  replyText,  exchange,  routingKey,  //消息路由失败才会回调此方法,发送到错误的exchange上不会回调
        properties, body)->{
        System.out.println(replyCode);
        System.out.println(replyText);
        System.out.println(exchange);
        System.out.println(routingKey);
        System.out.println(properties);
        System.out.println(body);
});

自定义一个consumer

自定义的consumer需要implement接口Consumer,方便的话可以实现继承DefaultConsumer类,只需重写handleDelivery方法即可。每当有效消息路由到queue转到consumer上时,都会执行handleDelivery方法,相应得message都在handleDelivery方法的参数中。

消费端限流

当rabbitMq上有成千上万的消息堆积未处理时,此时打开客户端(消费端)进行消息推送,会造成消费端拥堵甚至崩溃,此时就需要做一个限流处理。
RabbtMQ提供一种qos功能,即在非自动确认消息的前提下,如果一定数目的消息(通过基于consume或者channel设置Qos的值)未被确认前,不进行消费新的消息。
在消费端设置:channel.basicQos(3,false); 设置一次接受3个消息,并且设置false意思是在consumer上进行限制,ture是在channel上进行设置。
                       channel.basicConsume(queueName,false,myConsumer);channel绑定consumer时设置autoack为false,也就是第二个参数。
  在自定义的consumer类方法handleDelivery中进行手动ack:channel.basicAck(envelope.getDeliveryTag(),true);如果不行进行手动ack,rabbitmq就不会再往consumer发送消息,必须等到ack确认才会继续发送(重新开始发送,不是接着上次发送),这样就实现了消息的限流。

RabbitMQ整合Spring AMQP实战

导入jar包:

compile 'com.rabbitmq:amqp-client'
compile 'org.springframework.boot:spring-boot-starter-amqp'

定义rabbitAdmin:

@Bean
public ConnectionFactory getConnectionFactory(){
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
    cachingConnectionFactory.setHost("192.168.11.10");
    cachingConnectionFactory.setPort(5672);
    cachingConnectionFactory.setVirtualHost("/");
    cachingConnectionFactory.setUsername("name");
    cachingConnectionFactory.setPassword("123456");
    cachingConnectionFactory.setConnectionTimeout(3000);
    return cachingConnectionFactory;
}

@Bean
public RabbitAdmin rabbitadmin(ConnectionFactory getConnectionFactory){
     RabbitAdmin rabbitAdmin = new RabbitAdmin(getConnectionFactory);
     rabbitAdmin.setAutoStartup(false);
     return rabbitAdmin;
}

   这样就可以在java代码中随时随地运用exchange  ,queue, 例如:

rabbitAdmin.declareExchange(new DirectExchange("test.config.direct.exchange",false,false));//申明一个direct路由
rabbitAdmin.declareExchange(new TopicExchange("test.config.topic.exchange",false,false));//申明一个topic路由
rabbitAdmin.declareExchange(new FanoutExchange("test.config.fanout.exchange",false,false));//申明一个fanout路由
rabbitAdmin.declareQueue(new Queue("derect.queue",false)); //申明一个queue
rabbitAdmin.declareQueue(new Queue("topic.queue",false)); //申明一个queue
rabbitAdmin.declareQueue(new Queue("fanout.queue",false)); //申明一个queue
rabbitAdmin.declareBinding(new Binding("derect.queue",Binding.DestinationType.QUEUE,
        "test.config.direct.exchange","direct",new HashMap<>()));   //绑定direct
rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("topic.queue",false))
.to(new TopicExchange("test.config.topic.exchange",false,false))   //绑定topic另一个方式
.with("topic.#"))
rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue("fanout.queue",false))
        .to(new FanoutExchange("test.config.fanout.exchange",false,false)));//绑定fanout另一个方式

还可以直接申明出来exchang  queue  binding ,都交给spring管理,例如:

/**
 * 申明一个direct exchange
 */
@Bean
public DirectExchange directExchange(){
    return new DirectExchange("direct.exchange.001",false,false);
}
/**
 * 申明一个queue
 */
@Bean
public Queue queue(){
    return new Queue("direct.queue.001",false,false,false);
}
/**
 * 申明一个绑定
 */
public Binding bingding(Queue queue,DirectExchange directExchange){
    return BindingBuilder.bind(queue).to(directExchange).with("spring.#");
}

申明一个rabbitTemplate交给spring管理,他可以帮我们发送消息到exchange上。

rabbitTemplate.convertAndSend(exchangename,routekeying,"我是大大大大001");

总结

rabbitmq无论从性能,高可用,视图控制,spring融合都有不错的效果,我这边只是简单的做个介绍,想要深入了解的小伙伴还需要更系统的学习。

转载于:https://my.oschina.net/yaojianpeng/blog/3063978

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值