【RabbitMQ】初识消息队列 MQ,基于 Docker 部署 RabbitMQ,探索 RabbitMQ 基本使用,了解常见的消息类型

news2024/11/19 1:32:32

文章目录

  • 前言
  • 一、初识消息队列 MQ
    • 1.1 同步通信
    • 1.2 异步通信
    • 1.3 MQ 常见框架及其对比
  • 二、初识 RabbitMQ
    • 2.1 什么是 RabbitMQ
    • 2.2 RabbitMQ 的结构
  • 三、基于 Docker 部署 RabbitMQ
  • 四、常见的消息类型
  • 五、示例:在 Java 代码中通过 RabbitMQ 发送消息
    • 5.1 消息发布者
    • 5.2 消息消费者
    • 5.3 使用 RabbitMQ 的原生 Java 客户端操作消息队列存的问题


前言

一、初识消息队列 MQ

1.1 同步通信

同步通信是指发起请求后,调用者需要等待服务提供者的响应。

  1. 同步通信的例子


使用手机打电话就是一种同步通信,此时我们只能与一个妹子进行通话,但是如果有另外的妹子想要和自己通话,那么就会建立通话失败,想想确实是一件遗憾的事情。

  1. 同步通信在程序中的调用问题

比如,微服务间基于 Feign 实现远程调用,而这种调用方式就是一种同步通信,例如下面微服务之间的调用关系图:

通过这个图示,可以很好的展示在微服务中,同步通信存在的弊端:

  1. 用户通过手机端调用了支付服务,再目前这个架构中,其他的服务如订单服务、仓储服务、短信服务等等在支付服务中的调用代码都是线性关系,也就是说只有当支付功能完成后还需要调用其他的服务,调用完所有的微服务之后,支付服务才算完成。
  2. 此时所有的微服务都是一个线性关系,因此用户支付所花费的时间就是所有微服务处理业务的时间总和了,此时带给用户的体验不佳不说,如果是面对高并发的场景,整个系统也很大可能会招架不住。
  3. 此时由于所有微服务都是线性关系的,如果系统中的一个微服务宕机了,那么整个系统就会崩溃。
  4. 如果要新增一个需求,即需要新增一个微服务,那么就会修改支付服务的代码,此时系统的耦合度较高。

因此,总体来说,同步调用存在如下问题:

  1. 耦合度高: 每次加入新的需求,都要修改原来的代码。
  2. 性能下降: 调用者需要等待服务提供者响应,如果调用链过长则响应时间等于每次调用的时间之和。
  3. 资源浪费: 调用链中的每个服务在等待响应过程中,不能释放请求占用的资源,高并发场景下会极度浪费系统资源。
  4. 级联失败: 如果服务提供者出现问题,所有调用方都会跟着出问题,如同多米诺骨牌一样,迅速导致整个微服务群故障。

但是对于同步通信来说也具有优点:

例如,它的时效性很强,就如电话通信一样,可以实时获取对方的消息。

1.2 异步通信

异步通信是指发起请求后,调用者不需要立即等待服务提供者的响应。

  1. 异步通信的例子

例如,通过微信发送信息就是一种一步通信,当收到了消息之后,我们才去看收到的消息。并且同时可以向多个妹子发消息,一个不回就换另一个发,总有一个回消息的。

  1. 异步通信的方案——事件驱动模式

异步通信常见实现就是事件驱动模式,即某个消息就绪了,再通知其他服务来处理,如下图所示,微服务的调用就采用了事件驱动的模式:

通过这个图示,可以很好的展示在微服务中,异步通信的优势:

  1. 用户通过手机端调用支付服务,支付功能完成后将支付成功的消息发送给Broker,此时反馈给用户的耗时也就是这两步的耗时之后,此时的时间就非常短了,带给用户的体验也更佳。

  2. 这里的 Broker代表的是消息中间件。在消息传递中,Broker 是一种常见的模式。消息中间件充当了消息的中心处理单元,它接收来自生产者的消息,将其存储在队列中,并将消息传递给消费者。这种模式有助于实现解耦、异步通信和提高系统的可伸缩性。

  3. Broker 收到了支付成功的消息之后,立即向其他的订阅者通知自己收到了支付成功的消息,然后其他的微服务再向 Broker 获取这个消息来完成自己的业务。

  4. 此时各种微服务之间的依赖性大大降低了,如果一个微服务宕机了并不会对整个系统造成太大的影响,并且如果想要新增微服务的话也不需要改动其他微服务的代码,降低了耦合度。

  5. 另外,Broker 也起到了消息缓存的作用,如果突然产生了大量的消息,可以缓存到 Broker中,而不至于对其他微服务造成过大的压力。

