RocketMQ 安装与入门

news2024/11/26 7:52:25

文章目录

  • 简介
  • 下载
    • 下载目录地址
  • 安装
    • 部署环境要求
    • 下载二进制包解压即可
    • 启动 NameServer
  • 启动Broker+Proxy
    • 单组节点单副本模式启动
  • 使用Java客户端发布订阅消息
    • 1. 创建主题 topic
    • 2. 创建Java工程使用Maven引入Java SDK包
    • 生产者代码 ProducerDemo
    • 消费者代码 ConsumerDemo
  • RocketMQ 的一些基本概念
    • NameServer 名字服务器
    • Broker 代理服务器(直译为经纪人)
    • Proxy (直译为代理)
    • Topic 主题
    • MessageType 消息类型
    • MessageQueue 消息队列
    • 消息位点(Offset)
    • 消费位点(ConsumerOffset)
    • Message 消息
    • MessageView 消息视图
    • MessageTag 消息标签
    • MessageKey 消息索引(或者说消息的关键字)
    • 订阅关系(Subscription)
  • RocketMQ 领域模型
  • 远程通信方式
    • 直接远程调用
    • 中间件异步调用
  • 消息的传输模型
    • 点对点
    • 发布订阅

简介

Apache RocketMQ 自诞生以来,因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经阿里十余年的大规模场景打磨,RocketMQ 已经成为业内共识的金融级可靠业务消息首选方案,被广泛应用于互联网、大数据、移动互联网、物联网等领域的业务场景。

下载

RocketMQ 的安装包分为两种

  • 二进制包:二进制包是已经编译完成后可以直接运行的
  • 源码包:源码包是需要编译后运行的

下载目录地址

https://rocketmq.apache.org/zh/download/
在这里插入图片描述
当前最新的版本为 5.1.3

我们通过二进制下载来安装。

安装

部署环境要求

64位操作系统,推荐 Linux/Unix/macOS
64位 JDK 1.8+

我们的示例在linux CentOS 发行版下安装

下载二进制包解压即可

解压后文件夹名字可能太长,可以修改一下,如我们修改为:rocketmq-5.1.3

如果是源码包,则需要执行如下操作

$ unzip rocketmq-all-5.1.3-source-release.zip
$ cd rocketmq-all-5.1.3-source-release/
$ mvn -Prelease-all -DskipTests -Dspotbugs.skip=true clean install -U
$ cd distribution/target/rocketmq-5.1.3/rocketmq-5.1.3

启动 NameServer

### 启动namesrv
$ nohup sh bin/mqnamesrv &
 
### 验证namesrv是否启动成功
$ tail -f ~/logs/rocketmqlogs/namesrv.log

日志打印出如下字样则说明启动成功

..... The Name Server boot success.  .......

在这里插入图片描述

NameServer 的默认端口为9876,IP 为部署服务器IP地址

启动Broker+Proxy

在 5.0 版本中 Proxy 和 Broker 根据实际诉求可以分为 Local 模式和 Cluster 模式。官网推荐模式为 Local 模式。

  • 在 Local 模式下,Broker 和 Proxy 是同进程部署,只是在原有 Broker 的配置基础上新增 Proxy 的简易配置就可以运行。
  • 在 Cluster 模式下,Broker 和 Proxy 分别部署,即在原有的集群基础上,额外再部署 Proxy 即可。

这两种模式,又对应了多种可部署的组合方式,这个我们后续章再说。我们当前先使用单组节点单副本模式启动。

单组节点单副本模式启动

### 先启动broker  
## -n 后面是 nameServe 的地址,由于我们的broker和nameServer在同一台服务器上执行,所以使用localhost
$ nohup sh bin/mqbroker -n localhost:9876 --enable-proxy &

### 验证broker是否启动成功, 比如, broker的ip是192.168.1.2 然后名字是broker-a
$ tail -f ~/logs/rocketmqlogs/proxy.log 

#---- 日志中出现如下内容 broker + proxy 即启动成功。
The broker[broker-a,192.169.1.2:10911] boot success...

