随笔- 23  文章- 0  评论- 0  阅读- 1896 

RabbitMQ基本命令

ubuntu、基于Debian的【deb】的系统

sudo service rabbitmq-server start
sudo service rabbitmq-server stop
sudo service rabbitmq-server restart
sudo service rabbitmq-server status

CentOS、基于rpm的系统

systemctl start rabbitmq-server
systemctl stop rabbitmq-server 
systemctl restart rabbitmq-server
systemctl status rabbitmq-server    

插件管理

sudo rabbitmq-plugins enable rabbitmq_management #启用某个插件
sudo rabbitmq-plugins list #显示所有插件名

应用

流量削峰、降低耦合

整合Spring

连接
public class FactoryRabbit {

    public ConnectionFactory getFactory(){
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setPort(5672);
        connectionFactory.setHost("222.201.144.247");
        connectionFactory.setUsername("lian");
        connectionFactory.setPassword("lian");
        connectionFactory.setVirtualHost("/virtual");
        return connectionFactory;
    }
}
发布消息
public class RabbitMQTest {

    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        
        channel.queueDeclare("hello",false,false,false,null);

       channel.basicPublish("","hello",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello:lian".getBytes());

        channel.close();
        connection.close();
    }
}
消费消息
public class Customer {
    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        
        Channel.basicQos(1);//每一次只能消费一个消息
        
        channel.queueDeclare("hello",false,false,false,null);
		
        //关闭自动确认机制
        channel.basicConsume("hello",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("msg: "+ new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}

消息确认机制:

工作队列中的每条消息只要有一个worker处理即可

当开启自动确认机制时,消费者接受到消息则会自动返回确认,而不管剩下的业务逻辑是否顺利执行。在自动确认机制开启的情况下,在工作队列中每个消费者往往是循环的接收到队列中的消息。所以需要关闭消息自动确认

        channel.basicConsume("hello",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("msg: "+ new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });

优点:保证能者多劳,消息不会丢失

发布和订阅模式:广播

需要用到交换机:队列中的每条消息都发送给所有worker:

其中发送者只需要把消息给交换机即可

public class FanOut {
    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("exchange","fanout");

        channel.basicPublish("exchange","",null,"fan out".getBytes());

        channel.close();
        connection.close();

    }
}

而接收者需要定义临时队列并通过队列接受消息

public class FanCustomer {
    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        //在channel对象里添加一个交换机
        channel.exchangeDeclare("exchange","fanout");

        //在channel对象里添加一个临时队列:queueDeclare(),并返回队列名
        String queue = channel.queueDeclare().getQueue();

        //绑定指定的交换机和队列,一个channel对象里有多个交换机和队列
        channel.queueBind(queue,"exchange","");

        //在channel中指定的队列中消费对象,设置自动确认,否则应当手动确认
        channel.basicConsume(queue,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(new String(body));
            }
        });
    }
}

路由模式:

交换机通过消息中不同的key值转发到不同的消息队列中:指定交换机类型type=direct

发布消息部分:

public class Route {
    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("direct_exchange","direct");
        String key = "info";
        channel.basicPublish("direct_exchange",key,null,"msg:key is info".getBytes());
        channel.close();
        connection.close();
    }
}

接收消息部分

public class RouteCustomer {
    public static void main(String[] args) throws IOException, TimeoutException {
        FactoryRabbit factoryRabbit = new FactoryRabbit();
        ConnectionFactory factory = factoryRabbit.getFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("direct_exchange","direct");
        String queue = channel.queueDeclare().getQueue();
        String key = "info";
        
        //当使用动态路由时,用统配符代替下面的key即可,*匹配一个,而#匹配多个
        channel.queueBind(queue,"direct_exchange",key);

        channel.basicConsume(queue,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(new String(body));
            }
        });
    }
}

整合SpringBoot

依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

application.properties,用RabbitTemplate直接注入然后操作即可

spring.rabbitmq.host=222.201.144.247
spring.rabbitmq.port=5672
spring.rabbitmq.username=lian
spring.rabbitmq.password=lian
#虚拟主机名
spring.rabbitmq.virtual-host=/virtual
注解开发
@Component
@RabbitListener(queuesToDeclare = @Queue(value = "boot",durable = "false"))
public class HalloCustomer {