因此,总体来说,异步通信具体如下的优点:

  1. 耦合度低: 利用中间件 Broker 对各个微服务实现了解耦,即使新增业务也不会对其他微服务造成影响。
  2. 性能提升: 消息发布者只管将消息发送给中间件Broker,而无需关心其他微服务的执行。
  3. 故障隔离: 由于耦合度降低,因此一个微服务发生了故障,不会对其他微服务造成影响。
  4. 流量削峰: Broker 具有对消息的缓存作用,突然面对大量的并发的时候,可以起到缓冲作用。

但是异步通信也具有如下的缺点:

  1. 整个系统对消息中间件Broker 的可靠性依赖程度高,如果Broker 中间件异常了则会影响整个系统。
  2. 系统的架构更加复杂,业务没有明显的流程线,对业务管理追踪的难度大大提升。

1.3 MQ 常见框架及其对比

MQ 是 “消息队列” 的缩写,它是一种在分布式系统中用于进行异步通信的技术。消息队列允许不同的软件组件或系统之间通过在消息队列中发送和接收消息来进行通信,而不需要直接连接彼此,在上述的事件驱动架构中,Broker 就是 MQ。

在消息队列领域,有多种常见的框架,每个框架都有其优点和适用场景。一些常见的消息队列框架有:RabbitMQ、ActiveMQ、RocketMQ 和 Kafka 。它们都是消息中间件(Message Queue)系统,用于实现分布式系统中不同组件之间的异步通信。它们在设计和使用方面有一些区别,以下是它们的简要介绍:

  1. RabbitMQ:

    • 特点: RabbitMQ 是一个开源的消息代理软件,实现了高级消息队列协议(AMQP)。
    • 设计理念: 设计简单、易于使用,支持广泛的消息传递模式,包括点对点、发布/订阅、请求/响应等。
    • 语言支持: 支持多种编程语言,如Java、Python、Ruby等。
    • 可靠性: 提供持久性消息、消息确认等机制,确保消息的可靠性传递。
  2. ActiveMQ:

    • 特点: ActiveMQ 是一个开源的消息中间件,实现了Java Message Service(JMS)规范。
    • 设计理念: 面向Java应用,提供了丰富的API,支持多种消息传递模式和高级功能。
    • 语言支持: 主要支持Java,但也有一些其他语言的客户端。
    • 可靠性: 提供持久订阅、消息事务等功能,确保可靠性和一致性。
  3. RocketMQ:

    • 特点: RocketMQ 是阿里巴巴开源的分布式消息中间件系统。
    • 设计理念: 设计为分布式、水平可扩展的系统,适用于大规模数据的处理。
    • 语言支持: 提供Java、C++、Python等多语言的客户端。
    • 可靠性: 支持多种消息传递模式,具备高可用性、高吞吐量和低延迟的特性。
  4. Kafka:

    • 特点: Kafka 是由Apache软件基金会开发的分布式流处理平台,兼具消息队列和日志系统的功能。
    • 设计理念: 设计为高吞吐、持久性、可水平扩展的分布式系统,用于处理实时数据流。
    • 语言支持: 提供Java和Scala等语言的客户端。
    • 可靠性: 提供副本机制、持久性日志存储等特性,适用于大规模数据流的处理。

如下表所示,总结了这四种消息队列在不同方面的差异:

特性RabbitMQActiveMQRocketMQKafka
公司/社区RabbitApache阿里Apache
开发语言ErlangJavaJavaScala&Java
协议支持AMQP, XMPP, SMTP, STOMPOpenWire, STOMP, REST, XMPP, AMQP自定义协议自定义协议
可用性一般
单机吞吐量一般非常高
消息延迟微秒级毫秒级毫秒级毫秒以内
消息可靠性一般一般

这个表格展示了这四个消息队列框架的一些关键特性的对比。总体而言,选择其中一个消息中间件系统通常取决于具体的业务需求、系统架构以及性能要求。不同的系统可能更适合不同的消息中间件。

二、初识 RabbitMQ

