RabbitMQ支持的消息模型

  • RabbitMQ基础
  • RabbitMQ支持的消息模型

一、第一种模型(直连)

我们将用Java编写两个程序,发送单个消息的生成者和接收消息并打印出来的消费者。
在下图,“P”是生成者,“C”消费者。中间框是一个队列RabbitMQ保留的消息缓冲区 。

首先构建一个Maven项目,然后引入依赖。

<!-- 导入rabbitmq原生依赖-->
<dependency>
  <groupId>com.rabbitmq</groupId>
  <artifactId>amqp-client</artifactId>
  <version>5.10.0</version>
</dependency>
定义生产者
import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
* @author db
* @version 1.0
* @description Provider 生产者代码
* @since 2022/12/29
*/
public class Producer {

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

        //        // 1.创建连接工厂
        //        ConnectionFactory connectionFactory = new ConnectionFactory();
        //        // 2.设置连接属性
        //        connectionFactory.setHost("192.168.137.120");
        //        connectionFactory.setPort(5672);
        //        connectionFactory.setVirtualHost("/");
        //        connectionFactory.setUsername("admin");
        //        connectionFactory.setPassword("123456");
        //        connectionFactory.setHandshakeTimeout(60000);
        //
        //        // 3.从连接工厂获得连接
        //        Connection connection = connectionFactory.newConnection();

        // 从工具类中获得连接
        Connection connection = RabbitMqUtil.getConnection();
        // 4.从连接中获得channel
        Channel channel = connection.createChannel();
        // 5.声明队列queue存储消息

        /**
         * 参数s:队列名称 如果队列不存在就自动创建
         * 参数b:用来定义队列特性是否要持久化 true 持久化队列  false 不持久化
         * 参数b1: exclusive 是否独占队列  true 独占队列 false 不独占
         * 参数b2:autoDelete 是否在消费完成后自动删除队列 true 自动删除 false 不自动删除
         * 参数5:额外附加参数
         *
         */
        channel.queueDeclare("hello",true,false,false,null);

        // 7.发送消息给中间件
        // 参数1:交换机名称 参数2:队列名称 参数3:传递消息的额外设置 参数4:
        channel.basicPublish("","hello", MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());

        System.out.println("消息发送成功");


        //        // 8.关闭连接
        //        channel.close();
        //        connection.close();

        RabbitMqUtil.closeConnectionAndChannel(channel,connection);
    }
}

执行发送,这个时候可以在web控制台查看到这个队列queue的信息。

定义消费者

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author db
 * @version 1.0
 * @description Consumer  消费者
 * @since 2022/12/29
 */
public class Consumer {

    public static void main(String[] args) throws IOException, TimeoutException {
//        ConnectionFactory connectionFactory = new ConnectionFactory();
//        connectionFactory.setHost("192.168.137.120");
//        connectionFactory.setPort(5672);
//        connectionFactory.setVirtualHost("/");
//        connectionFactory.setUsername("admin");
//        connectionFactory.setPassword("123456");
//        connectionFactory.setHandshakeTimeout(60000);
//
//        // 创建连接
//        Connection connection = connectionFactory.newConnection();

        // 从工具类中获得连接
        Connection connection = RabbitMqUtil.getConnection();
        // 创建信道
        Channel channel = connection.createChannel();

        // 消费者成功消费时的回调
        DeliverCallback deliverCallback = (consumerTag,message) ->{
            System.out.println(new String(message.getBody()));
        };

        // 消费者取消消费时的回调
        CancelCallback callback = consumerTag ->{
            System.out.println("消费者取消消费接口的回调");
        };

        // 参数1:消费队列的名称
        // 参数2:消息的自动确认机制(已获得消息就通知MQ消息已被消费)true 打开 false 关闭
        // 参数3:
        channel.basicConsume("hello",true,deliverCallback,callback);

//        channel.close();
//        connection.close();
    }
}


工具类的包装

package com.duan.rabbitmq.utils;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author db
 * @version 1.0
 * @description RabbitMqUtil
 * @since 2023/1/2
 */
public class RabbitMqUtil {