    @RabbitHandler
    public void receive(String message) {
        System.out.println("message:"+ message);
    }
}
class MqApplicationTests {
    @Autowired
    public RabbitTemplate rabbitTemplate;
    @Test
    void test() {
        rabbitTemplate.convertAndSend("boot","hello spring");
    }
}

基于SpringBoot的多种模式

工作队列:循环分配
@Component
public class Work {

    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive1(String msg){
        System.out.println("message1:"+msg);
    }

    @RabbitListener(queuesToDeclare = @Queue("work"))//监听的队列名称是work
    public void receive2(String msg){
        System.out.println("message2:"+msg);
    }
}
发布订阅:广播
@Test
void fanOut(){
    rabbitTemplate.convertAndSend("logs","","fanout:msg");
}
@Component
public class FanOut {

    @RabbitListener(bindings = {@QueueBinding(
            value = @Queue,
            exchange = @Exchange(value = "logs",type = "fanout")
    )})
    public void receive(String msg){
        System.out.println("receive1:"+ msg);
    }

    @RabbitListener(bindings = {@QueueBinding(
            value = @Queue,
            exchange = @Exchange(value = "logs",type = "fanout")
    )})
    public void receive2(String msg){
        System.out.println("receive2:"+ msg);
    }

}
路由模式:
@Test
void route(){
    rabbitTemplate.convertAndSend("directs","info","route:msg");
}
@Component
public class Route {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "directs",type = "direct"),
                    key = {"info","error"}
            )
    })
    public void receive(String msg){
        System.out.println("receive1"+msg);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "directs",type = "direct"),
                    key = {"debug"}
            )
    })
    public void receive2(String msg){
        System.out.println("receive2  "+msg);
    }
}
动态路由
@Test
void topic(){
    rabbitTemplate.convertAndSend("topics","info.hello","topic:msg");
}
@Component
public class Topic {

    @RabbitListener(bindings = {@QueueBinding(
            value = @Queue,
            exchange = @Exchange(type="topic",name = "topics"),
            key = {"info.#"}
    )
    })
    public void receive(String msg){
        System.out.println("receive: "+msg);
    }
}

RabbitMQ镜像集群

主备集群只是同步交换机信息,对除了消息队列外的信息做一个备份而已。其他节点能够通过主节点看到队列,但实际上并没有消息队列的实际信息

ubuntu搭建好的rabbitmq默认是没有配置文件的,需要我们来手动添加;Rabbitmq的一些运行脚本存放在 /usr/sbin 下面;通过rabbitmqctl cluster_status命令,可以查看和个节点的状态。

创建步骤1:

vim /etc/rabbitmq/rabbitmq.config

 [{rabbit, [{loopback_users, []}]}].

拷贝/var/lib/rabbitmq/ .erlang.cookie,因为是隐藏的直接ls看不到

步骤2:

要将一个节点加入到现有的集群中,你需要停止这个应用并将节点设置为原始状态,然后就为加入集群准备好了。使用rabbitmqctl stop_app仅仅关闭应用

./rabbitmqctl stop_app 

./rabbitmqctl join_cluster rabbit@host

./rabbitmqctl start_app

./rabbitmqctl cluster_status

步骤3:

设置镜像集趣

#set_policy [-p vhostpath] {name} {pattern} {definition} [priority]

./rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}

Setting policy "ha-all" for pattern "^" to "{\"ha-mode\":\"all\"}" with priority "0"

./rabbitmqctl list_policies#显示当前正在使用的策略

消息队列的作用

解耦合:在某个场景下需要向不同的系统发送消息,为了避免为每一个系统维护一个接口,并方面后续的扩展,使用消息队列达到解耦合的目的

异步操作:某个系统接收到用户请求,不仅需要调用本地服务,还要调用其他服务,有时可以不用等待后续服务的调用结果,将调用申请缓冲到消息队列中,直接向用户返回结果,避免了长时间的等待。

 posted on   春秋流千事  阅读(161)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示