2.1 什么是 RabbitMQ

RabbitMQ 是一个开源的消息代理软件,实现了高级消息队列协议(AMQP)。它允许不同应用之间进行异步通信,并提供了一种有效的方式来处理分布式系统中的大量消息。

官方网站:https://www.rabbitmq.com

下面是 RabbitMQ 的一些关键特点:

  • 消息代理: RabbitMQ 充当消息代理,负责接收、存储和转发消息。

  • 消息队列: 通过消息队列实现消息的存储和传递,允许生产者将消息发送到队列,而消费者从队列中接收消息。

  • 消息模型: 支持多种消息传递模型,包括点对点、发布/订阅、请求/响应等。

  • 可靠性: 提供持久性消息、消息确认等机制,确保消息的可靠传递。

  • 灵活性: RabbitMQ 是高度可配置的,支持多种插件和扩展,可以适应不同的应用场景。

  • 跨平台: 支持多种操作系统,并提供多种语言的客户端,如 Java、Python、Ruby 等。

RabbitMQ 的设计理念是简单、灵活、可靠,并且具有广泛的应用领域,从企业级应用到小型项目都能发挥其优势。通过使用 RabbitMQ,开发人员可以更轻松地实现分布式系统中的消息传递和解耦。

2.2 RabbitMQ 的结构

RabbitMQ 的整体结构如下图所示:

RabbitMQ Structure

在上图中,我们可以看到 RabbitMQ 的结构主要涉及以下几个核心概念:

  • Producer(生产者): 生产者是消息的发送方,负责将消息发送到 RabbitMQ 服务器。

  • Exchange(交换机): 交换机接收来自生产者的消息,并将其路由到一个或多个队列。交换机有不同的类型,包括直连交换机(direct)、主题交换机(topic)、扇出交换机(fanout)等,用于定义消息的路由规则。

  • Queue(队列): 队列是消息的存储位置,生产者或交换机将消息发送到队列,而消费者则从队列中接收消息进行处理。

  • Binding(绑定): 绑定定义了 Exchange 和 Queue 之间的关系,指定消息如何从 Exchange 路由到特定的队列。绑定规则根据交换机的类型而异。

  • Consumer(消费者): 消费者是消息的接收方,负责从队列中获取消息并进行相应的处理。

  • VirtualHost(虚拟主机): 虚拟主机是逻辑上的隔离单位,每个虚拟主机都拥有自己的独立的用户、交换机、队列等资源,用于隔离不同应用或团队的消息流。

RabbitMQ 的结构允许构建灵活的消息传递系统,支持多种消息传递模式和路由策略,使其适用于各种不同的应用场景。这种灵活性使得 RabbitMQ 成为分布式系统中常用的消息中间件。

三、基于 Docker 部署 RabbitMQ

RabbitMQ的部署分为单机部署和集群部署,这里以单机部署为例。在 Centos7 虚拟机中使用 Docker 部署 RabbitMQ,以下是单例部署的步骤:

  1. 拉取 RabbitMQ 镜像

    使用以下命令拉取带有管理插件的 RabbitMQ 镜像:

    docker pull rabbitmq:3-management
    

  1. 启动 RabbitMQ 容器

    执行以下命令启动 RabbitMQ 容器:

    docker run \
    -e RABBITMQ_DEFAULT_USER=yourname \
    -e RABBITMQ_DEFAULT_PASS=yourpassword \
    --name mq \
    --hostname mq1 \
    -p 15672:15672 \
    -p 5672:5672 \
    -d \
    rabbitmq:3-management
    
    • yourname:自定义的 RabbitMQ 用户名。
    • yourpassword:自定义的 RabbitMQ 密码。

例如:

  1. 访问 RabbitMQ 管理界面

    启动成功后,通过浏览器访问 宿主机IP:15672,使用上述用户名和密码登录 RabbitMQ 管理界面。

在管理界面中,我们可以监控队列、交换机,查看连接、通道等信息。

通过上述步骤,就完成了基于 Docker 的 RabbitMQ 单例部署。在实际生产环境中,可能还需要考虑持久化配置、集群部署等问题。

四、常见的消息类型