    // 定义提供连接对象的方法
    public static Connection getConnection(){
        try{
            // 1.创建连接工厂
            ConnectionFactory connectionFactory = new ConnectionFactory();
            // 2.设置连接属性
            connectionFactory.setHost("192.168.137.120");
            connectionFactory.setPort(5672);
            connectionFactory.setVirtualHost("/");
            connectionFactory.setUsername("admin");
            connectionFactory.setPassword("123456");

            connectionFactory.setHandshakeTimeout(60000);
            return connectionFactory.newConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    // 关闭连接通道和关闭连接的工具方法
    public static void closeConnectionAndChannel(Channel channel,Connection connection){
        try{
            if(channel !=null){
                channel.close();
            }
            if(connection != null){
                connection.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

报连接超时错误

**解决方案:**原因是连接超时,加超时时间。

maevn项目设置超时时间:factory.setHandshakeTimeout\(60000\)

二、第二种模型(work quene)

work queues被称为任务队列(Task queues)。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。长此以往,消息就会堆积越来越多,无法及时处理。此时就可以使用work 模型: 让多个消费者绑定到一个队列,共同消费队列中的消息。 队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。

  • P:生产者
  • C1:消费者1
  • C2:消费者2
定义生成者
package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Producer
 * @since 2023/3/24
 */
public class Producer {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();
        /**
         * 声明队列queue存储信息
         * 参数1: 队列名称
         * 参数2: 用来定义队列是否要持久化
         * 参数3: exclusion 是否是独占队列
         * 参数4: autoDelete 是否再消费完成后自动删除队列
         * 参数5: 额外附加参数
         */
        channel.queueDeclare("work",true,false,false,null);

        for(int i = 0; i<10; i++){
            // 参数1:交换机名称 参数2:队列名称 参数3:消息传递的额外设置
            channel.basicPublish("","work",null,(i+"work").getBytes());
        }
        RabbitMqUtil.closeConnectionAndChannel(channel,connection);
    }
}
定义消费者1
package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer1
 * @since 2023/3/24
 */
public class Consumer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        // 创建信道
        Channel channel = connection.createChannel();

        // 消费者消费成功时的回调
        channel.queueDeclare("work",true,false,false,null);
        channel.basicConsume("work",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{
                System.out.println("消费者1: "+new String(body));
            }
        });
        RabbitMqUtil.closeConnectionAndChannel(channel,connection);
    }
}
定义消费者2
package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer1
 * @since 2023/3/24
 */
public class Consumer2 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        // 创建信道
        Channel channel = connection.createChannel();

        // 消费者消费成功时的回调
        channel.queueDeclare("work",true,false,false,null);
        channel.basicConsume("work",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{
                try{
                    Thread.sleep(2000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("消费者2: "+new String(body));
            }
        });
        RabbitMqUtil.closeConnectionAndChannel(channel,connection);
    }
}

rabbitMQ讲按照顺序将每个消息发给下一个使用者,每个消费者都会收到相同数量的消息。
测试结果

消息确认机制

前面看到的是所有的消费者均分消息,会有一个问题,如果一个消费者宕机了,会出现消息丢失现场,希望当出现消费者宕机时,消息被另一个消费者消费,也就是多劳多得生产者代码。

package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Producer
 * @since 2023/3/24
 */
public class Producer {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();
        /**
         * 声明队列queue存储信息
         * 参数1: 队列名称
         * 参数2: 用来定义队列是否要持久化
         * 参数3: exclusion 是否是独占队列
         * 参数4: autoDelete 是否再消费完成后自动删除队列
         * 参数5: 额外附加参数
         */
        channel.queueDeclare("work",true,false,false,null);

        for(int i = 0; i<20; i++){
            // 参数1:交换机名称 参数2:队列名称 参数3:消息传递的额外设置
            channel.basicPublish("","work",null,(i+"work").getBytes());
        }

        RabbitMqUtil.closeConnectionAndChannel(channel,connection);

    }
}

生成者1

package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer3
 * @since 2023/11/27
 */
public class Consumer3 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        // 创建信道
        Channel channel = connection.createChannel();

        channel.basicQos(1); // 每次只消费一个消息
        // 消费者消费成功时的回调
        channel.queueDeclare("work",true,false,false,null);
        channel.basicConsume("work",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{
                System.out.println("消费者1: "+new String(body));

                // 手动确认,参数1:消息标识  参数2:每次确认1个
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });

    }
}

生成者2

package com.duan.rabbitmq.work;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer4
 * @since 2023/11/27
 */
