【图解RabbitMQ-7】图解RabbitMQ五种队列模型(简单模型、工作模型、发布订阅模型、路由模型、主题模型)及代码实现

news2024/11/23 11:24:57

🧑‍💻作者名称:DaenCode
🎤作者简介:CSDN实力新星,后端开发两年经验,曾担任甲方技术代表,业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开发。技术尚浅,闭关学习中······
😎人生感悟:尝尽人生百味,方知世间冷暖。
📖所属专栏:图解RabbitMQ


在这里插入图片描述


专栏推荐

  • 专门为Redis入门打造的专栏,包含Redis基础知识、基础命令、五大数据类型实战场景、key删除策略、内存淘汰机制、持久化机制、哨兵模式、主从复制、分布式锁等等内容。链接>>>>>>>>>《Redis从头学》
  • SpringBoot实战相关专栏,包含SpringBoot过滤器、拦截器、AOP实现日志、整合Freemaker、整合Redis等等实战相关内容,多篇文章登入全站热榜、领域热榜、被技术社区收录。链接>>>>>>《SpringBoot实战》

文章目录

  • 专栏推荐
  • 🌟前言
  • 🌟连接工具类
  • 🌟简单工作模型
    • 介绍
    • 代码实现
  • 🌟工作队列模型
    • 介绍
    • 代码实现
  • 🌟发布订阅模型
    • 介绍
    • 代码实现
  • 🌟路由模型
    • 介绍
    • 代码实现
  • 🌟主题模型
    • 介绍
    • 代码实现
  • 🌟总结
  • 🌟写在最后

参考网站:https://www.rabbitmq.com/getstarted.html

🌟前言

在上一节学习了RabbitMQ中交换机的相关基础知识,本文来学习一下RabbitMQ中的五种队列模型的,对其有一个基本的认识。

🌟连接工具类

public class MQConnectionUtil {
    public static Connection createConnection() throws IOException, TimeoutException {
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.124.23");
        factory.setUsername("admin");
        factory.setPassword("password");
        factory.setVirtualHost("/dev");
        factory.setPort(5672);
        return factory.newConnection();
    }
}

🌟简单工作模型

介绍

模型图
在这里插入图片描述
流程

  1. 生产者发送消息到队列。
  2. 如果队列存在则直接存入消息;若不存在,先进行队列的创建。
  3. 消费者监听队列。
  4. 处理完消息,通过ACK机制确认消息已经消费。

特点

  1. 只有一个消费者,并且其中没有交换机参与。

代码实现

生产者

public class Send {
    private final static String QUEUE_NAME="hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
                Connection connection=MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
            /**
             * 队列名称
             * 持久化配置:mq重启后还在
             * 是否独占:只能有一个消费者监听队列;当connection关闭是否删除队列,一般是false,发布订阅是独占
             * 自动删除: 当没有消费者的时候,自动删除掉,一般是false
             * 其他参数
             *
             * 队列不存在则会自动创建,如果存在则不会覆盖,所以此时的时候需要注意属性
             */
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            String message = "Hello World!";
            /**
             * 参数说明:
             * 交换机名称:不写则是默认的交换机,那路由健需要和队列名称一样才可以被路由,
             * 路由健名称
             * 配置信息
             * 发送的消息数据:字节数组
             */
            //发布消息
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}

消费者

public class Recv {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        //消费者一般不增加自动关闭
        Connection connection=MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //回调方法,下面两种都行
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
                System.out.println("consumerTag消息标识="+consumerTag);
                //可以获取交换机,路由健等
                System.out.println("envelope元数据="+envelope);

                System.out.println("properties配置信息="+properties);

                System.out.println("body="+new String(body,"utf-8"));
            }
        };
        channel.basicConsume(QUEUE_NAME,true,consumer);

//        DeliverCallback deliverCallback = (consumerTag,delivery) -> {
//            String message = new String(delivery.getBody(), "UTF-8");
//            System.out.println(" [x] Received '" + message + "'");
//        };

        //自动确认消息
//        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}

🌟工作队列模型

介绍

模型图
在这里插入图片描述
特点

  1. 生产者将消息发送到队列,并由多个消费者进行消费。