RabbitMQ 提供了多种消息传递模型,常见的消息类型包括以下几种,对应 RabbitMQ 官方文档中的不同示例:

  1. 基本消息队列(BasicQueue)
    BasicQueue

    • 描述: 这是最简单的消息队列模型,一个生产者发送消息到队列,一个消费者从队列中接收并处理消息。
  2. 工作消息队列(WorkQueue)

    WorkQueue

    • 描述: 多个消费者共享一个队列,生产者发送消息到队列,其中一个消费者接收并处理消息。适用于任务分发和负载均衡。
  3. 发布订阅(Publish、Subscribe)

    • 广播(Fanout Exchange)

      Fanout Exchange

      • 描述: 生产者将消息发送到交换机,交换机将消息广播到所有与之绑定的队列。每个队列都有自己的消费者。
    • 路由(Direct Exchange)

      Direct Exchange

      • 描述: 生产者发送带有指定路由键的消息到交换机,交换机根据路由键将消息路由到匹配的队列。每个队列有一个或多个消费者。
    • 主题(Topic Exchange)

      Topic Exchange

      • 描述: 类似于直连交换机,但是主题交换机允许使用通配符进行匹配,以实现更灵活的消息路由。

这些不同的消息类型满足了不同的应用场景需求,使 RabbitMQ 成为一个灵活而强大的消息中间件。通过选择合适的消息模型,开发人员可以更好地满足系统设计的要求。

五、示例:在 Java 代码中通过 RabbitMQ 发送消息

5.1 消息发布者

以下是一个通过 Java 中单元测试的代码向 RabbitMQ 发送消息的示例。在这个示例中,我们使用 RabbitMQ 的 Java 客户端库来创建连接、通道,并发送消息到队列。

public class PublisherTest {
    @Test
    public void testSendMessage() throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("192.168.146.128");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        factory.setUsername("admin");
        factory.setPassword("123456");
        // 1.2.建立连接
        Connection connection = factory.newConnection();

        // 2.创建通道Channel
        Channel channel = connection.createChannel();

        // 3.创建队列
        String queueName = "simple.queue";
        channel.queueDeclare(queueName, false, false, false, null);

        // 4.发送消息
        String message = "Hello, RabbitMQ!";
        channel.basicPublish("", queueName, null, message.getBytes());
        System.out.println("发送消息成功:【" + message + "】");

        // 5.关闭通道和连接
        channel.close();
        connection.close();

    }
}

对上述代码的说明:

  1. 建立连接: 使用 ConnectionFactory 创建连接,并设置 RabbitMQ 服务器的地址、端口号、用户名和密码。

  2. 创建通道: 通过连接创建通道,大部分的 RabbitMQ 操作都是通过通道进行的。

  3. 创建队列: 使用通道创建一个名为 simple.queue 的队列,如果该队列不存在则会被创建。

  4. 发送消息: 使用 basicPublish 方法发送消息到指定的队列。在本例中,消息内容为 “Hello, RabbitMQ!”。

  5. 关闭通道和连接: 释放资源,关闭通道和连接。

然后运行这段代码:

可以发现在 RabbitMQ 的管理页面就多了一个 simple.queue 的队列,并且其中有一条未消费的消息:


点击消息的名称,然后在点击获取消息,就可以看到具体的消息内容了。

5.2 消息消费者

以下是一个通过 Java中单元测试的代码实现的 RabbitMQ 消息消费者示例。在这个示例中,我们使用 RabbitMQ 的 Java 客户端库来创建连接、通道,并从队列中接收和处理消息。

public class ConsumerTest {

    public static void main(String[] args) throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("192.168.146.128");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        factory.setUsername("admin");
        factory.setPassword("123456");
        // 1.2.建立连接
        Connection connection = factory.newConnection();

        // 2.创建通道Channel
        Channel channel = connection.createChannel();

        // 3.创建队列
        String queueName = "simple.queue";
        channel.queueDeclare(queueName, false, false, false, null);

        // 4.订阅消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 5.处理消息
                String message = new String(body);
                System.out.println("接收到消息:【" + message + "】");
            }
        });
        System.out.println("等待接收消息。。。。");
    }
}

对上述代码的说明:

  1. 建立连接: 使用 ConnectionFactory 创建连接,并设置 RabbitMQ 服务器的地址、端口号、用户名和密码。

  2. 创建通道: 通过连接创建通道,大部分的 RabbitMQ 操作都是通过通道进行的。

  3. 创建队列: 使用通道创建一个名为 simple.queue 的队列,如果该队列不存在则会被创建。

  4. 订阅消息: 使用 basicConsume 方法订阅消息。在本例中,我们使用匿名内部类继承 DefaultConsumer 类,并重写 handleDelivery 方法来处理接收到的消息。

  5. 处理消息: 在 handleDelivery 方法中,处理接收到的消息。在本例中,我们简单地打印出接收到的消息。