public class Consumer4 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtil.getConnection();
        // 创建信道
        Channel channel = connection.createChannel();

        channel.basicQos(1);  // 每次消费一个消息
        // 消费者消费成功时的回调
        channel.queueDeclare("work",true,false,false,null);
        channel.basicConsume("work",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException{
                try{
                    Thread.sleep(2000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("消费者2: "+new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });


    }
}

测试结果

三、第三种模型(Fanout)

广播模式下:发送消息流程是可以有多个消费者每个消费者都有自己的队列(queue)每个队列都要绑定交换机(exchange)生成者发送消息,只能发送到交换机,交换机决定把消息发给哪个队列,生成者无法决定交换机把消息发给绑定过的所有队列,队列的消费者都能拿到消息,一条消息可以被多个消费者消费。

生产者
package com.duan.rabbitmq.fanout;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Provider
 * @since 2023/11/28
 */
public class Provider {
    public static void main(String[] args) throws IOException {

        // 获取连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 将通道声明交换机  参数1:交换机名称 参数2:交换机类型
        channel.exchangeDeclare("logs","fanout");

        // 发送消息
        channel.basicPublish("logs","",null,"fanout type message".getBytes());

        // 释放资源
        RabbitMqUtil.closeConnectionAndChannel(channel,connection);

    }
}
消费者1
package com.duan.rabbitmq.fanout;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Customer1
 * @since 2023/11/28
 */
public class Customer1 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("logs","fanout");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"logs","");

        // 消费消息
        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("消费者1: "+new String(body));
            }
        });
    }
}
消费者2
package com.duan.rabbitmq.fanout;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Customer1
 * @since 2023/11/28
 */
public class Customer2 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("logs","fanout");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"logs","");

        // 消费消息
        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("消费者2: "+new String(body));
            }
        });
    }
}
消费者3
package com.duan.rabbitmq.fanout;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Customer1
 * @since 2023/11/28
 */
public class Customer3 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("logs","fanout");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"logs","");

        // 消费消息
        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("消费者3: "+new String(body));
            }
        });
    }
}
测试结果

四、第四种模型(Routing)

fanout模式中,一条消息,会被所有绑定的队列都能消费,但是,在某些场景下,希望不同的消息被不同的队列消费,就需要Direct类型的exchange

Direct模型下:队列与交换机的绑定,不是任意绑定的,而是要指定一个RoutingKey(路由key)消息的发送方在向Exchange发送消息时,也必须指定消息的 RoutingKeyExchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息。

生产者
package com.duan.rabbitmq.direct;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Provider
 * @since 2023/11/28
 */
public class Provider {
    public static void main(String[] args) throws IOException {
        // 建立连接
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("logs_direct","direct");

        String routingKey = "error";
        channel.basicPublish("logs_direct",routingKey,null,("这是direct模型发布的基于route key: ["+routingKey+"] 发送的消息").getBytes());

        RabbitMqUtil.closeConnectionAndChannel(channel,connection);
    }
}
消费者1
package com.duan.rabbitmq.direct;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer1
 * @since 2023/11/28
 */
public class Consumer1 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("logs_direct","direct");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"logs_direct","error");

        // 消费消息
        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("消费者1: "+new String(body));
            }
        });
    }
}
消费者2
package com.duan.rabbitmq.direct;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Consumer1
 * @since 2023/11/28
 */
public class Consumer2 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("logs_direct","direct");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"logs_direct","info");
        channel.queueBind(queue,"logs_direct","error");
        channel.queueBind(queue,"logs_direct","warning");

        // 消费消息
        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("消费者1: "+new String(body));
            }
        });
    }
}
测试结果

routingKeyinfo时,消费者1和消费者2结果如下:

routingKeyerror时,消费者1和消费者2结果如下:

五、第五种模型(topic)

Topic类型的ExchangeDirect相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符!BindingKey 一般都是有一个或多个单词组成,多个单词之间以.分割,例如: item.insert通配符规则:

  • #:匹配一个或多个词
  • *:匹配不多不少恰好1个词

举例:

  • item.#:能够匹配item.spu.insert 或者 item.spu
  • item.*:只能匹配item.spu
生产者
package com.duan.rabbitmq.topic;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Provider
 * @since 2023/11/30
 */
public class Provider {

    public static void main(String[] args) throws IOException {
        //获取连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        //声明交换机以及交换机类型 topic
        channel.exchangeDeclare("topics","topic");

        //发布消息
        String routekey = "save.user.delete";

        channel.basicPublish("topics",routekey,null,("这里是topic动态路由模型,routekey: ["+routekey+"]").getBytes());

        //关闭资源
        RabbitMqUtil.closeConnectionAndChannel(channel,connection);

    }


}
消费者1
package com.duan.rabbitmq.topic;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Customer1
 * @since 2023/11/30
 */