broker 默认端口为10911,proxy 默认端口为8081

启动后 在 ~/logs/rocketmqlogs 目录下还可以看见 broker.log、namesrv.log、proxy.log

使用Java客户端发布订阅消息

在使用本示例时,很多概念都还没有讲解,对于初次接触的人来说有些困难,这不要紧,直接无脑按顺序操作即可,先体验结果,后续将逐步详细讲解这些内容。

1. 创建主题 topic

5.0版本下创建主题操作,官网推荐使用 mqadmin 命令工具来创建。

$ sh bin/mqadmin updatetopic -n localhost:9876 -t TestTopic -c DefaultCluster

在这里插入图片描述

-n 表示 nameserver 的地址,-t 表示主题名称(用于唯一标识主题),-c 集群名称,RocketMQ 默认集群名称就是 DefaultCluster

2. 创建Java工程使用Maven引入Java SDK包

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client-java</artifactId>
    <version>${rocketmq-client-java-version}</version>
</dependency> 

${rocketmq-client-java-version} 使用最新的版本即可。在maven 仓库中搜索即可。本文编写时的最新版本为:5.0.5。

生产者代码 ProducerDemo

import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientConfigurationBuilder;
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;

import java.io.IOException;

public class ProducerDemo {

    public static void main(String[] args) throws ClientException, InterruptedException {
        // 接入点地址,需要设置成Proxy的地址和端口列表,一般是xxx:8081;xxx:8081。
        String endpoint = "192.168.1.1:8081";
        // 消息发送的目标Topic名称,需要提前创建。
        String topic = "TestTopic";
        ClientServiceProvider provider = ClientServiceProvider.loadService();
        ClientConfigurationBuilder builder = ClientConfiguration.newBuilder().setEndpoints(endpoint);
        ClientConfiguration configuration = builder.build();
        // 初始化Producer时需要设置通信配置以及预绑定的Topic。
        Producer producer = provider.newProducerBuilder()
                .setTopics(topic)
                .setClientConfiguration(configuration)
                .build();

        for(int i = 0; i < 1000;i++) {
            // 普通消息发送。
            Message message = provider.newMessageBuilder()
                    .setTopic(topic)
                    // 设置消息索引键,可根据关键字精确查找某条消息。
                    .setKeys("messageKey")
                    // 设置消息Tag,用于消费端根据指定Tag过滤消息。
                    .setTag("messageTag")
                    // 消息体。
                    .setBody(("messageBody" + i).getBytes())
                    .build();
            try {
                // 发送消息,需要关注发送结果,并捕获失败等异常。
                SendReceipt sendReceipt = producer.send(message);
                System.out.println("Send message successfully, messageId=" + sendReceipt.getMessageId());
            } catch (ClientException e) {
                System.out.println("Failed to send message");
            }
            // 等待10秒再次发送
            Thread.sleep(10000);
        }


        // 发送完,关闭
        try {
            producer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

控制台会打印类似: Send message successfully, messageId=01005056C0000846DC04DFC51400000000 的结果

消费者代码 ConsumerDemo

import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.consumer.ConsumeResult;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.FilterExpressionType;
import org.apache.rocketmq.client.apis.consumer.PushConsumer;

import java.nio.ByteBuffer;
import java.util.Collections;

public class ConsumerDemo {

    public static void main(String[] args) throws InterruptedException, ClientException {

        final ClientServiceProvider provider = ClientServiceProvider.loadService();
        // 接入点地址,需要设置成Proxy的地址和端口列表,一般是xxx:8081;xxx:8081。
        String endpoints = "192.168.1.1:8081";
        ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
                .setEndpoints(endpoints)
                .build();
        // 订阅消息的过滤规则,表示订阅所有Tag的消息。
        String tag = "*";
        FilterExpression filterExpression = new FilterExpression(tag, FilterExpressionType.TAG);
        // 为消费者指定所属的消费者分组。
        String consumerGroup = "YourConsumerGroup";
        // 指定需要订阅哪个目标Topic,Topic需要提前创建。
        String topic = "TestTopic";
        // 初始化PushConsumer,需要绑定消费者分组ConsumerGroup、通信参数以及订阅关系。
        PushConsumer pushConsumer = provider.newPushConsumerBuilder()
                .setClientConfiguration(clientConfiguration)
                // 设置消费者分组。
                .setConsumerGroup(consumerGroup)
                // 设置预绑定的订阅关系。
                .setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
                // 设置消费监听器。
                .setMessageListener(messageView -> {
                    System.out.println(messageView);
                    ByteBuffer rs = messageView.getBody();
                    byte[] rsByte = new byte[rs.limit()];
                    rs.get(rsByte);
                    System.out.println("Message body:" + new String(rsByte));
                    // 处理消息并返回消费结果。
                    System.out.println("Consume message successfully, messageId=" + messageView.getMessageId());;
                    return ConsumeResult.SUCCESS;
                })
                .build();

        // 如果不需要再使用 PushConsumer,可关闭该实例。
        // 不调用close 该程序不会关闭
        // pushConsumer.close(); 

    }

}

消费者有3中类型,这里的消费者我们使用了 PushConsumer 。后续我们会详解。打印结果如下:

MessageViewImpl{messageId=01005056C00008017404E0A8AD00000000, topic=TestTopic, bornHost=xxx, bornTimestamp=1691291309533, endpoints=ipv4:192.168.1.1:8081, deliveryAttempt=1, tag=messageTag, keys=[messageKey], messageGroup=null, deliveryTimestamp=null, properties={}}
Message body:messageBody0
Consume message successfully, messageId=01005056C00008017404E0A8AD00000000

RocketMQ 的一些基本概念

NameServer 名字服务器

NameServer是一个简单的 Topic 路由注册中心,支持 Topic、Broker 的动态注册与发现。

主要包括两个功能:

  • 管理Broker,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;
  • 路由信息管理,每个NameServer将保存关于 Broker 集群的整个路由信息和用于客户端查询的队列信息。Producer和Consumer通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。

NameServer通常会有多个实例部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,客户端仍然可以向其它NameServer获取路由信息。

Broker 代理服务器(直译为经纪人)

Broker主要负责消息的存储、投递和查询以及服务高可用保证。

NameServer几乎无状态节点,因此可集群部署,节点之间无任何信息同步。Broker部署相对复杂。

Proxy (直译为代理)

在官网5.0的文档中NameServer、Broker、Proxy都没有做说明,以上关于NameServer、Broker的说明是4.x的文档说明,(或许是5.0版本2022.9.22才发布,文档没有跟上吧)。

由于没有官方说明,这里只能大胆猜测一下 Proxy 的作用,应该是替代NameServer 和 broker 的一些功能,按照我们示例的写法,以及英文直译它的作用应该是代理网络连接、以及集群下的寻址等功能等。

Topic 主题

RocketMQ 中消息传输和存储的顶层容器,用于标识同一类业务逻辑的消息。主题通过TopicName来做唯一标识和区分。一般我们定义不同的主题来区分不同的业务逻辑。

MessageType 消息类型

RocketMQ 中按照消息传输特性的不同而定义的分类,用于类型管理和安全校验。 RocketMQ 支持的消息类型有普通消息、顺序消息、事务消息和定时/延时消息。

从5.0版本开始,支持强制校验消息类型,即每个主题Topic只允许发送一种消息类型的消息,这样可以更好的运维和管理生产系统,避免混乱。但同时保证向下兼容4.x版本行为,强制校验功能默认关闭,推荐通过服务端参数 enableTopicMessageTypeCheck 手动开启校验。

MessageQueue 消息队列

队列是 RocketMQ 中消息存储和传输的实际容器,也是消息的最小存储单元。通过QueueId来做唯一标识和区分。RocketMQ 的所有主题都是由多个队列组成。任意一个消息队列在逻辑上都是无限存储,即消息位点会从0到Long.MAX无限增加。

消息位点(Offset)

消息是按到达服务端的先后顺序存储在指定主题的多个队列中,每条消息在队列中都有一个唯一的Long类型坐标,这个坐标被定义为消息位点。

队列中最早一条消息的位点为最小消息位点(MinOffset);最新一条消息的位点为最大消息位点(MaxOffset)。

消费位点(ConsumerOffset)

RocketMQ 通过消费位点管理消息的消费进度。每条消息被某个消费者消费完成后不会立即在队列中删除,RocketMQ 会基于每个消费者分组维护一份消费记录,该记录指定消费者分组消费某一个队列时,消费过的最新一条消息的位点,即消费位点。

Message 消息

消息是 RocketMQ 中的最小数据传输单元。生产者将业务数据的负载和拓展属性包装成消息发送到服务端,服务端按照相关语义将消息投递到消费端进行消费。

MessageView 消息视图

消息视图是 RocketMQ 面向开发视角提供的一种消息只读接口。通过消息视图可以读取消息内部的多个属性和负载信息,但是不能对消息本身做任何修改。

MessageTag 消息标签

消息标签是 RocketMQ 提供的细粒度消息分类属性,可以在主题层级之下做消息类型的细分。消费者通过订阅特定的标签来实现细粒度过滤。比如:我们一般将标签设计为业务操作级,如果消息都是下单成功的消息,那么他们的标签为“orderSuccess”,相同标签的消息,调用相同的业务逻辑。这样我们可以减少要创建的主题的个数。

MessageKey 消息索引(或者说消息的关键字)

通过设置的消息索引可以快速查找到对应的消息内容。一般 MessageKey 我们会设计为当前消息的内容的唯一关键字,比如订单号、订单id、唯一标识等,这样可以方便我们更精确的查找的与某个业务有关的消息。

订阅关系(Subscription)

订阅关系是 RocketMQ 系统中消费者获取消息、处理消息的规则和状态配置。

RocketMQ 领域模型

在这里插入图片描述
如图,RocketMQ 的消息生命周期主要分为三部分

  • 消息生产:生产者(Producer)
  • 消息存储:主题(Topic)
  • 消息消费:消费者(consumer)

主题由多个队列组成,队列示消息的传输和存储的实际容器,RocketMQ 通过无限流式队列来存储消息,消息的顺序性也有队列来保证。

消息是 RocketMQ 的最小传输单元。消息一旦存储不可改变(不可变性),且 RocketMQ 接受到消息会默认持久化到服务端存储文件。

远程通信方式

直接远程调用

在我们日常的应用开发中,如果不使用中间件异步调用,那么基本上都是通过 RPC 或 HTTP 等直接调用相应接口进行应用间的通信,这就是直接远程调用。比如下图中的订单系统调用库存系统扣减库存的操作:

在这里插入图片描述

这种调用方式,订单系统需要等待库存系统正确处理完成,并返回信息之后,订单系统确认无误,然后反馈用户。

就算在整个过程其实参数、流程、事务控制逻辑上都完全没问题的前提下,由于 request 、response 是远程通信,比如出现网络波动、断联,导致 request 或 response 超时或丢包,也会导致请求失败

如果库存系统有内容需要重新部署启动,这期间整个请求无法使用,两个系统间的耦合度高。而且我们此处只是最基本的两个应用,一般的大型应用可能有很多个子系统间需要相互调用,这样带来的耦合度、维护成本等就更高了。

中间件异步调用

在这里插入图片描述

异步调用方式所有的应用都只跟中间件进行通信,这样结构简单,每个应用之间都没有直接关联,耦合度低,各个应用可以独立启停和部署等,相互并不影响。当然 MQ 的作用远不于此。

消息的传输模型

点对点

在这里插入图片描述
点对点模型也叫队列模型,具有如下特点:

  • 消费匿名:消息上下游沟通的唯一的身份就是队列,下游消费者从队列获取消息无法申明独立身份。
  • 一对一通信:基于消费匿名特点,下游消费者即使有多个,但都没有自己独立的身份,因此共享队列中的消息,每一条消息都只会被唯一一个消费者处理。因此点对点模型只能实现一对一通信。

发布订阅

在这里插入图片描述
发布订阅模型具有如下特点:

  • 消费独立:相比队列模型的匿名消费方式,发布订阅模型中消费方都会具备的身份,一般叫做订阅组(订阅关系),不同订阅组之间相互独立不会相互影响。
  • 一对多通信:基于独立身份的设计,同一个主题内的消息可以被多个订阅组处理,每个订阅组都可以拿到全量消息。因此发布订阅模型可以实现一对多通信。

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

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

相关文章

SPSS教程:如何绘制带误差的折线图

SPSS教程&#xff1a;如何绘制带误差的折线图 1、问题与数据 研究者想研究45-65岁健康男性中&#xff0c;静坐时长和血胆固醇水平的关系&#xff0c;故招募100名研究对象询问其每天静坐时长&#xff08;time&#xff09;&#xff0c;并检测其血液中胆固醇水平&#xff08;cho…

VSCode下载、安装及配置、调试的一些过程理解

第一步先下载了vscode&#xff0c;官方地址为&#xff1a;https://code.visualstudio.com/Download 第二步安装vscode&#xff0c;安装环境是win10&#xff0c;安装基本上就是一步步默认即可。 第三步汉化vscode&#xff0c;这一步就是去扩展插件里面下载一个中文插件即可&am…

安全测试-django防御安全策略

django安全性 django针对安全方面有一些处理&#xff0c;学习如何进行处理设置&#xff0c;也有利于学习安全测试知识。 CSRF 跨站点请求伪造&#xff08;Cross-Site Request Forgery&#xff0c;CSRF&#xff09;是一种网络攻击方式&#xff0c;攻击者欺骗用户在自己访问的网…

【实验二】基尔霍夫定律和叠加定理

【实验内容】 【实验报告】 表一线路图 表二线路图 线路1 线路2 同时作用 【得分】

两台电脑共享文件设置

步骤一&#xff1a;确保网络连接正常&#xff0c;可网线直连。 两台电脑IP设置&#xff0c;例&#xff1a; 步骤二&#xff1a;启用共享功能。 1.在【控制面板】中选择【网络和Internet】&#xff1b; 2.点击【网络和共享中心】&#xff0c;在左侧导航栏中&#xff0c;点击【…

政府网站之守护:如何确保信息真实与透明,避免政治风险?

在数字化时代&#xff0c;政府网站已经成为公众获取官方信息和政府政策的主要途径。确保这些信息的真实性、透明性和及时性是维护 政府公信力的关键。特别是在涉及落马官员、政治敏感信息等内容时&#xff0c;更需要加强审查与管理&#xff0c;避免带来不必要的政治风险。 那…

视频云存储/安防监控/AI视频智能分析网关V3:工服检测功能详解

在一些工地、后厨、化工、电力等特定的场景中&#xff0c;工服的穿戴是必不可少的。这不仅是安全制度的要求&#xff0c;更能降低工作风险、提高工作效率。TSINGSEE青犀AI 边缘计算网关硬件 —— 智能分析网关可以通过实时监测和识别工人的工装穿戴情况&#xff0c;确保他们符合…

DBeaver 23.1.5 发布

导读DBeaver 是一个免费开源的通用数据库工具&#xff0c;适用于开发人员和数据库管理员。DBeaver 23.1.5 现已发布&#xff0c;更新内容如下. Data editor 重新设计了词典查看器面板 UI 空间数据类型&#xff1a;曲线几何线性化已修复 数据保存时结果选项卡关闭的问题已解决…

springboot实战(三)之多环境部署配置文件生效方式

环境&#xff1a; jdk&#xff1a;1.8 springboot版本&#xff1a;2.7.15 配置&#xff1a; 1.新建yml文件 在resources包中创建application-dev.yml、application-testing.yml两个yml文件 2.配置 在application.yml进行配置生效文件 3.注意事项 新建yml的名称必须以&qu…

GBDT,XGBoost算法理解

pyspark实现GBDT 参考资料&#xff1a; datawhalechina/ensemble-learning (github.com)

Stable Diffusion 从入门到企业级应用0401

一、概述 本章是《Stable Diffusion 从入门到企业级实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》第01节&#xff0c; 利用Stable Diffusion ControlNet Inpaint模型精准控制图像生成。本部分内容&#xff0c;位于整个Stable Diffusion生…

java 多个list取交集

java 多个list集合根据某个字段取出交集 模拟多个list集合&#xff0c;如下图 如果只有一个集合那么交集就是当前集合&#xff0c;如果有多个集合&#xff0c;那么第一个集合当做目标集合&#xff0c;在通过目标集合去和剩下的集合比较&#xff0c;取出相同的值&#xff0c;运…

CAR-T商品化的第一步

1、CAR-T细胞的体外扩增能力 CAR-T细胞疗法需要先从患者体内获得T淋巴细胞&#xff0c;然后通过体外转基因技术 transduce CAR靶向结构域。这一过程需要在细胞培养体系中得到充分的扩增&#xff0c;以获得足够的治疗CAR-T细胞数量。因此&#xff0c;CAR-T细胞的体外扩增能力直…

邮箱授权码的获取(以qq邮箱为例)

第一步&#xff0c;登录你需要授权的邮箱&#xff08;如登录qq邮箱主页面&#xff09; 第二步&#xff0c;点击设置&#xff0c;选择账号 往下拉&#xff0c;找到POP3等服务中的服务状态&#xff0c;点击开启服务 在通过认证后得到授权码 在一些第三方登录中我们通过这个授权码…

想跳槽?先别急!这5个问题搞懂再离职也不迟!

创建坐席组的功能模块&#xff0c;如何进行测试用例设计&#xff1f; 解答&#xff1a; 功能测试&#xff0c;使用等价类划分法去分析创建坐席的每个输入项的有效及无效类&#xff0c;同步考虑边界值去设计对应的测试用例&#xff1a; 先进行冒烟测试&#xff0c;正常创建坐席…

如何让视频小于50m?最新视频压缩技巧分享

在我们的日常生活中&#xff0c;视频文件经常占据较大的存储空间&#xff0c;给我们存储和传输带来了困扰&#xff0c;那么如何将视频文件压缩至50m以下呢&#xff1f;下面就为大家分享三个实用的方法&#xff0c;轻松解决视频过大问题。 方法一&#xff1a;调整视频分辨率 视…

用小额贷款产品微粒贷借钱靠谱方便,应急周转值得一试

平时资金周转应急&#xff0c;除了找亲戚朋友之外&#xff0c;要说用着放心靠谱的渠道&#xff0c;小编是相当认可微粒贷的。微粒贷作为微众银行旗下的小额贷款&#xff0c;正规可靠&#xff0c;值得信赖。接下来做个详细介绍&#xff0c;平时有资金应急周转需要的小伙伴&#…

掌握Linkedin营销小技巧,再也不愁客户

众所周知&#xff0c;Linkedin是发展业务、拓展人脉的好地方&#xff0c;在过去的一年里&#xff0c;93%的B2B营销人员最常使用该平台来有机分发内容。Linkedin也因为能产生较好的营销效果而成为跨境业务开发的选择平台。 有些企业可以使用Linkedin向潜在用户进行营销和接触&a…

如何在`Pycharm`中配置基于WSL的`Python Interpreters`,以及配置基于WSL的`Terminal`

文章目录 一、创建pycharm用户并授予sudo权限0. 启动WSL下的CentOS1. 创建pycharm用户并授予sudo权限2. 设置pycharm用户为wsl启动Linux的默认用户3. 重启并重新登录wsl下的CentOS4. 验证pycharm用户的sudo权限 二、创建基于WSL的Python Interpreter1. 添加基于WSL的Python Int…

Matlab——二维绘图(最为详细,附上相关实例)

为了帮助各位同学备战数学建模和学习Matlab的使用&#xff0c;今天我们来聊一聊 Matlab 中的绘图技巧吧&#xff01;对于 Matlab 这样的科学计算软件来说&#xff0c;绘图是非常重要的一项功能。在数据处理和分析时&#xff0c;良好的绘图技巧能够更直观地呈现数据&#xff0c;…