运行这段代码,成功获取到了 simple.queue 队列中的消息:

在 RabbitMQ 的管理页面中, simple.queue 队列中消费过的消息也被删除了:

5.3 使用 RabbitMQ 的原生 Java 客户端操作消息队列存的问题

通过上述对消息的发布和消费两个例子,发现了使用 RabbitMQ 的原生 Java 客户端操作消息队列存在一些问题,其中包括:

  1. 样板代码繁琐: 使用原生客户端需要编写很多样板代码,例如创建连接、通道,声明队列、交换机等。这使得代码显得冗长且容易出错。

  2. 异常处理繁琐: 处理连接、通道等的异常,以及消息的手动确认(acknowledgment)等操作都需要额外的处理,增加了代码的复杂性。

  3. 线程安全问题: RabbitMQ 的 Java 客户端不是线程安全的,因此需要确保在多线程环境中正确处理连接、通道的共享与释放。

  4. 不便于整合: 如果项目使用了 Spring 框架,使用原生客户端可能不够方便与 Spring 进行整合。

为了解决这些问题,可以使用 Spring AMQP(Spring 对 AMQP 协议的支持)来简化 RabbitMQ 操作。Spring AMQP 提供了更高级别的抽象,通过配置简化了连接、通道的创建,提供了更易用的消息发送和接收的方式,同时处理了很多底层细节。

使用 Spring AMQP 可以极大地简化 RabbitMQ 相关的操作,提高代码的可维护性和可读性。Spring AMQP 还提供了一些其他特性,如事务管理、消息确认机制等,使得消息队列的操作更加健壮。

关于 Spring AMQP 的使用,将在后续文章中进行展示。

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

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

相关文章

【数据库——MySQL】(15)存储过程、存储函数和事务处理习题及讲解

目录 1. 题目1.1 存储过程1.2 存储函数1.3 事务处理 2. 解答2.1 存储过程2.2 存储函数2.3 事务处理 1. 题目 1.1 存储过程 创建表 RandNumber :字段:id 自增长, data int; 创建存储过程向表中插入指定个数的随机数(1-…

UDP通信程序的详细解析

2.UDP通信程序 2.1 UDP发送数据 Java中的UDP通信 UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端…

MySql017——组合查询UNION和UNION ALL

一、UNION作用 可用UNION操作符来组合数条SQL查询。 二、UNION 使用规则 1、UNION的使用很简单。所需做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION。2、UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔&#xff…

Hive 【Hive(七)窗口函数练习】

窗口函数案例 数据准备 1)建表语句 create table order_info (order_id string, --订单iduser_id string, -- 用户iduser_name string, -- 用户姓名order_date string, -- 下单日期order_amount int -- 订单金额 ); 2)装载语句 i…

代码随想录算法训练营第五十八天 | 动态规划 part 16 | 583. 两个字符串的删除操作、72. 编辑距离

目录 583. 两个字符串的删除操作思路思路2代码 72. 编辑距离思路代码 583. 两个字符串的删除操作 Leetcode 思路 dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。递推公…

【AI视野·今日NLP 自然语言处理论文速览 第四十八期】Thu, 5 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 5 Oct 2023 Totally 50 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Retrieval meets Long Context Large Language Models Authors Peng Xu, Wei Ping, Xianchao Wu, Lawrence McA…

算法题:摆动序列

这道题是一道贪心算法题,如果前两个数是递增,则后面要递减,如果不符合则往后遍历,直到找到符合的。(完整题目附在了最后) 代码如下: class Solution(object):def wiggleMaxLength(self, nums):…

【力扣-每日一题】714. 买卖股票的最佳时机含手续费

