Asp .Net Core 实现微服务:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现

什么是 Ocelot ?

Ocelot是一个开源的ASP.NET Core微服务网关,它提供了API网关所需的所有功能,如路由、认证、限流、监控等。

Ocelot是一个简单、灵活且功能强大的API网关,它可以与现有的服务集成,并帮助您保护、监控和扩展您的微服务。

以下是Ocelot的一些主要功能:

  1. 路由管理:Ocelot允许您定义路由规则,将请求路由到正确的微服务。
  2. 认证和授权:Ocelot支持多种认证机制,如JWT、OAuth等,并允许您定义访问控制策略,确保只有授权的用户才能访问特定的API。
  3. 限流和速率限制:Ocelot提供了一些内置的限流和速率限制功能,以确保您的服务不会受到过度的请求压力。
  4. 监控和日志:Ocelot可以收集和显示各种度量指标,帮助您了解您的服务的性能和行为。此外,它还可以将日志记录到各种日志源,以便您进行分析和故障排除。
  5. 集成:Ocelot可以与现有的服务集成,包括Kubernetes、Consul等。
  6. 易于扩展:Ocelot的设计使其易于扩展,您可以编写自己的中间件来处理特定的逻辑,例如修改请求或响应、添加自定义的认证机制等。
  7. 可扩展的配置:Ocelot使用JSON配置文件进行配置,这意味着您可以轻松地根据需要进行配置更改,而无需重新编译代码。

总之,Ocelot是一个功能强大且易于使用的API网关,可以帮助您保护、监控和扩展您的微服务。

官网:Ocelot 23.4 Documentation — Ocelot Gateway 23.4 documentation

什么是 Nacos ?

Nacos是一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它是Dynamic Naming and Configuration Service的首字母简称。Nacos提供了一组简单易用的特性集,包括动态服务发现、服务配置、服务元数据及流量管理等功能,帮助用户快速实现微服务的发现、配置和管理。Nacos还支持多种服务注册方式和服务发现方式,如DNS、RPC、原生SDK和OpenAPI等。

此外,Nacos致力于提供更敏捷和容易的微服务平台构建、交付和管理。它是构建以“服务”为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施,能够支持动态DNS服务权重路由和动态DNS服务等特性。

官网:Nacos 快速开始 | Nacos 官网

什么是 Swagger ?

Swagger是一种规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。它是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许API始终保持同步。

此外,Swagger还提供了一个文档工具,可自动生成Web服务的API文档,使开发人员能够更轻松地理解和使用API。它还提供了一个测试工具,可以模拟对Web服务的API请求并验证响应。

什么是 Cors ?

CORS(跨来源资源共享,Cross-Origin Resource Sharing)是一种机制,允许Web应用程序在未经服务器明确许可的情况下,通过浏览器向服务器发送跨域请求。CORS是一种W3C规范,旨在解决Web应用程序中的跨域问题,以促进Web应用程序的安全性和可扩展性。

在Web应用程序中,浏览器会遵循同源策略(Same-Origin Policy),即默认只允许来自同一域的页面之间进行通信。然而,随着Web应用程序的发展,越来越多的应用程序需要与不同域的资源进行交互,例如使用第三方API或进行跨域请求。为了解决这个问题,CORS规范允许服务器通过设置适当的HTTP标头来明确地允许跨域请求。

当浏览器向服务器发送跨域请求时,服务器可以在响应头中包含一个Access-Control-Allow-Origin标头,指定允许哪些源进行跨域请求。浏览器会检查这个标头,如果允许的源与请求的源匹配,则允许跨域请求。此外,CORS规范还定义了其他一些相关的标头,如Access-Control-Allow-MethodsAccess-Control-Allow-Headers等,以进一步控制跨域请求的行为。

通过使用CORS机制,Web应用程序可以更安全、更有效地进行跨域请求,提高了应用程序的可扩展性和用户体验。