public class Customer1 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("topics","topic");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"topics","*.user.*");

        // 消费消息
        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("消费者1: "+new String(body));
            }
        });
    }
}
消费者2
package com.duan.rabbitmq.topic;

import com.duan.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author db
 * @version 1.0
 * @description Customer1
 * @since 2023/11/30
 */
public class Customer2 {
    public static void main(String[] args) throws IOException {
        // 获得连接对象
        Connection connection = RabbitMqUtil.getConnection();
        Channel channel = connection.createChannel();

        // 通道绑定交换机
        channel.exchangeDeclare("topics","topic");

        // 绑定临时队列
        String queue = channel.queueDeclare().getQueue();

        // 绑定交换机和队列
        channel.queueBind(queue,"topics","*.user.#");

        // 消费消息
        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("消费者1: "+new String(body));
            }
        });
    }
}
测试结果

代码地址:https://gitee.com/duan138/practice-code/tree/dev/rabbitmq-java

六、总结

以上就是rabbitMQ中常见的几种模式,这些模型通过交换机(Exchange)和队列(Queue)的不同组合与绑定方式实现。本文只是初步了解RabbitMQ相关知识。后续会讲解怎么在SpringBoot中应用。


改变你能改变的,接受你不能改变的,关注公众号:程序员康康,一起成长,共同进步。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

win11右键二级菜单恢复成win10一级菜单

winr输入“cmd”回车&#xff0c;打开cmd窗口&#xff0c;输入如下命令&#xff0c;并回车。reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve提示cuccessfully&#xff0c;表示操作成功。重启电脑即可。 如下…

测试记录3:WLS2运行Linux界面

1.WLS1转到WLS2 &#xff08;1&#xff09;根据自己的平台&#xff0c;下载WLS2安装包 x64: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi arm64: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_arm64.msi &#xff08;2&…

《2024年网络安全预测:未来规划深度洞察》

2024 年打击网络对手的计划。 阅读报告&#xff0c;了解我们的专家对 2024 年网络安全行业的预测&#xff0c;包括&#xff1a; 攻击者将人工智能融入其行动中&#xff0c;防御者利用它来加强检测和响应 民族国家继续开展网络行动以实现其地缘政治目标 攻击者继续利用零日漏洞…

word 无法自动检测拼写

word 有时候不能分辨是哪种语言,比如把英语错认为法语 。 例如&#xff1a;Interlaayer spacace,发现误认为是法语。 1、选中Interlaayer spacace 2、点击语言下拉按钮 选择设置校对语言 发现校对语言为法语 3、手动修改校对语言为英语&#xff0c;并点击确认。 4、发现现…

【ARM Cache 及 MMU 系列文章 6.1 -- Cache maintenance 相关寄存器及指令详细介绍】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Cache Maintenance registers and instructionsDCZID_EL0DCZID_EL0寄存器字段解释 DCZ 使用场景Cache maintenance 范围选择 Cache maintenance 指令集 Cache Maintenance registers a…

学习笔记——路由网络基础——等开销负载均衡

3、等开销负载均衡 等开销负载均衡&#xff1a;到达同一目标网段&#xff0c;存在多条路由条目&#xff0c;存在两条或两条以上的路由优先级值和开销值都是最优的(优先级值和开销值一致)&#xff0c;则这几条路径执行负载均衡(在ping中就是这条路由发个包再下一条路由再发个包…

如何进行光伏户用开发?

1、业主端使用 业主使用手机端进行账户注册&#xff0c;填写个人信息&#xff1b;开设银行二类卡&#xff0c;用于电费的结转。之后就可以进行线上合同签署。 2、踏勘收资 大家可以借助一些踏勘软件&#xff0c;例如无人机踏勘、卫星踏勘等&#xff0c;使用无人机搭载高清摄…

超实惠的GPU云服务器安利!!

自己一个人抱着老笔记本学深度学习&#xff0c;没有GPU是真的难受。Colab用过&#xff0c;GPU稍微用用就被剥夺了。华为云在培训的时候也用过&#xff0c;好贵。现在学到大模型&#xff0c;cuda10.1举步维艰。 失眠在网上冲浪&#xff0c;刷到了潞晨云&#xff0c;一块六就能用…

FFA-Net:用于单图像去雾的特征融合注意力网络