两种消费策略
1 . 轮训策略:将消息平均分配给多个消费者进行消费,不考虑消费者的处理能力;采用自动ACK消息机制。
2. 公平策略:消费者每次只能处理一个消息。一定时间内,能力强者消费的多,否则少;采用手动ACK消息机制。


代码实现

轮询策略

//生产者
public class Send {
    private final static String QUEUE_NAME="work_rr";

    public static void main(String[] args) throws IOException, TimeoutException {
        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
               Connection connection= MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
            /**
             * 队列名称
             * 持久化配置:mq重启后还在
             * 是否独占:只能有一个消费者监听队列;当connection关闭是否删除队列,一般是false,发布订阅是独占
             * 自动删除: 当没有消费者的时候,自动删除掉,一般是false
             * 其他参数
             *
             * 队列不存在则会自动创建,如果存在则不会覆盖,所以此时的时候需要注意属性
             */
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            for (int i = 0; i < 10; i++) {
                String message = "Hello World!";
                /**
                 * 参数说明:
                 * 交换机名称:不写则是默认的交换机,那路由健需要和队列名称一样才可以被路由,
                 * 路由健名称
                 * 配置信息
                 * 发送的消息数据:字节数组
                 */
                //发布消息
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println(" [x] Sent '" + message + "'");
            }
        }
    }
}
//消费者
public class Recv {
    private final static String QUEUE_NAME = "work_rr";

    public static void main(String[] argv) throws Exception {
        //消费者一般不增加自动关闭
        Connection connection= MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //回调方法,下面两种都行
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
                System.out.println("consumerTag消息标识="+consumerTag);
                //可以获取交换机,路由健等
                System.out.println("envelope元数据="+envelope);

                System.out.println("properties配置信息="+properties);

                System.out.println("body="+new String(body,"utf-8"));
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);

//        DeliverCallback deliverCallback = (consumerTag,delivery) -> {
//            String message = new String(delivery.getBody(), "UTF-8");
//            System.out.println(" [x] Received '" + message + "'");
//        };

        //自动确认消息
//        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}
//消费者2
public class Recv2 {
    private final static String QUEUE_NAME = "work_rr";

    public static void main(String[] argv) throws Exception {
        Connection connection= MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //回调方法,下面两种都行
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
                System.out.println("consumerTag消息标识="+consumerTag);
                //可以获取交换机,路由健等
                System.out.println("envelope元数据="+envelope);

                System.out.println("properties配置信息="+properties);

                System.out.println("body="+new String(body,"utf-8"));
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);

//        DeliverCallback deliverCallback = (consumerTag,delivery) -> {
//            String message = new String(delivery.getBody(), "UTF-8");
//            System.out.println(" [x] Received '" + message + "'");
//        };

        //自动确认消息
//        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}

公平策略
通过channel.basicQos(1);确保每个消费者每次只能处理一个未确认的消息。

public class Send {
    private final static String QUEUE_NAME="work_fair";

    public static void main(String[] args) throws IOException, TimeoutException {

        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
                Connection connection = MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
            /**
             * 队列名称
             * 持久化配置:mq重启后还在
             * 是否独占:只能有一个消费者监听队列;当connection关闭是否删除队列,一般是false,发布订阅是独占
             * 自动删除: 当没有消费者的时候,自动删除掉,一般是false
             * 其他参数
             *
             * 队列不存在则会自动创建,如果存在则不会覆盖,所以此时的时候需要注意属性
             */
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            for (int i = 0; i < 10; i++) {
                String message = "Hello World!";
                /**
                 * 参数说明:
                 * 交换机名称:不写则是默认的交换机,那路由健需要和队列名称一样才可以被路由,
                 * 路由健名称
                 * 配置信息
                 * 发送的消息数据:字节数组
                 */
                //发布消息
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println(" [x] Sent '" + message + "'");
            }
        }
    }
}
//消费者1
public class Recv {
    private final static String QUEUE_NAME = "work_fair";

    public static void main(String[] argv) throws Exception {
        Connection connection= MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        channel.basicQos(1);
        //回调方法,下面两种都行
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
                System.out.println("consumerTag消息标识="+consumerTag);
                //可以获取交换机,路由健等
                System.out.println("envelope元数据="+envelope);

                System.out.println("properties配置信息="+properties);

                System.out.println("body="+new String(body,"utf-8"));
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);

//        DeliverCallback deliverCallback = (consumerTag,delivery) -> {
//            String message = new String(delivery.getBody(), "UTF-8");
//            System.out.println(" [x] Received '" + message + "'");
//        };