Asp .Net Core 集成 Ocelot

要在ASP.NET Core中集成Ocelot,您可以按照以下步骤进行操作:

  1. 安装Ocelot NuGet包:
    在您的ASP.NET Core项目中,打开终端或NuGet包管理器控制台,并运行以下命令来安装Ocelot的NuGet包:
dotnet add package Ocelot
  1. 添加Ocelot配置文件:
{"Routes": [ //这里注意一下版本(旧版本用ReRoutes){"DownstreamPathTemplate": "/api/{controller}", //下游路径模板"DownstreamScheme": "http", //下游方案//"DownstreamHostAndPorts": [//  {//    "Host": "localhost",//    "Port": "5014"//  }//], //下游主机和端口"UpstreamPathTemplate": "/api/product/{controller}", //上游路径模板"UpstreamHttpMethod": [], //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法"ServiceName": "api-product-service", //请求服务名称"LoadBalancerOptions": {"Type": "LeastConnection" //负载均衡算法:目前 Ocelot 有RoundRobin 和LeastConnection算法}}],"GlobalConfiguration": {"BaseUrl": "http://localhost:5015", //进行标头查找和替换以及某些管理配置"ServiceDiscoveryProvider": {"Type": "Nacos"}},"Nacos": {"ServerAddresses": [ "http://127.0.0.1:8848" ], //服务地址"UserName": "nacos",  //用户名"Password": "nacos", //密码"ServiceName": "api-gateway", //服务名称//"Namespace": "",  //命名空间//"GroupName": "DEFAULT_GROUP" //组名,//"ClusterName": "DEFAULT", // 集群名称"ListenInterval": 1000,   //监听"RegisterEnabled": true, // 注册是否启动"InstanceEnabled": true   //实例是否启动},"Url": "http://*:5015"
}
  1. 配置Ocelot服务:
builder.Services.AddOcelot();

Configure方法中配置请求管道并添加Ocelot中间件:

app.UseOcelot().Wait();

网关集成 Nacos

要将Naocs集成Ocelot到中,您可以按照以下步骤进行操作:

  1. 下载Ocelot.Provider.Nacos 源码,导入Ocelot.Provider.Nacos 项目

    github:https://github.com/softlgl/Ocelot.Provider.Nacos

    修改Ocelot.Provider.Nacos 源码,在Ocelot 22版本中 IServiceDiscoveryProvider接口中的Get方法变成了GetAsync

    升级各Nuget包

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Ocelot.ServiceDiscovery.Providers;
    using Ocelot.Values;
    using Nacos.V2;
    using Microsoft.Extensions.Options;
    using Ocelot.Provider.Nacos.NacosClient.V2;
    using NacosConstants = Nacos.V2.Common.Constants;namespace Ocelot.Provider.Nacos
    {public class Nacos : IServiceDiscoveryProvider{private readonly INacosNamingService _client;private readonly string _serviceName;private readonly string _groupName;private readonly List<string> _clusters;public Nacos(string serviceName, INacosNamingService client, IOptions<NacosAspNetOptions> options){_serviceName = serviceName;_client = client;_groupName = string.IsNullOrWhiteSpace(options.Value.GroupName) ? NacosConstants.DEFAULT_GROUP : options.Value.GroupName;_clusters = (string.IsNullOrWhiteSpace(options.Value.ClusterName) ? NacosConstants.DEFAULT_CLUSTER_NAME : options.Value.ClusterName).Split(",").ToList();}public async  Task<List<Service>> GetAsync(){var services = new List<Service>();var instances = await _client.GetAllInstances(_serviceName, _groupName, _clusters);if (instances != null && instances.Any()){services.AddRange(instances.Select(i => new Service(i.InstanceId, new ServiceHostAndPort(i.Ip, i.Port), "", "", new List<string>())));}return await Task.FromResult(services);}}
    }
    
  2. 配置Ocelot:
    在Ocelot的配置中,您需要指定Nacos作为服务发现和配置的提供者。在Ocelot的配置文件(例如appsettings.json)中,添加以下内容:

{"GlobalConfiguration": {"BaseUrl": "http://localhost:5015", //进行标头查找和替换以及某些管理配置"ServiceDiscoveryProvider": {"Type": "Nacos" //指定Nacos}},"Nacos": {"ServerAddresses": [ "http://127.0.0.1:8848" ], //服务地址"UserName": "nacos",  //用户名"Password": "nacos", //密码"ServiceName": "api-gateway", //服务名称//"Namespace": "",  //命名空间//"GroupName": "DEFAULT_GROUP" //组名,//"ClusterName": "DEFAULT", // 集群名称"ListenInterval": 1000,   //监听"RegisterEnabled": true, // 注册是否启动"InstanceEnabled": true   //实例是否启动}
}
  1. 启动Ocelot:
    在您的ASP.NET Core应用程序中启动Ocelot。您可以在Startup.cs文件中添加以下代码:
builder.Services.AddOcelot().AddNacosDiscovery("Nacos");

下游配置 Nacos

  1. 安装必要的NuGet包:

    在Visual Studio中打开你的项目,通过NuGet包管理器安装Nacos.AspNetCore包。可以通过NuGet包管理器控制台运行以下命令来安装:

Install-Package Nacos.AspNetCore
  1. 配置Nacos客户端:

    appsettings.json文件中添加Nacos服务的配置信息,例如服务器地址、端口、命名空间等信息。示例配置如下:

{"Nacos": {"ServerAddresses": [ "http://127.0.0.1:8848" ],//命名空间GUID,public默认没有//"Namesapce": "","UserName": "nacos","Password": "nacos",// 配置中心//"Listeners": [//  {//    "Group": "dev",//    "DataId": "api-product-service",//    "Optional": false//  }//],// 服务发现"Ip": "localhost", // Nacos 注册时如果没有指定IP,那么就按照本机的IPv4 Address"Port": "5014", //端口"ServiceName": "api-product-service" // 服务名称//"GroupName": "",// 权重//"Weight": 100}
}
  1. 配置依赖注入:

    如果你需要在你的应用程序中使用Nacos服务,可以在Startup.csConfigureServices方法中注册Nacos服务的依赖注入。示例如下:

builder.Services.AddNacosAspNet(builder.Configuration,"Nacos");

配置跨域(Cors)

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MCode.Common.Extensions.Cors
{public static class CorsServiceExtensions{private readonly static string PolicyName = "MCodeCors";/// <summary>/// 添加跨域/// </summary>/// <param name="services">服务集合</param>/// <returns></returns>public static IServiceCollection AddMCodeCors(this IServiceCollection services){if (services == null) throw new ArgumentNullException(nameof(services));//origin microsoft.aspnetcore.cors      return services.AddCors(options =>{options.AddPolicy(PolicyName, policy =>{policy.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();});});}/// <summary>/// 使用跨域/// </summary>/// <param name="app">应用程序建造者</param>/// <returns></returns>public static IApplicationBuilder UseMCodeCors(this IApplicationBuilder app){return app.UseCors(PolicyName);}}
}

网关和微服务中配置Swagger

SwaggerOptions

using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MCode.Common.Extensions.Swagger
{/// <summary>/// Swagger配置/// </summary>public class SwaggerOptions{/// <summary>/// 服务名称/// </summary>public string ServiceName { get; set; }/// <summary>/// API信息/// </summary>public OpenApiInfo ApiInfo { get; set; }/// <summary>/// Xml注释文件/// </summary>public string[] XmlCommentFiles { get; set; }/// <summary>/// 构造函数/// </summary>/// <param name="serviceName">服务名称</param>/// <param name="apiInfo">API信息</param>/// <param name="xmlCommentFiles">Xml注释文件</param>public SwaggerOptions(string serviceName, OpenApiInfo apiInfo, string[] xmlCommentFiles = null){ServiceName = !string.IsNullOrWhiteSpace(serviceName) ? serviceName : throw new ArgumentException("serviceName parameter not config.");ApiInfo = apiInfo;XmlCommentFiles = xmlCommentFiles;}}
}

SwaggerEndPoint

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MCode.Common.Extensions.Swagger
{/// <summary>/// Swagger终端/// </summary>public class SwaggerEndPoint{/// <summary>/// 名称/// </summary>public string Name { get; set; }/// <summary>/// 地址/// </summary>public string Url { get; set; }}
}

OcelotSwaggerOptions

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace MCode.Common.Extensions.Swagger
{/// <summary>/// 网关Swagger配置/// </summary>public class OcelotSwaggerOptions{public List<SwaggerEndPoint> SwaggerEndPoints { get; set; }}
}

SwaggerServiceExtensions

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;namespace MCode.Common.Extensions.Swagger
{/// <summary>/// Swagger 服务扩展/// </summary>public static class SwaggerServiceExtensions{/// <summary>/// 添加 Swagger 服务/// </summary>/// <param name="services"></param>/// <param name="swaggerOptions"></param>/// <returns></returns>public static IServiceCollection AddMCodeSwagger(this IServiceCollection services, SwaggerOptions swaggerOptions){services.AddSingleton(swaggerOptions);SwaggerGenServiceCollectionExtensions.AddSwaggerGen(services, c =>{c.SwaggerDoc(swaggerOptions.ServiceName, swaggerOptions.ApiInfo);if (swaggerOptions.XmlCommentFiles != null){foreach (string xmlCommentFile in swaggerOptions.XmlCommentFiles){string str = Path.Combine(AppContext.BaseDirectory, xmlCommentFile);if (File.Exists(str)) c.IncludeXmlComments(str, true);}}SwaggerGenOptionsExtensions.CustomSchemaIds(c, x => x.FullName);c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme{Type = SecuritySchemeType.Http,Scheme = "bearer",BearerFormat = "JWT",Description = "请输入 bearer 认证"});c.AddSecurityRequirement(new OpenApiSecurityRequirement{{new OpenApiSecurityScheme{Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }},new string[] {}}});});return services;}/// <summary>/// 使用 Swagger UI/// </summary>/// <param name="app"></param>/// <returns></returns>public static IApplicationBuilder UseMCodeSwagger(this IApplicationBuilder app){string serviceName = app.ApplicationServices.GetRequiredService<SwaggerOptions>().ServiceName;SwaggerUIBuilderExtensions.UseSwaggerUI(SwaggerBuilderExtensions.UseSwagger(app), c =>{c.SwaggerEndpoint("/swagger/" + serviceName + "/swagger.json", serviceName);});return app;}public static IServiceCollection AddMCodeOcelotSwagger(this IServiceCollection services, OcelotSwaggerOptions ocelotSwaggerOptions){services.AddSingleton(ocelotSwaggerOptions);SwaggerGenServiceCollectionExtensions.AddSwaggerGen(services);return services;}public static IApplicationBuilder UseMCodeOcelotSwagger(this IApplicationBuilder app){OcelotSwaggerOptions ocelotSwaggerOptions = app.ApplicationServices.GetService<OcelotSwaggerOptions>();if (ocelotSwaggerOptions == null || ocelotSwaggerOptions.SwaggerEndPoints == null){return app;}SwaggerUIBuilderExtensions.UseSwaggerUI(SwaggerBuilderExtensions.UseSwagger(app), c =>{foreach (SwaggerEndPoint swaggerEndPoint in ocelotSwaggerOptions.SwaggerEndPoints){c.SwaggerEndpoint(swaggerEndPoint.Url, swaggerEndPoint.Name);}});return app;}}
}

效果

image

image

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

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

相关文章

性价比1.2V电压基准替代

前言&#xff1a; 小于2V的电压基准比较少&#xff0c;且价格稍贵&#xff0c;对于要求不高的场合&#xff0c;1117可以替代使用&#xff0c;温度系数低于 100ppm/C, 价格便宜。 1117是线性稳压器的一种&#xff0c;一般情况下&#xff0c;输出电压可调。 如下述的1117&#xf…

使用 Java 和 FreeMarker 实现自动生成供货清单,动态生成 Word 文档,简化文档处理流程。

在上一篇博客中主要是使用SpringBootApache POI实现了BOM物料清单Excel表格导出&#xff0c;详见以下博客&#xff1a; Spring Boot Apache POI 实现 Exc&#xff08;&#xff09;el 导出&#xff1a;BOM物料清单生成器&#xff08;支持中文文件名、样式美化、数据合并&#…

探索与创作:2024年CSDN平台上的成长与突破

文章目录 我与CSDN的初次邂逅初学阶段的阅读CSDN&#xff1a;编程新手的避风港初学者的福音&#xff1a;细致入微的知识讲解考试复习神器&#xff1a;技术总结的“救命指南”曾经的自己&#xff1a;为何迟迟不迈出写博客的第一步兴趣萌芽&#xff1a;从“读”到“想写”的初体验…

鸿蒙(HarmonyOS)的开发

在当今数字化时代&#xff0c;软件开发不仅需要技术上的创新和突破&#xff0c;同时也必须严格遵守法律法规。作为中国自主研发的操作系统&#xff0c;鸿蒙&#xff08;HarmonyOS&#xff09;的开发者们更应该注重这一点。本文将围绕“鸿蒙开发需遵守法律法规”这一主题&#x…

SSM课设-学生管理系统

【课设者】SSM课设-学生管理系统 技术栈: 后端: SpringSpringMVCMybatisMySQLJSP 前端: HtmlCssJavaScriptEasyUIAjax 功能: 学生端: 登陆 学生信息管理 个人信息管理 老师端: 多了教师信息管理 管理员端: 多了班级信息管理 多了年级信息管理 多了系统用户管理

力扣 打家劫舍

动态规划&#xff0c;当前状态由前两个状态获得&#xff0c;滚动数组。 题目 从题可以看出要达到最高金额时&#xff0c;要从相邻的房屋拿。因此是当前房屋的金额隔一个做累加&#xff0c;当然还需要跟前一个相邻的房屋做比较&#xff0c;便于取到哪边金额更高&#xff0c;因此…

用公网服务器实现内网穿透

首先需要一个公网服务器 下载frp 搜索github下载到frp&#xff0c;服务端frps/客户端frpc。。下载的时候要注意自己本地内网机的cpu版本和服务端cpu架构 我的电脑是mac M1PRO版本 下载的是&#xff1a;darwinarm64 比如 服务端一般是Linux&#xff08;Intel 64位CPU&#xf…

clang、C++23标准库模块基本使用

1. 已经知道clang和LLVM的版本大于18的话&#xff0c;就支持C23标准的新特性&#xff1a;标准库模块啦&#xff01;那么该怎么使用呢&#xff1f; 2. 操作系统是Manjaro 3. 必须同时把clang 、LLVM 、 libc 、 libcabi这四个软件包同时安装好&#xff01;缺一不可…

【Django开发】django美多商城项目完整开发4.0第12篇:商品部分,表结构【附代码文档】

本教程的知识点为&#xff1a; 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计&#xff1a; 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…

Redis的安装和使用--Windows系统

Redis下载地址&#xff1a; windows版本readis下载&#xff08;GitHub&#xff09;&#xff1a; https://github.com/tporadowski/redis/releases &#xff08;推荐使用&#xff09; https://github.com/MicrosoftArchive/redis/releases 官网下载&#xff08;无Windows版本…

Linux操作命令之云计算基础命令

一、图形化界面/文本模式 ctrlaltF2-6 图形切换到文本 ctrlalt 鼠标跳出虚拟机 ctrlaltF1 文本切换到图形 shift ctrl "" 扩大 ctrl "-" 缩小 shift ctrl "n" 新终端 shift ctrl "t" 新标签 alt 1,…

LabVIEW桥接传感器配置与数据采集

该LabVIEW程序主要用于配置桥接传感器并进行数据采集&#xff0c;涉及电压激励、桥接电阻、采样设置及错误处理。第一个VI&#xff08;"Auto Cleanup"&#xff09;用于自动清理资源&#xff0c;建议保留以确保系统稳定运行。 以下是对图像中各个组件的详细解释&#…

逐笔成交逐笔委托Level2高频数据下载和分析:20241230

逐笔委托逐笔成交下载 链接: https://pan.baidu.com/s/11Tdq06bbYX4ID9dEaiv_lQ?pwdcge6 提取码: cge6 Level2逐笔成交逐笔委托数据分享下载 利用Level2的逐笔交易和委托数据&#xff0c;这种以毫秒为单位的详细信息能揭露众多关键信息&#xff0c;如庄家意图、伪装行为&…

网络编程 | UDP广播通信

1、什么是广播 在上一篇博客文章中已经对UDP进行了详细的说明介绍及如何编程实现。本文将接着上一文的内容&#xff0c;在其基础上&#xff0c;对UDP的知识体系进一步深入的讲解。 网络编程 | UDP套接字通信及编程实现经验教程-CSDN博客 例子&#xff1a;在一些中小学的操场中&…

Count Sketch--计数草图

背景 Count Sketch 是一种空间高效的概率型数据结构&#xff0c;由 Moses Charikar、Kevin Chen 和 Martin Farach-Colton 在 2002 年提出&#xff0c;用于估计数据流中元素的频率&#xff0c;也可用于解决重击者问题。 原理 算法结构 参数设定&#xff1a;Count Sketch算法…

洛谷P4017 最大食物链计数(图的拓扑排序)

题目链接&#xff1a;P4017 最大食物链计数 - 洛谷 | 计算机科学教育新生态 题目描述 给你一个食物网&#xff0c;你要求出这个食物网中最大食物链的数量。 &#xff08;这里的“最大食物链”&#xff0c;指的是生物学意义上的食物链&#xff0c;即最左端是不会捕食其他生物…

2025.1.17——三、SQLi regexp正则表达式|

题目来源&#xff1a;buuctf [NCTF2019]SQLi1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;正常注入 step 2&#xff1a;弄清关键字黑名单 1.目录扫描 2.bp爆破 step 3&#xff1a;根据过滤名单构造payload step 4&#xff1a;regexp正则注…

【华为OD-E卷 - 字符串加密 100分(python、java、c++、js、c)】

【华为OD-E卷 - 字符串加密 100分&#xff08;python、java、c、js、c&#xff09;】 题目 给你一串未加密的字符串str&#xff0c;通过对字符串的每一个字母进行改变来实现加密&#xff0c;加密方式是在每一个字母str[i]偏移特定数组元素a[i]的量&#xff0c;数组a前三位已经…

搭建一个基于Spring Boot的书籍学习平台

搭建一个基于Spring Boot的书籍学习平台可以涵盖多个功能模块&#xff0c;例如用户管理、书籍管理、学习进度跟踪、笔记管理、评论和评分等。以下是一个简化的步骤指南&#xff0c;帮助你快速搭建一个基础的书籍学习平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个…

【Linux 之一 】Linux常用命令汇总

Linux常用命令 ./catcd 命令chmodclearcphistoryhtoplnmkdirmvpwdrmtailunamewcwhoami 我从2021年4月份开始才开始真正意义上接触Linux&#xff0c;最初学习时是一脸蒙圈&#xff0c;啥也不会&#xff0c;啥也不懂&#xff0c;做了很多乱七八糟&#xff0c;没有条理的笔记。不知…