class Solution { public:int maxProfit(vector<int>& prices, int fee) {//[i][0]-不持有 [i][1]-持有int mprices.size();vector<vector<int>> dp(m,vector<int>(2));dp[0][0]0; //初始状态dp[0][1]-prices[0];for(int i1;i<m;i){dp[i]…

光伏发电预测(LSTM、CNN_LSTM和XGBoost回归模型,Python代码)

光伏太阳能电池通过互连形成光伏模块&#xff0c;以捕捉太阳光并将太阳能转化为电能。因此&#xff0c;当光伏模块暴露在阳光下时&#xff0c;它们会产生直流电。这是目前将太阳能转化为电能的最佳方式之一。世界上许多国家已经采用了这项技术&#xff1b;然而&#xff0c;光伏…

Unity解决:安卓打包设置项目名称为中文名 packageName为英文包名

把productName改成中文名&#xff0c;然后在OtherSettings里面重写默认的包名就可以了

Android:实现手机前后摄像头预览同开

效果展示 一.概述 本博文讲解如何实现手机前后两颗摄像头同时预览并显示 我之前博文《OpenGLES&#xff1a;GLSurfaceView实现Android Camera预览》对单颗摄像头预览做过详细讲解&#xff0c;而前后双摄实现原理其实也并不复杂&#xff0c;粗糙点说就是把单摄像头预览流程写两…

抄写Linux源码(Day19:读取硬盘前的准备工作有哪些?)

回忆我们需要做的事情&#xff1a; 为了支持 shell 程序的执行&#xff0c;我们需要提供&#xff1a; 1.缺页中断(不理解为什么要这个东西&#xff0c;只是闪客说需要&#xff0c;后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的&#xff0c;所以需要这两个东…

如何在VMware workstation虚拟机中安装ensp(完美运行),解决报错40

如何在VMware workstation虚拟机中安装ensp&#xff08;完美运行&#xff09; 效果如图&#xff1a; 问题体现是ensp的路由器报错40&#xff0c;这是vbox相关的问题 在虚拟机中安装ensp的关键其实是vbox&#xff08;ensp依赖vbox&#xff09; ensp自带的vbox版本太低&#x…

想要精通算法和SQL的成长之路 - 存在重复元素

想要精通算法和SQL的成长之路 - 存在重复元素 前言一. 存在重复元素II二. 存在重复元素III2.1 基于红黑树增删改查 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 存在重复元素II 原题链接 思路&#xff1a; 我们用HashSet存储元素&#xff0c;做到去重的效果。同时存储…

防火墙的相关技术

安全技术&#xff1a;&#xff08;市场上常见的防御&#xff09; 1.入侵检测机制 阻断&#xff0c;量化&#xff0c;定位来自内外的网络的威胁情况 提供报警和事后监督。类似于监控。 2.入侵防御 以透明模式工作&#xff0c;分析数据包的内容&#xff0c;一切进入本机的内容…

windows 任务计划自动提交 笔记到github 、gitee

一、必须有个git仓库托管到git上。 这个就不用说了&#xff0c;自己在github或者码云上新建一个仓库就行了。 二、创建自动提交脚本 这个bat脚本是在windows环境下使用的。 注意&#xff1a;windows定时任务下 调用自动提交git前&#xff0c;必须先进入该git仓库目录&#x…

Windows11 安全中心页面不可用问题(无法打开病毒和威胁防护)解决方案汇总(图文介绍版)

本文目录 Windows版本与报错信息问题详细图片&#xff1a; 解决方案:方案一、管理员权限&#xff08;若你确定你的电脑只有你一个账户&#xff0c;则此教程无效&#xff0c;若你也不清楚&#xff0c;请阅读后再做打算&#xff09;方案二、修改注册表(常用方案)方案三、进入开发…

服务器or虚拟机安装SSH和虚拟机or服务器设置远程服务权限

第一步 服务器/虚拟机安装SSH工具,这是外部SSH终端连接服务器/虚拟机的第一步! sudo apt update && sudo apt upgrade#更新apt sudo apt install openssh-server#安装SSH工具 service ssh status#查看SSh运行状态 sudo systemctl enable --now ssh#运行SSH工具第二步…

基于SpringBoot的信息化在线教学平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 教师信息管理 学生成绩管理 留言板 学生注册管理 留言反馈 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已…

各平台更新根证书

windows7 windows7根证书更新 https://support.microsoft.com/en-us/topic/support-for-urgent-trusted-root-updates-for-windows-root-certificate-program-in-windows-a4ac4d6c-7c62-3b6e-dfd2-377982bf3ea5 Linux 查看证书 ls -l /etc/ssl/certs/更新根证书 update-ca…