        //自动确认消息
//        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}
//消费者2
public class Recv2 {
    private final static String QUEUE_NAME = "work_fair";

    public static void main(String[] argv) throws Exception {
        Connection connection=MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        channel.basicQos(1);
        //回调方法,下面两种都行
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
                System.out.println("consumerTag消息标识="+consumerTag);
                //可以获取交换机,路由健等
                System.out.println("envelope元数据="+envelope);

                System.out.println("properties配置信息="+properties);

                System.out.println("body="+new String(body,"utf-8"));
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume(QUEUE_NAME,false,consumer);

//        DeliverCallback deliverCallback = (consumerTag,delivery) -> {
//            String message = new String(delivery.getBody(), "UTF-8");
//            System.out.println(" [x] Received '" + message + "'");
//        };

        //自动确认消息
//        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}

🌟发布订阅模型

介绍

模型图
在这里插入图片描述

特点

  1. 一条消息可以被多个消费者同时接收。
  2. 采用扇形(Fanout)交换机。
  3. 无需路由Key
  4. 类似于公众号的订阅。

代码实现

生产者

public class Send {
    private final static String EXCHANGE_NAME="exchange_fanout";

    public static void main(String[] args) throws IOException, TimeoutException {
        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
                Connection connection = MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
                String message="daencode rabbitmq pub";
                channel.basicPublish(EXCHANGE_NAME," ",null,message.getBytes(StandardCharsets.UTF_8));
                System.out.println("广播消息已经发送!!!!");
        }
    }
}

消费者:两个消费者都是一样的代码,都需要绑定相同的扇形交换机。

public class Recv {
    private final static String EXCHANGE_NAME="exchange_fanout";

    public static void main(String[] argv) throws Exception {
        Connection connection = MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.FANOUT);

        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();

        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName,EXCHANGE_NAME,"");


        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };

        //自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
    }
}

🌟路由模型

介绍

模型图
在这里插入图片描述
特点

  1. 交换机类型采用直连交换机,特定的路由key由特定的消费者进行消费。
  2. 交换机根据特定的路由key与队列进行绑定。

代码实现

以记录不同日志级别为例,不同的消费者进行不同日志级别的记录。

生产者

public class Send {
    private final static String EXCHANGE_NAME="exchange_direct";

    public static void main(String[] args) throws IOException, TimeoutException {
        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
                Connection connection = MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
                String debugLog="[debug]daencode rabbitmq direct";
                String errorLog="[error]出现error错误";
                channel.basicPublish(EXCHANGE_NAME,"errorRoutingKey",null,errorLog.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME,"debugRoutingKey",null,debugLog.getBytes(StandardCharsets.UTF_8));
            System.out.println("消息已经发送!!!!");
        }
    }
}

消费者1:只记录ERROR级别日志。

public class Recv1 {
    private final static String EXCHANGE_NAME="exchange_direct";

    public static void main(String[] argv) throws Exception {
        Connection connection = MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.DIRECT);

        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();

        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName,EXCHANGE_NAME,"errorRoutingKey");


        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };

        //自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
    }
}

消费者2:只记录Debug级别日志。

public class Recv2 {
    private final static String EXCHANGE_NAME="exchange_direct";

    public static void main(String[] argv) throws Exception {
        Connection connection = MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.DIRECT);

        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();

        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName,EXCHANGE_NAME,"debugRoutingKey");


        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };

        //自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
    }
}

🌟主题模型

介绍

模型图
在这里插入图片描述
特点

  1. 交换机类型采用主题交换机。
  2. 路由key根据通配符规则,限定消息消费规则。*匹配一个词,#匹配一个或者多个词。
  3. 交换机通过通配符路由KEY将消息绑定到不同的队列,以此实现不同的消费者进行消息消费。
  4. 同时满足路由模型和发布订阅模型。

代码实现

生产者:生产者通过路由KEY向交换机发送消息。

public class Send {
    private final static String EXCHANGE_NAME="exchange_topic";