摘要 论文链接&#xff1a;https://arxiv.org/pdf/1911.07559v2 在这篇论文中&#xff0c;我们提出了一种端到端的特征融合注意力网络&#xff08;FFA-Net&#xff09;来直接恢复无雾图像。FFA-Net架构由三个关键组件组成&#xff1a; 一种新颖的特征注意力&#xff08;FA&…

【python】IndexError: Replacement index 1 out of range for positional args tuple

成功解决“IndexError: Replacement index 1 out of range for positional args tuple”错误的全面指南 一、引言 在Python编程中&#xff0c;IndexError: Replacement index 1 out of range for positional args tuple这个错误通常发生在使用str.format()方法或者f-string&am…

SpringBoot: 读取项目的Git版本号

在开发项目的时候&#xff0c;我们经常会想要拿到线上运行的程序版本&#xff0c;以确定程序是否正确发布。Spring Boot提供了这样的能力支持。这个能力的核心组件是3个: Maven插件git-commit-id-maven-plugin&#xff0c;用于生成.properties文件&#xff0c;里边包含git的各…

LeetCode 算法:最大子数组和c++

原题链接&#x1f517;&#xff1a;最大子数组和 难度&#xff1a;中等⭐️⭐️ 题目 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 …

LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关

角色扮演&#xff1a;在系统指令中告诉千问你需要它扮演的角色&#xff0c;即可沉浸式和该角色对话交流语言风格&#xff1a;简单调整 LLM 的语言风格任务设定&#xff1a;比如旅行规划&#xff0c;小红书文案助手这样的专项任务处理System message 也可以被用于规定 LLM 的答复…

使用 LiteGraph.js 构建可视化工作流图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 LiteGraph.js 构建可视化工作流图 应用场景介绍 LiteGraph.js 是一个轻量级的开源 JavaScript 库&#xff0c;用于构建可视化工作流图。它广泛应用于游戏开发、数据可视化、交互式叙事等领域。 代码基本…

人工智能的兴起和发展

人工智能的兴起 人工智能&#xff0c;artificial intelligence&#xff0c;缩写为AI。 它是随着计算机技术的发展才逐步产生并发展起来的一门学科。关于AI的定义有很多种&#xff0c;通俗一点说&#xff0c;它企图了解智能的实质&#xff0c;并生产出一种新的&#xff0c;能以…

从学士-硕士-博士-博士后-副教授-教授-优青-杰青-长江-院士:一文看懂学术巨人的成长历程

会议之眼 快讯 学术之路&#xff0c;如同攀登一座高耸入云的山峰&#xff0c;需要毅力、智慧和不断的求知探索。从奠定基础的学士&#xff0c;到站在学术巅峰的院士。这条成长之路充满了挑战和机遇。 如果把学术界比作王者荣耀&#xff0c;那么学者们的成长历程就像是在进行一…

真实场景 这周的任意一天,获取上周一到周日的时间范围-作者:【小可耐教你学影刀RPA】

用户场景 我想在这周的任意一天&#xff0c;获取上周一到周日的时间范围&#xff0c;应该怎么做 解决办法1 用指令解决 最简单 解决办法2 自己写逻辑 不过要用到 获取当前日期指令 当前是礼拜几

DuDuTalk柜台拾音器:如何助力营业厅实现3分钟快速风险响应?

在运营商、金融服务、政府服务场景&#xff0c;营业厅是企业和政府与客户互动的第一线&#xff0c;也是风险管理的关键环节。随着技术的发展&#xff0c;以AI技术为基础的新一代营业厅柜台服务智能管理产品——DuDuTalk柜台拾音器已成为营业厅风险管理的新策略&#xff0c;帮助…

Docker部署青龙面板

青龙面板 文章目录 青龙面板介绍资源列表基础环境一、安装Docker二、安装Docker-Compose三、安装青龙面板3.1、拉取青龙&#xff08;whyour/qinglong&#xff09;镜像3.2、编写docker-compose文件3.3、检查语法启动容器 四、访问青龙面板五、映射本地部署的青龙面板至公网5.1、…

TCP的核心属性

TCP的核心属性 一: TCP的核心属性1.1: 确认应答:1.2 : 超时重传1.3 : 连接管理1.3.1 三次握手1.3.2 四次挥手 1.4 滑动窗口1.5: 流量控制:1.6 拥塞控制1.7 延时应答1.8 :捎带应答1.9: 面向字节流1.10 : 异常情况 一: TCP的核心属性 1.1: 确认应答: 保证可靠性最核心的机制 1…