    public static void main(String[] args) throws IOException, TimeoutException {
        try (   //JDK7语法 或自动关闭 connnection和channel
                //创建连接
                Connection connection= MQConnectionUtil.createConnection();
                //创建信道
                Channel channel = connection.createChannel()) {
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
                String debugLog="[debug]daencode rabbitmq direct";
                String errorLog="[error]出现error错误";
                channel.basicPublish(EXCHANGE_NAME,"log.error",null,errorLog.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME,"log.debug",null,debugLog.getBytes(StandardCharsets.UTF_8));
            System.out.println("广播消息已经发送!!!!");
        }
    }
}

消费者

public class Recv1 {
    private final static String EXCHANGE_NAME="exchange_topic";

    public static void main(String[] argv) throws Exception {
        Connection connection= MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.TOPIC);

        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();

        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName,EXCHANGE_NAME,"*.debug");


        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };

        //自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
    }
}

消费者2


public class Recv2 {
    private final static String EXCHANGE_NAME="exchange_topic";

    public static void main(String[] argv) throws Exception {
        Connection connection= MQConnectionUtil.createConnection();
        Channel channel = connection.createChannel();
        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.TOPIC);

        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();

        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName,EXCHANGE_NAME,"*.error");


        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };

        //自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
    }
}

🌟总结

模型是否交换机参与交换机类型需要路由键描述
简单模型消息直接发送到队列,最基本的消息传递模型。
工作模型多个消费者共同处理一个队列中的消息。
发布订阅模型fanout将消息广播给所有绑定到交换机的队列,多个消费者同时订阅。
路由模型direct根据消息的路由键将消息发送到与之匹配的队列。
主题模型topic使用通配符进行灵活的路由,根据主题和通配符规则进行匹配。

🌟写在最后

有关于图解RabbitMQ五种队列模型介绍及代码实现到此就结束了。感谢大家的阅读,希望大家在评论区对此部分内容散发讨论,便于学到更多的知识。


请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1002487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年世界机器人大会回顾

1、前记&#xff1a; 本次记录是我自己去世界机器人博览会参观的一些感受&#xff0c;所有回顾为个人感兴趣部分的机器人产品分享。整个参观下来最大的感受就是科学技术、特别是机器人技术和人工智能毫无疑问地、广泛的应用在我们日常生活的方方面面&#xff0c;在安全巡检、特…

【洛谷算法题】P5704-字母转换【入门1顺序结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5704-字母转换【入门1顺序结构】&#x1f30f;题目描述&#x1f30f;输入格式&a…

ClickHouse进阶(十三):Clickhouse数据字典-3-文件数据源及Mysql数据源

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_大数据OLAP体系技术栈,Apache Doris,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…

metinfo __ 6.0.0 __ file-read

metinfo __ 6.0.0 __ file-read 说明内容漏洞编号–漏洞名称MetInfo 6.0.0 任意文件读取漏洞漏洞评级高危影响范围6.0.0.0漏洞描述MetInfo 存在任意文件读取漏洞&#xff0c;攻击者利用该漏洞&#xff0c;在具有权限的情况下&#xff0c;可以读取网站任意文件&#xff0c;包括…

ASP.NET+sqlserver公司项目管理系统

一、源码描述 这是一款简洁十分美观的ASP.NETsqlserver源码&#xff0c;界面十分美观&#xff0c;功能也比较全面&#xff0c;比较适合 作为毕业设计、课程设计、使用&#xff0c;感兴趣的朋友可以下载看看哦 二、功能介绍 该源码功能十分的全面&#xff0c;具体介绍如下&…

centos定期清理磁盘

centos/linux定期清理磁盘 要定时清理空间&#xff0c;我们需要了解一个命令&#xff0c;find 命令&#xff0c;这个命令可以查询目录下特定文件名&#xff0c;生成日期的文件 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.查找需要删除的 find /data_back/zhhyba…

buuctf crypto 【Cipher】解题记录

1.打开题目就有密文 2.一点思路没有&#xff0c;看看大佬的wp&#xff08;BUUCTF Cipher 1_cipher buuctf_玥轩_521的博客-CSDN博客&#xff09;&#xff0c;捏麻麻的原来玄机就在“公平的玩吧”这句话里&#xff0c;playfair也是一种加密方式&#xff0c;密钥猜测也是playfair…

SMB 协议详解之-NTLM身份认证

前面的文章说明了SMB协议交互的过程,在SMB交互的Session Setup Request/Response会对请求者的身份进行验证,这其中涉及到两个主要的协议NTLM以及Kerberos,本文将对NTLM协议进行详细的说明。 什么是NTLM NTLM是 NT LAN Manager (NTLM) Authentication Protocol 的缩写,主要…

MediaCodec源码分析 configure流程

前言 本文梳理MediaCodec configure流程,基于7.0代码,这里只分析AVC和HEVC的视频硬解,流程图如下。 代码见: frameworks/base/media/java/android/media/MediaCodec.java frameworks/base/media/jni/android_media_MediaCodec.h frameworks/base/media/jni/android_media_…

C#,数值计算——指数微分(exponential deviates)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 指数偏差 /// Structure for exponential deviates. /// </summary> public class Expondev : Ran { private double beta { get; set; } /// <s…

windows或者任何系统通过二进制安装最新的Protocol Buffer Compiler

此处使用二进制法安装,适用于任何操作系统 安装预编译的二进制文件&#xff08;任何操作系统&#xff09; 要从预编译的二进制文件安装最新版本的协议编译器&#xff0c;请按照以下说明操作&#xff1a; 1.从 github.com/google/protobuf/releases 手动下载与您的操作系统和计…

学习 [Spring MVC] 的JSR 303和拦截器,提高开发效率

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《推荐】Spring与Mybatis集成整合》 ⛺️ 生活的理想&#xff0c;不断更新自己 ! 1.JSR303 1.1JSR303是什么 JSR 303是Java规范请求&#xff08;Java Specification Request&#xff09;…

【AI理论学习】语言模型Performer:一种基于Transformer架构的通用注意力框架

语言模型Performer&#xff1a;一种基于Transformer架构的通用注意力框架 Performer论文解读Regular Attention MechanismFAVOR&#xff1a;通过矩阵相关性实现快速注意力 Attention的时间复杂性绕过softmax瓶颈通过Gaussian kernel求Softmax kernel寻找更稳定的Softmax内核使用…

单链表(Single Link Table)——单文件实现

一、单链表前言 上篇文章我们讲述了顺序表&#xff0c;认真学习我们会发现顺序表优缺点。 缺点1&#xff1a;头部和中部的插入删除效率都不行&#xff0c;时间和空间复杂度都为O(N); 缺点2&#xff1a;空间不够了扩容有一定的消耗(尤其是realloc的异地扩容)&#xff1b; 缺…

Linux网络编程:网络协议及网络传输的基本流程

目录 一. 计算机网络的发展 二. 网络协议的认识 2.1 对于协议分层的理解 2.2 TCP/IP五层协议模型 2.3 OSI七层模型 三. 网络传输的流程 3.1 同一网段中计算机通信的流程 3.2 不同网段中计算机设备的通信 3.3 对于IP地址和MAC地址的理解 3.4 数据的封装和解包 四. 总结…

2.linux的组管理和权限管理

一、组管理 1.Linux组的介绍 在linux中每个用户必须属于一个组&#xff0c;不能独立于组外。在linux中每个文件有所有者&#xff0c;所有组&#xff0c;其他组的概念 ①所有者 ②所在组 ③其他组 ④改变用户所在组 2.文件/目录 所有者 哪个用户创建了文件&#xff0c;就…

使用rpm重新安装包

#查询 rpm -qa | grep cloudstack #卸载 rpm -e cloudstack-agent-4.18.0.0-1.x86_64 #安装 rpm -ivh cloudstack-agent-4.18.0.0-1.x86_64.rpm

17.Xaml DockPanel控件 ---> 停靠面板

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

CFD模拟仿真理论求解-基于大数据的物理现象研究:热传导方程的数值求解

基于大数据的物理现象研究&#xff1a;热传导方程的数值求解 CFD模拟仿真理论求解 在科学研究和工程实践中&#xff0c;许多物理现象都可以用微分方程来描述。其中&#xff0c;热传导方程是一个非常重要且基础的例子。热传导方程是一个二阶线性偏微分方程&#xff0c;描述了热…

Docker-namespace

Docker-namespace namespace基础命令dd 命令mkfsdfmountunshare pid 隔离试验mount 隔离 namespace namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源&#xff0c;而另外一些进程也只能看到与它们自己相关的资源…