Rust实战(三):HTTP健康检查引擎 —— 异步Rust与高性能探针


\u003e **关于本rust实战教程系列:**\u003e - **定位**:一份从rust基础迈向项目实战的练习记录。\u003e - **内容**:聚焦实战中遇到的具体问题、解决思路与心得总结。\u003e - **读者**:适合有rust基础,但急需项目经验巩固知识的开发者。**资深玩家可忽略**。\u003e - **计划**:本期为系列第三篇,将根据我的学习进度持续更新。\u003e - **导航**:相关内容都已经放到专栏中:[rust实战课程](https://juejin.cn/column/7563087634245599241) [git仓库地址](https://github.com/maamos/rust-practical-course)

简要说明本篇是之前的网络资源监控器(初版)的续集,在这篇文章中我将会继续丰富网络资源监控器的功能,当然本篇也没有结束,只是二版,因为完整的功能确实太多太多了,本身这系列也是自己的学习的记录,如果一次完成的话太复杂了,对我这种新手来说不是很友好,所以我这边会像堆积木一样一点点的来完成每个模块的内容,争取我们能完成一个可用的企业级网络资源监控器(*牛逼吹起来了~*);

## 需求内容### 1. 搭建监控引擎的框架- 支持多种监控类型(HTTP/HTTPS、Memory、TCP、PING等)- 可配置的检查频率- 并发执行监控检查- 重试机制- 超时控制- 结果记录(包括响应时间、状态、错误信息等)### 2.实现HTTP/HTTPS监控引擎- 基础可用监控(BasicAvailability)- 性能监控(PerformanceTimings)- 安全监控(SslSecurity, SecurityHeaders)- 内容验证监控(ContentVerification)

## 功能点详解\u003e 首先,我们将基于上一篇内容中的监控配置列表,搭建一个支持多监控类型的框架。在本次课程中,我们会一步步完成整体框架的基础结构,并重点实现 HTTP/HTTPS 类型的监控逻辑。其他监控类型(如 ICMP、TCP、DNS 等)暂时不在此次实现范围之内,将作为课后扩展练习留给大家自行完成与完善(***其实主要是因为监控类型实在太多,写不动啦~***)。

好的,我们来梳理一下核心任务。简单来说,这个框架需要支持多种监控类型(如 HTTP、HTTPS、DNS、TCP 等),并通过一个监控引擎来统一调度这些检查任务,最终汇总并输出所有类型的监控结果。

为了实现这个目标,我们可以将整体逻辑划分为以下两个核心部分来构建:

1. **监控引擎**:这是框架的大脑,负责调度和执行任务。它的主要工作是读取监控列表,依次调用不同监控类型的检查逻辑,并收集结果。1. **监控类型实现**:这是框架的肌肉,包含各种监控类型(如 HTTP/HTTPS)的具体检查逻辑。每种类型都是一个独立的模块,负责执行专业检查并返回标准化的结果。

下面,我们就按照这两个模块来具体实现:### 多类型监控引擎实现在本次框架设计中,我们核心采用了 **策略模式与工厂模式相结合** 的架构方案:

- **策略模式**:我们将每种监控类型(如 HTTP、HTTPS)都定义为实现了统一 `Monitor` Trait 的独立策略。这确保了每种监控检查逻辑都高度内聚,可以独立开发和演变。- **工厂模式**:我们通过一个统一的工厂,根据配置来批量创建对应的监控器实例。这消除了代码中复杂的对象创建逻辑,实现了客户端与具体实现的解耦。

这样未来扩展新的监控类型(如 DNS、TCP)将变得异常简单:**只需定义一个新的策略并实现 `Monitor` Trait 即可**,无需修改引擎的核心调度逻辑。高内聚、低耦合,完美~~~#### 1. Monitor公共Trait的实现首先我们来看下我们统一的Trait的定义,其实这个特征对象很简单,核心只需要实现一个检查函数即可

```rust// src/monitor/monitor_trait.rsuse super::types::{MonitorConfig, CheckResult};use crate::tools_types::MonitorType;// 定义监控类型的 trait 后续的不同的监控类型都实现这个 trait// 在这里添加 Send 和 Sync 作为父 trait// Send: 允许在线程间移动// Sync: 允许在线程间共享引用 (\u0026T)// 对于 tokio::spawn 和多线程异步,这两个通常都需要。#[async_trait::async_trait]pub trait Monitor: Send + Sync { async fn check(\u0026self, config: \u0026MonitorConfig) -\u003e CheckResult; fn get_type(\u0026self) -\u003e MonitorType;}```对应的`check`函数只需要传入一个监控配置参数,然后返回一个检测结果就可以了,同时我们还多定义了一个`get_type`方法:用于获取当前的检测类型,这样的话其实我们就已经实现了我们统一的特征对象的定义任务了。下面的话我们来具体的看下,我们抽象出来的`监控配置参数MonitorConfig`、`检测结果CheckResult`这两个对象的定义逻辑: 这里的话,我声明了一个`types.rs`模块,专门用来声明对应的结构体对象、枚举值对象等过程中使用到一下基础的类型定义,##### 1.1 监控配置参数MonitorConfig

```rust// src/monitor/types.rs 类型声明模块

// 定义核心的监控配置参数结构体#[derive(Debug, Clone)]pub struct MonitorConfig { pub target: Option\u003cString\u003e, // 监控的目标URL或IP地址 pub interval: Option\u003cu64\u003e, // 监控间隔,单位秒 pub monitor_type: MonitorType,// 监控类型 HTTP TCP FTP等等 pub details: MonitorConfigDetail, // 这里的话是不同监控类型的具体参数,跟公共的一些参数区分开 详见14行代码声明}

// 定义一个监控数据的详情监控参数 结构体 ,用于每个监控类型中的不同的参数类型#[derive(Debug, Clone)]pub enum MonitorConfigDetail { Http(HttpMonitorConfig), Https(HttpsMonitorConfig), Ftp(FtpMonitorConfig), Traceroute(TracerouteMonitorConfig), Cpu(CpuMonitorConfig), Memory(MemoryMonitorConfig), Disk(DiskMonitorConfig), Process(ProcessMonitorConfig), Unknown(UnknownQueryConfig),}// 其中这些不同监控类型的机构体我们就不一一声明了 ,都是类似的,// 异常监控的兜底类型#[derive(Debug, Clone)]pub struct UnknownQueryConfig{ pub description: String, // 异常描述信息}// HTTP监控的配置参数#[derive(Debug, Clone)]pub struct HttpMonitorConfig { pub url: String, // 定义HTTP监控的URL pub method: HttpMethodTypes, // GET, POST, etc. pub timeout: u64, // 配置超时时间 pub headers: Option\u003cHeaderMap\u003cHeaderValue\u003e\u003e, // 可选的请求URL需要的HTTP头 pub body: Option\u003cHttpBody\u003e, // 可选的请求URL需要的body体 pub rules: Option\u003cVec\u003cContentVerificationRulesSingle\u003e\u003e, // 可配置的监控规则}

// 其中监控的规则的话我们来简单实现了一下 //定义内容监控规则结构体明细字段#[derive(Debug, Clone, Default, serde::Deserialize)]pub struct ContentVerificationRulesSingle { pub rule_type: ContentVerificationRules, // 只支持Contains、NotContains、Regex三种不同的规则 pub rule_content: String, // 每种规则的关键字 pub rule_description: String, // 规则的描述字段}

```##### 1.2 检测结果CheckResult

```rust// 定义检查结果结构体#[derive(Debug, Clone)]pub struct CheckResult { pub id: u128, // 监控记录的ID 唯一标识 pub monitor_type: MonitorType, // 监控类型 pub target: Option\u003cString\u003e, // 监控的目标URL或IP地址 pub status: bool, // 监控状态,true表示正常,false表示异常 pub details: CheckResultDetail, // 监控结果的详细信息,依然是每种不同的监控类型都是不同的监控结果}

// 定义不同类型的监控返回结果详情结构体#[derive(Debug, Clone)]pub enum CheckResultDetail { Http(HttpMonitorResult), Https(HttpsMonitorResult), Ftp(FtpMonitorResult), Traceroute(TracerouteMonitorResult), Cpu(CpuMonitorResult), Memory(MemoryMonitorResult), Disk(DiskMonitorResult), Process(ProcessMonitorResult), Icmp(IcmpMonitorResult), Tcp(TcpMonitorResult), Udp(UdpMonitorResult), Dns(DnsMonitorResult), Unknown(UnknownQueryResult),}

// 定义一个保存http监控的最终结果参数结构体 #[derive(Debug, Clone, Default)]pub struct HttpMonitorResult{ pub basic_avaliable: BasicAvailability, // 包含基础的检测内容 pub response_headers: SecurityHeaders, // 安全检测相关的头信息 pub performance_timings: PerformanceTimings, // 性能指标相关信息 pub certificate_info: CertificateInfo, // SSL证书信息 pub content_verification: ContentVerificationResult, // 内容检测相关信息 pub advanced_avaliable: AdvancedAvailability, // 高级监控相关信息}// 这里的话我们就不过多展示HTTP中检测的各种类型的具体的实现Struct了,在后面我们会详细的讲解每一种类型的检测内容都包含哪些具体的字段值

```

通过前面的讲解,我们已经完成了公共 Trait 的定义与相关参数的声明,奠定了框架的核心基础。接下来,我们将进入**监控引擎工厂**的实现部分。

首先,我们来明确一下工厂的核心职责:**监控引擎工厂用于根据不同的监控类型,动态创建对应的监控引擎实例**。举个例子,当我需要监控一个 HTTP 服务时,我只需告知工厂“我需要一个 HTTP 监控引擎”,工厂便会返回一个专门用于执行 HTTP 检查的引擎实例。

理解了这个核心概念后,具体的代码实现就会显得清晰而直接:

```rustsrc/monitor/mod.rs

pub mod types;use crate::tools_types::MonitorType; // 全局通用的类型定义模块

// 引进特征对象 pub mod monitor_trait;use monitor_trait::Monitor;

// 声明具体的监控引擎mod icmp_monitor;mod tcp_monitor;mod udp_monitor;mod dns_monitor;mod http_monitor;mod ftp_monitor;mod traceroute_monitor;mod cpu_monitor;mod memory_monitor;mod disk_monitor;mod process_monitor;// 不同类型的监控系统use icmp_monitor::IcmpMonitor;use tcp_monitor::TcpMonitor;use udp_monitor::UdpMonitor;use dns_monitor::DnsMonitor;use http_monitor::HttpMonitor;use ftp_monitor::FtpMonitor;use traceroute_monitor::TracerouteMonitor;use cpu_monitor::CpuMonitor;use memory_monitor::MemoryMonitor;use disk_monitor::DiskMonitor;use process_monitor::ProcessMonitor;

// 定义监控工厂pub struct MonitorFactory;

impl MonitorFactory { // 基于策略模式 工厂函数返回一个实现特征Monitor的监控引擎 // 入参为监控类型,出参为具体的监控引擎 // 通过Box\u003c\u003e统一返回类型,同时因为尺寸未知必须要放在Box后面,同时通过vTable调用实现多态,调用端无需关注具体类型 pub fn create_monitor(monitor_type: MonitorType) -\u003e Box\u003cdyn Monitor\u003e { match monitor_type { MonitorType::Icmp =\u003e Box::new(IcmpMonitor::new()), MonitorType::Tcp =\u003e Box::new(TcpMonitor::new()), MonitorType::Udp =\u003e Box::new(UdpMonitor::new()), MonitorType::Dns =\u003e Box::new(DnsMonitor::new()), MonitorType::Http =\u003e Box::new(HttpMonitor::new()), MonitorType::Ftp =\u003e Box::new(FtpMonitor::new()), MonitorType::Traceroute =\u003e Box::new(TracerouteMonitor::new()), MonitorType::Cpu =\u003e Box::new(CpuMonitor::new()), MonitorType::Memory =\u003e Box::new(MemoryMonitor::new()), MonitorType::Disk =\u003e Box::new(DiskMonitor::new()), MonitorType::Process =\u003e Box::new(ProcessMonitor::new()), } }}

```接下来,我们将定义具体的监控引擎模块。所有监控引擎均遵循相同的结构:实现统一的 `Monitor` trait,并通过完善 `check` 方法,来承载各类监控任务的具体逻辑,为便于理解,这里我们仅以其中一个监控类型为例进行展示,其他类型的实现方式与此类似。

```rust// src/monitor/cpu_monitor.rsuse super::monitor_trait::Monitor;use super::types::{ MonitorConfig, CheckResult, CheckResultDetail, CpuMonitorResult};use crate::tools_types::MonitorType;

pub struct CpuMonitor {

}

impl CpuMonitor { pub fn new() -\u003e Self { CpuMonitor {} }}// 用来让trait中的异步方法可用,详细的请查看Q\u0026A#[async_trait::async_trait]impl Monitor for CpuMonitor { async fn check(\u0026self, config: \u0026MonitorConfig) -\u003e CheckResult {

CheckResult { id: uuid::Uuid::new_v4().as_u128(), monitor_type: MonitorType::Cpu, target: config.target.clone(), status: true, details: CheckResultDetail::Cpu(CpuMonitorResult::default()) } }

fn get_type(\u0026self) -\u003e MonitorType { MonitorType::Cpu }}```在完成了多类型监控引擎的声明与模块定义之后,我们的各个引擎已经具备了独立运行的能力。然而,引擎本身需要被协调和驱动,这正是**调度器**所承担的核心角色。

调度器作为整个系统的中枢,负责串联起完整的监控流程:它首先获取监控任务列表,随后根据每个任务的具体配置参数,动态调用对应的监控引擎来执行监控检查。简而言之,调度器不关心具体如何监控,而是专注于`“何时”`以及`“如何调度”`监控任务。

接下来,我们就具体实现这个关键的监控调度器:

#### 2.监控引擎调度器的具体实现调度器虽承担着系统“中枢”的名号,但在各监控引擎已封装完备的前提下,其核心职责确实清晰而聚焦——它无需关心具体的检测逻辑,只需专注于调度本身。具体来说,它需要完成三个核心任务:- **异步调度**:并发地调用各个监控引擎的检测方法;- **循环执行**:按预设间隔启动轮询任务,实现持续监控;- **结果收集**:汇总并输出每次任务的执行结果。

下面,我们就来具体实现这一调度逻辑:

```rustuse std::{ time::Duration}; // 引入时间模块// 定义公用的枚举值模块 这样在其他的地方 可以通过 use crate::tools_types..来使用pub mod tools_types;use tools_types::{ convert_to_monitor_config };

// 异步监控模块,用于实现异步调度mod async_monitor;use async_monitor::AsyncMonitor;

// 定义文件读取模块,封装通用的文件处理操作mod tools;use tools::file_tool::{read_json_file};

// 定义监控引擎模块,引入监控引擎工厂对象pub mod monitor;use monitor::{ MonitorFactory } ;

#[tokio::main]async fn main() { println!(\"网络监控器 启动...\"); // 获取需要监控的网站列表,这里的话我们改成了一个JSON文件,每个监控引擎参数都是一个对象,方便后续通过页面来配置,类似下面的数据结构: // [{ // \"target\": \"https://www.google.com\", // \"monitor_type\": \"HTTP\", // \"method\": \"GET\", // \"params\": {}, // \"headers\": {}, // \"rules\": [ // { // \"rule_type\": \"contains\", // \"rule_content\": \"Google\", // \"rule_description\": \"检查页面是否包含 'Google' 字符串\" // } // ], // \"timeout\": 5000 // }] let monitor_website_list = read_json_file(\"monitor_list.json\"); match monitor_website_list { Ok(monitor_list) =\u003e { // 存储线程的运行结果 let mut result_monitors = Vec::new(); for monitor in monitor_list { // 创建一个具体的监控器实例 let target = MonitorFactory::create_monitor(monitor.monitor_type); // 把监控配置文件中的对象转换成监控器检测时需要的对象 let monitor_config = convert_to_monitor_config(\u0026monitor); // 如果是一个 轮询监控 创建一个轮询监控器 match monitor.interval { Some(interval) =\u003e { // 创建一个轮询监控调度器 let async_monitor = AsyncMonitor::create_interval_monitoring(target, monitor_config).await; result_monitors.push(async_monitor); }, None =\u003e { // 创建一个单次监控调度器 let once_monitor = AsyncMonitor::create_once_monitoring(target, monitor_config).await; result_monitors.push(once_monitor); } } } // 处理所有的监控结果 for monitor_receiver in result_monitors { // 使用tokio::spawn异步任务来监控不同类型的调度器,避免阻塞主进程 tokio::spawn(async move { // 这里使用一个循环来接收所有的监控结果 let mut result_receiver = monitor_receiver; while let Some(result) = result_receiver.recv().await { // 直接打印相关的检测结果,后续会接入H5页面来实现 println!(\"Received result: {:?}\", result); } });

} println!(\"所有监控已启动,程序将继续运行\"); // 你可以根据需要调整这个时间或者使用其他方式保持程序运行 tokio::time::sleep(Duration::from_secs(60)).await; // 让程序运行60s然后程序就会退出 }, Err(err) =\u003e { eprintln!(\"Error reading monitor list: {}\", err.to_string()); } } println!(\"所有 URL 检查完毕\");}

```其中上面使用到了轮询调度器和单次调度器,下面我们来具体的看下相关的实现逻辑:

```rustsrc/async_monitor.rsuse tokio::time::{interval, Duration};use crate::monitor::monitor_trait::Monitor;use crate::monitor::types::{MonitorConfig, CheckResult};// 1. 引入mpsc 通道概念 用于创建通道 并将接收端返回给调用者use tokio::sync::mpsc;

use std::pin::Pin;

// 这里统一返回异步监控的类型,方便后续进行统一的监控结果检测type MonitorResultReceiver = mpsc::Receiver\u003cCheckResult\u003e;type PinnedReceiverFuture = Pin\u003cBox\u003cdyn Future\u003cOutput = MonitorResultReceiver\u003e + Send\u003e\u003e;

pub struct AsyncMonitor {}

impl AsyncMonitor { // 创建一个轮询的监控器 pub fn create_interval_monitoring(target: Box\u003cdyn Monitor\u003e, config: MonitorConfig) -\u003e PinnedReceiverFuture { Box::pin(async move { let (tx, rx) = mpsc::channel(100); tokio::spawn(async move { let mut interval: tokio::time::Interval = interval(Duration::from_secs(config.interval.unwrap())); loop { interval.tick().await; let check_result = target.check(\u0026config).await; if tx.send(check_result).await.is_err() { println!(\"Error sending result to channel\"); }

} }); // 返回接收端 对象 rx

}) } // 创建一个单次监控 pub fn create_once_monitoring( target: Box\u003cdyn Monitor\u003e, config: MonitorConfig) -\u003e PinnedReceiverFuture { Box::pin(async move { let (tx, rx) = mpsc::channel(1); tokio::spawn(async move { let check_result = target.check(\u0026config).await; if tx.send(check_result).await.is_err() { println!(\"Error sending result to channel\"); } }); // 返回接收端 对象 rx })

}

}

```? **热烈祝贺!**  ?

如果您已经跟随到这里,那么恭喜——您已经成功完成了整个监控系统核心框架的搭建!这是值得?掌声的重要里程碑!

根据我们最初的规划,接下来将进入具体监控类型的实现阶段。在本次实现中,我们将聚焦于 **HTTP 监控** 的详细逻辑开发,这也是最常用和基础的服务监控类型。

至于其他监控类型(如 TCP、DNS、ICMP 等),我们将它们留作大家的**课后实践作业**——当然,也不排除我后续会悄悄更新补充的可能性 ?

### 实现HTTP/HTTPS监控引擎基于之前的需求分析,我们已经明确了 HTTP 监控所需实现的功能。现在,我们将根据既定的设计,开始定义与之对应的监控器结构体。

#### 1.1 定义HTTP监控类型结构体

```rust// src/tools_types.rs// 定义一个struct 来保存http相关监控的最终结果参数结构体#[derive(Debug, Clone, Default)]pub struct HttpMonitorResult{ pub basic_avaliable: BasicAvailability, pub response_headers: SecurityHeaders, pub performance_timings: PerformanceTimings, pub certificate_info: CertificateInfo, // SSL证书信息 pub content_verification: ContentVerificationResult, pub advanced_avaliable: AdvancedAvailability,

}

```在上面我们已经看到了HTTP监控引擎最后的监控结果了,包含6个模块:- `BasicAvailability`:基础监控结果,包括是否可访问、状态码、协议类型等等

```rust// 定义一个struct 来保存基本的HTTP可用性信息#[derive(Debug, Clone, Default)]pub struct BasicAvailability{ pub is_reachable: bool, // 是否可达 pub dns_resolvable: bool, // DNS解析是否成功 pub tcp_connect_success: bool, // TCP链接是否成功 // HTTP相关 pub res_received: bool, // 是否收到响应 pub res_status_code: Option\u003cu16\u003e, // 响应状态码 pub res_status_category: StatusCategory, // 响应状态码类别 pub protocol_version: String, // HTTP协议版本(如HTTP/1.1, HTTP/2) pub res_content_type: Option\u003cString\u003e, // 响应内容类型 pub res_content_length: u64, // 响应内容长度 pub res_charset: Option\u003cString\u003e, // 响应字符集}```- `SecurityHeaders`:安全头相关监控结果,是否包含一些安全头信息:`strict_transport_security、content_security_policy`等等

```rust// 定义一个struct 来保存安全头监控信息#[derive(Debug, Clone, Default)]pub struct SecurityHeaders{ pub strict_transport_security: Option\u003cString\u003e, // 是否存在Strict-Transport-Security头 pub content_security_policy: Option\u003cString\u003e, // 是否存在Content-Security-Policy头 pub x_content_type_options: Option\u003cString\u003e, // 是否存在X-Content-Type-Options头 pub x_frame_options: Option\u003cString\u003e, // 是否存在X-Frame-Options头 pub x_xss_protection: Option\u003cString\u003e, // 是否存在X-XSS-Protection头 pub referrer_policy: Option\u003cString\u003e, // 是否存在Referrer-Policy头 pub feature_policy: Option\u003cString\u003e, // 是否存在Feature-Policy头 pub permissions_policy: Option\u003cString\u003e, // 是否存在Permissions-Policy头 pub security_headers_ok: bool, // 是否所有安全头都存在}```- `PerformanceTimings`:性能指标,包括TCP连接时间、TLS链接时间、连接耗时等等

```rust// 创建一个枚举类型,表示性能指标的类别#[derive(Debug, Clone, Default)]pub struct PerformanceTimings { // 性能指标相关 pub dns_lookup_time: u128, // DNS查询时间,单位毫秒 pub tcp_connect_time: u128, // TCP连接时间,单位毫秒 pub tls_handshake_time: u128, // TLS握手时间,单位毫秒 pub first_byte_time: u128, // 首字节时间,单位毫秒 pub content_download_time: u128, // 内容下载时间,单位毫秒 pub ssl_negotiation_time: u128, // SSL协商时间,单位毫秒 pub ssl_cert_valid: bool, // SSL证书是否有效 pub request_sending_time: u128, // 请求发送时间,单位毫秒 pub server_processing_time: u128, // 服务器处理时间,单位毫秒 pub response_receiving_time: u128, // 响应接收时间,单位毫秒 pub total_time: u128, // 总时间,单位毫秒

}```- `CertificateInfo`:SSL证书相关内容,包括证书编号、是否有效等等

```rust#[derive(Debug, Clone, Default)]pub struct CertificateInfo { pub issuer: Option\u003cString\u003e, // 证书颁发者 pub subject: Option\u003cString\u003e, // 证书主题 pub valid_from: Option\u003cString\u003e, // 证书有效期开始时间 pub valid_until: Option\u003cString\u003e, // 证书有效期结束时间 pub serial_number: Option\u003cString\u003e, // 证书序列号 pub signature_algorithm: Option\u003cString\u003e, // 签名算法 pub public_key_algorithm: Option\u003cString\u003e, // 公钥算法 pub public_key_size: Option\u003cusize\u003e, // 公钥大小 pub is_valid: bool, // 证书是否有效}```- `ContentVerificationResult`:响应内容监控结果,包括是否包含某字段、正则匹配内容等

```rust// 创建一个内容验证结果#[derive(Debug, Clone, Default)]pub struct ContentVerificationResult { pub match_rules: Vec\u003cContentVerificationRulesResult\u003e, // 匹配的规则 pub failed_rules: Vec\u003cContentVerificationRulesResult\u003e, // 未匹配的规则 及其原因}// 定义核心内容验证返回数据结构体#[derive(Debug, Clone, Default)]pub struct ContentVerificationRulesResult { pub rule_id: u64, pub status:StatusInfo, pub message: String, pub rules: ContentVerificationRulesSingle}//定义内容监控规则结构体明细字段#[derive(Debug, Clone, Default, serde::Deserialize)]pub struct ContentVerificationRulesSingle { pub rule_type: ContentVerificationRules, pub rule_content: String, pub rule_description: String,}// 内容验证类别#[derive(Debug, Clone, serde::Deserialize)]pub enum ContentVerificationRules { #[serde(rename = \"contains\")] Contains, // 响应内容中包含指定字符串 #[serde(rename = \"not_contains\")] NotContains, // 响应内容中不包含指定字符串 #[serde(rename = \"regex\")] Regex, // 响应内容匹配正则表达式 // 定义一个默认值 用于匹配 #[serde(rename = \"default\")] // 定义默认值 Default,}// 设置默认值impl Default for ContentVerificationRules { fn default() -\u003e Self { ContentVerificationRules::Default }}

#[derive(Debug, Clone, serde::Deserialize)]pub enum StatusInfo { Success, Failed, Unknown,}impl Default for StatusInfo { fn default() -\u003e Self { StatusInfo::Unknown }}

```- AdvancedAvailability:高级监控内容,包含事物监控等,本次先不涉及...

```rust// 高级可用性类别 业务指标监控 事务监控 等#[derive(Debug, Clone, Default)]pub struct AdvancedAvailability { pub bussiness_metrics: HashMap\u003cString, String\u003e,}```现在,我们已经完成了监控结果结构体的定义,接下来要做的就是逐步填充每个字段的值——这就像完成拼图的最后一块,当所有字段都被正确赋值时,整个HTTP监控模块的实现也就圆满完成了。

让我们立即开始这最后的实现环节,为每个字段注入实际的数据内容。

#### 1.2 HTTP监控引擎的实现现在,让我们将视线转回最初设计的 HTTP 监控引擎。在之前搭建框架时,我们已经实现了一个基础的结果返回逻辑。接下来,我们将在此基础上逐步深化,填充更多实际功能。

正如前文所提到的,我们将继续使用 `reqwest` 库来处理 HTTP 请求。其基本用法在此不再赘述,现在让我们集中精力,进一步完善 `HttpMonitor` 引擎的完整逻辑。

```rustsrc/monitor/http_monitor.rs

pub struct HttpMonitor { client: Client,}impl HttpMonitor { pub fn new() -\u003e Self { // 创建一个Client,方便后续进行URL调用 HttpMonitor { client: Client::builder() .redirect(reqwest::redirect::Policy::limited(5)) // 重定向次数限制为5次 .build().expect(\"Failed to create HTTP client\"), } } // 获取一个http 客户端链接 根据 method 方法来判断 创建一个http 链接 pub fn get_client(\u0026self, config: \u0026HttpMonitorConfig) -\u003e reqwest::RequestBuilder { // 创建一个http 请求 let mut request_client = match config.method { HttpMethodTypes::Get =\u003e self.client.get(config.url.as_str()), HttpMethodTypes::Post =\u003e self.client.post(config.url.as_str()), HttpMethodTypes::Put =\u003e self.client.put(config.url.as_str()), HttpMethodTypes::Delete =\u003e self.client.delete(config.url.as_str()), HttpMethodTypes::Head =\u003e self.client.head(config.url.as_str()), HttpMethodTypes::Patch =\u003e self.client.patch(config.url.as_str()), _ =\u003e self.client.get(config.url.as_str()), // 默认使用 GET 方法 };

// 根据配置信息 设置超时时间 request_client = request_client.timeout(std::time::Duration::from_millis(config.timeout)); // 如果用户自定义了Header头信息 在这里要添加进去 if let Some(headers) = \u0026config.headers { request_client = request_client.headers(headers.clone()); } // 兼容几种不同的body类型,分别进行设置 if let Some(body) = \u0026config.body { match body { HttpBody::Text(text) =\u003e { request_client = request_client.body(text.clone()); }, HttpBody::Binary(bin) =\u003e { request_client = request_client.body(bin.clone()); }, HttpBody::Json(json_value) =\u003e { request_client = request_client.json(json_value); }, HttpBody::Empty =\u003e {request_client = request_client.body(\"\");}, } } // 最终返回一个HTTP连接 Client request_client } // 创建一个生成基础监控结果的函数 fn create_basic_result(\u0026self, ...) -\u003e BasicAvailability {???????} // 创建一个生成安全头监控结果的函数 fn create_headers_result(\u0026self,...) -\u003e SecurityHeaders{???????} // 创建一个生成性能指标的监控结果的函数 fn create_performance_timings(\u0026self,...) -\u003e PerformanceTimings {???????} // 创建一个校验响应内容监控结果的函数 fn create_content_verification_result(\u0026self,...) -\u003e ContentVerificationResult{???????} // 创建高级可用性结果 直接返回一个默认结果 fn create_advanced_availability_result(\u0026self) -\u003e AdvancedAvailability { AdvancedAvailability { bussiness_metrics: HashMap::new(), } } }// 下面的话 就是要实现具体的check方法了#[async_trait::async_trait]impl Monitor for HttpMonitor{ async fn check(\u0026self, config: \u0026MonitorConfig) -\u003e CheckResult { // 这里就是我们的主战场了 首先我们先把异常情况写完,然后在后面进行一点点的填空 // 判断一下是否存在 target 此时的target 应该是一个 URL 地址 if config.target.is_none() { return CheckResult { id: uuid::Uuid::new_v4().as_u128(), // V4 uuid 一种随机数 基于时间戳和随机数 V4版本的生成功能 monitor_type: MonitorType::Http, target: None, status: false, // 监控状态失败 根本就没有进入监控当中去 details: CheckResultDetail::Http(HttpMonitorResult::default()), // default 表示调用Default trait方法,默认值为每个字段的默认值 }; } // 来处理具体的HTTP监控的类型数据 match config.details { MonitorConfigDetail::Http(ref detail) =\u003e { // 在这里的话 我们在前一章里面也看到了 首先我们要发送HTTP请求到Target地址 let request_client = self.get_client(detail); // 发送请求,来匹配返回的结果 match request_client.send().await{ Ok(response)=\u003e { // 实际上我们要做的就是把这个地方的逻辑来一点点的完善 好 如果细心的你看到这里的话,别急 我们这个里面的内容请往下翻哦~~~ ????????上车准备出发喽!!!!???????? }, Err(e) =\u003e { // 检查各种错误类型 return CheckResult { id: uuid::Uuid::new_v4().as_u128(), // V4 uuid 一种随机数 基于时间戳和随机数 V4版本的生成功能 monitor_type: MonitorType::Http, target: config.target.clone(), status: true, // 代表监控状态为成功,但是target访问失败了 details: CheckResultDetail::Http(HttpMonitorResult::default()), }; }, } }, _ =\u003e { // 如果不是 HTTP 监控类型,返回错误结果 return CheckResult { id: uuid::Uuid::new_v4().as_u128(), // V4 uuid 一种随机数 基于时间戳和随机数 V4版本的生成功能 monitor_type: MonitorType::Http, target: None, status: false, // 监控状态失败 根本就没有进入监控当中去 details: CheckResultDetail::Unknown(UnknownQueryResult { description: \"调用监控类型: HTTP, 请查实后再继续操作\".to_string(), query_type: MonitorType::Http, }), }; }, } } // 定义返回具体类型的函数 fn get_type(\u0026self) -\u003e MonitorType { MonitorType::Http }

}

```好,细心的你应该已经发现上面的代码需要填空的地方我都已经做了标注,现在我们来一个一个的实现具体的逻辑即可:- `拼接基础监控信息函数create_basic_result`:这个地方没有什么复杂的内容,直接根据response进行处理相关的数据即可

```rust// 解析成基础的响应结果结构体 fn create_basic_result(\u0026self, status_code: u16, version: reqwest::Version, headers: \u0026reqwest::header::HeaderMap, content_length: Option\u003cu64\u003e ) -\u003e BasicAvailability { BasicAvailability { is_reachable: true, // 代表这个target 是可以访问的 dns_resolvable: true, // 代表这个target 的域名是可以解析的 tcp_connect_success: true, // 代表这个target 的 TCP 连接是成功的 res_received: true, res_status_code: Some(status_code), res_status_category: StatusCategory::from_status_code(status_code),//获取对应的状态码描述信息 protocol_version: format!(\"{:?}\", version), // 获取HTTP协议版本 res_content_type: headers.get(reqwest::header::CONTENT_TYPE).and_then(|v| v.to_str().ok()).map(|s| s.to_string()), res_content_length: content_length.unwrap_or(0), res_charset: headers.get(reqwest::header::ACCEPT_CHARSET).and_then(|v| v.to_str().ok()).map(|s| s.to_string()), } } // 定义状态码对应的状态枚举类型 #[derive(Debug, Clone)] pub enum StatusCategory { Informational, Success, Redirection, ClientError, ServerError, Unknown, }

// 给对应的枚举值 添加方法 来获取不同的状态码的实际状态

impl StatusCategory { pub fn from_status_code(status_code: u16) -\u003e Self { match status_code { 100..=199 =\u003e StatusCategory::Informational, 200..=299 =\u003e StatusCategory::Success, 300..=399 =\u003e StatusCategory::Redirection, 400..=499 =\u003e StatusCategory::ClientError, 500..=599 =\u003e StatusCategory::ServerError, _ =\u003e StatusCategory::Unknown, } } } ```- `解析安全头信息函数create_headers_result`:也是相对比较简单的,就是获取返回请求头里面有么有一些安全字段值,最后判断如果大于4个字段的话就设置`security_headers_ok`为`true`

```rust// 解析相关头信息 fn create_headers_result(\u0026self, headers: \u0026reqwest::header::HeaderMap) -\u003e SecurityHeaders { SecurityHeaders { strict_transport_security: headers.get(\"Strict-Transport-Security\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), content_security_policy: headers.get(\"Content-Security-Policy\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), x_content_type_options: headers.get(\"X-Content-Type-Options\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), x_frame_options: headers.get(\"X-Frame-Options\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), x_xss_protection: headers.get(\"X-XSS-Protection\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), referrer_policy: headers.get(\"Referrer-Policy\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), feature_policy: headers.get(\"Feature-Policy\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), permissions_policy: headers.get(\"Permissions-Policy\").as_ref().map(|v| v.to_str().unwrap_or(\"\").to_string()), security_headers_ok: self.check_security_headers_ok(\u0026headers), } } // 检测是否安全头有效 fn check_security_headers_ok(\u0026self, headers: \u0026reqwest::header::HeaderMap) -\u003e bool { let mut score = 0; if headers.get(\"Strict-Transport-Security\").is_some() { score += 1; } if headers.get(\"Content-Security-Policy\").is_some() { score += 1; } if headers.get(\"X-Content-Type-Options\").is_some() { score += 1; } if headers.get(\"X-Frame-Options\").is_some() { score += 1; } if headers.get(\"X-XSS-Protection\").is_some() { score += 1; } if headers.get(\"Referrer-Policy\").is_some() { score += 1; } if headers.get(\"Permissions-Policy\").is_some() { score += 1; } score \u003e= 4 // 例如,至少有4个安全头部存在则认为安全头部检查通过 }```- `获取性能指标参数函数create_performance_timings`:这里的话reqwest并没有直接提供获取DNS、TCP、TLS相关的数据指标,所以这里的话我们还需要定义另外的方法来实现

```rust// 获取性能参数fn create_performance_timings(\u0026self, start_time: std::time::Instant, start_time_unix: u128) -\u003e PerformanceTimings { let total_time = start_time.elapsed().as_millis(); PerformanceTimings { dns_lookup_time: 0, tcp_connect_time: 0, tls_handshake_time: 0, first_byte_time: 0, // mor content_download_time: 0, ssl_negotiation_time: 0, ssl_cert_valid: true, request_sending_time: start_time_unix, server_processing_time: 0, response_receiving_time: total_time, total_time: total_time, }}

// 单独定义一个获取TCP 、DNS、TLS的函数

//定义一个函数返回类型 一个元组即可type DnsTcpTlsPerformance = (u128, u128, u128, Option\u003cCertificateInfo\u003e); // DNS时间,TCP时间,TLS时间,证书信息

// 计算 性能监控相关数据 DNS TCP TLS 三个数据耗时 以及在连接过程中SSL证书相关信息pub async fn get_dns_tcp_tls_performance(url: \u0026str) -\u003e Result\u003cDnsTcpTlsPerformance, Box\u003cdyn std::error::Error\u003e\u003e { // 使用Url进行解析相关的地址 let url = reqwest::Url::parse(url)?; let host = url.host_str().ok_or(\"Invalid URL\")?; let port = url.port_or_known_default().unwrap_or(80); let resolver = TokioAsyncResolver::tokio_from_system_conf()?; let dns_lookup_time =Instant::now(); let ips = resolver.lookup_ip(host).await?; // 开始设置DNS的缓存时间 let dns_lookup_ms = dns_lookup_time.elapsed().as_millis(); // 开始设置TCP的缓存时间 以及 TLS的时间 // 遍历相关的IP 地址 取其中最小的一个时间即可 let mut tls_min_time: Option\u003cu128\u003e = None; let mut tcp_min_time: Option\u003cu128\u003e = None;

let per_addr_timeout = Duration::from_secs(3); let is_https = url.scheme() == \"https\"; // 复用 TLS 连接器 let tls_connector = if is_https { Some(TokioTlsConnector::from(TlsConnector::new()?)) } else { None }; let mut ssl_certificate_info: Option\u003cCertificateInfo\u003e = None; for ip in ips.iter(){ let addr = std::net::SocketAddr::new(ip, port); let start_tcp = Instant::now(); // 设置一个超时时间 避免个别IP无法连接阻塞后续的连接 let tcp_res = timeout(per_addr_timeout, TcpStream::connect(addr)).await; let tcp_stream = match tcp_res { Ok(Ok(stream)) =\u003e { let ms = start_tcp.elapsed().as_millis(); // 设置TCP链接时间 tcp_min_time = tcp_min_time.map_or(Some(ms), |min| Some(min.min(ms))); stream }, _ =\u003e continue, // 超时或连接失败,尝试下一个地址 }; if let Some(tls) = \u0026tls_connector { let hs_start = Instant::now(); let hs_res = timeout(per_addr_timeout, tls.connect(host, tcp_stream)).await; if let Ok(Ok(_tls_stream)) = hs_res { let ms = hs_start.elapsed().as_millis(); // 设置TLS的连接时间 tls_min_time = tls_min_time.map_or(Some(ms), |min| Some(min.min(ms))); // 检测证书有效性可以在这里进行 if ssl_certificate_info.is_none() { if let Some(cert) = _tls_stream.get_ref().peer_certificate()? { let cert_der = cert.to_der()?; // from_der 返回 nom::IResult,需要手动 map_err let (_, x509_cert) = X509Certificate::from_der(\u0026cert_der) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!(\"x509 parse error: {e}\")))?;

let validity = x509_cert.validity(); let now = std::time::SystemTime::now(); let not_before = validity.not_before.to_datetime(); let not_after = validity.not_after.to_datetime(); let days_until_expiry = (not_after - now).whole_days(); // 这里的话需要查看相关的API文档来获取相关的库的信息 let info = CertificateInfo { issuer: Some(x509_cert.issuer().to_string()), subject: Some(x509_cert.subject().to_string()), valid_from: Some(not_before.to_string()), valid_until: Some(not_after.to_string()), serial_number: Some(x509_cert.tbs_certificate.serial.to_string()), signature_algorithm: Some(x509_cert.signature_algorithm.algorithm.to_string()), public_key_algorithm: Some(format!(\"{:?}\", x509_cert.public_key().algorithm)), public_key_size: Some(x509_cert.public_key().subject_public_key.data.len() * 8), // 转换为位数 is_valid: days_until_expiry \u003e 0, }; ssl_certificate_info = Some(info); } } } } } let tcp = tcp_min_time.ok_or(\"all TCP connect attempts failed\")?; let tls = if is_https { tls_min_time.unwrap_or(0) } else { 0 }; // 返回相关结果 Ok((dns_lookup_ms, tcp, tls, ssl_certificate_info))} ```- `创建响应内容校验函数create_content_verification_result`:我们获取到body内容,然后执行相关的校验逻辑即可,

```rust // 创建内容验证结果fn create_content_verification_result(\u0026self,body: String, rules: \u0026Option\u003cVec\u003cContentVerificationRulesSingle\u003e\u003e) -\u003e ContentVerificationResult { // 判空处理 if(rules.is_none() || body.is_empty()){ return ContentVerificationResult { match_rules: vec![], failed_rules: vec![], }; } let rules = rules.as_ref().unwrap(); let mut match_rules = vec![]; let mut failed_rules = vec![];

for ContentVerificationRulesSingle{rule_type, rule_content,rule_description } in rules.iter() { let status = match rule_type { // 是否包含哪些内容? ContentVerificationRules::Contains =\u003e { body.contains(rule_content) }, // 是否不包含哪些内容? ContentVerificationRules::NotContains =\u003e { !body.contains(rule_content) }, // 匹配正则表达式 ContentVerificationRules::Regex =\u003e { let regex = Regex::new(\u0026rule_content).unwrap(); regex.is_match(\u0026body) }, _ =\u003e { false }, }; self.get_content_verify_result(status, rule_type.clone(), rule_content.clone(), rule_description.clone(), \u0026mut match_rules, \u0026mut failed_rules);

} ContentVerificationResult { match_rules: match_rules, failed_rules: failed_rules, }}// 拼接内容校验的内容 因为不管是什么类型 返回的数据结构都是一样的fn get_content_verify_result(\u0026self, status: bool, rule_type: ContentVerificationRules, rule_content: String, rule_description: String, true_Rules: \u0026mut Vec\u003cContentVerificationRulesResult\u003e, failed_Rules: \u0026mut Vec\u003cContentVerificationRulesResult\u003e) { let result = ContentVerificationRulesResult { rule_id: Uuid::new_v4().as_u128() as u64, status: if status { StatusInfo::Success } else { StatusInfo::Failed }, message: if status { \"Rule verification passed\".to_string() } else { \"Rule verification failed\".to_string() }, rules: ContentVerificationRulesSingle{rule_type: rule_type.clone(),rule_content: rule_content.clone(),rule_description: rule_description.clone()} }; if status { true_Rules.push(result); } else { failed_Rules.push(result); }}```上面的这几个函数定义完来的话,其实我们的HTTP监控引擎的内容就已经全部完成了,现在我们最后来看下HTTP监控中我们待完成的那一段代码就可以了:

```rustimpl Monitor for HttpMonitor { async fn check(\u0026self, config: \u0026MonitorConfig)-\u003eCheckResult{ // 判空逻辑 上面写过了 这里就不赘述了 ... // 为了记录请求发送时间 let start_time_instant = std::time::Instant::now(); match config.details { MonitorConfigDetail::Http(ref detail) =\u003e { // 获取一个http 链接 let request_client = self.get_client(detail); match request_client.send().await{ Ok(response)=\u003e{ // ?️点,?️点,?️点 // 获取状态码 let (dns_lookup_time, tcp_connect_time, tls_handshake_time, ssl_certificate_info) = match get_dns_tcp_tls_performance(config.target.as_ref().unwrap()).await { Ok(performance) =\u003e performance, Err(_) =\u003e (0, 0, 0, None), }; // 提取需要的数据 let status_code = response.status().as_u16(); let version = response.version(); let headers = response.headers().clone(); let content_length = response.content_length(); // 因为这里的代码会获取所有权 所以后面就没办法直接用response了 所以上面就单独获取response中的字段值用在后面的方法中 let body = response.text().await.unwrap_or_default(); // 创建基本结果和头部结果 let basic_avaliable = self.create_basic_result(status_code, version, \u0026headers, content_length); let response_headers = self.create_headers_result(\u0026headers); let performance_timings = PerformanceTimings { dns_lookup_time, tcp_connect_time, tls_handshake_time, ..self.create_performance_timings(start_time_instant, unix_now_ms()) }; return CheckResult { id: uuid::Uuid::new_v4().as_u128(), // V4 uuid 一种随机数 基于时间戳和随机数 V4版本的生成功能 monitor_type: MonitorType::Http, target: config.target.clone(), status: true, // 代表监控状态为成功,但是target访问失败了 details: CheckResultDetail::Http(HttpMonitorResult { basic_avaliable, response_headers, performance_timings, certificate_info: ssl_certificate_info.unwrap_or_default(), content_verification: self.create_content_verification_result(body, \u0026detail.rules), advanced_avaliable: self.create_advanced_availability_result(), }) } }, Err(_)=\u003e{ .... } } }, _=\u003e{ // 其他类型 上面也写过了 ... } }

}}

```

如果您能坚持学习到这里,那么恭喜——我们的代码实现部分已经圆满完成!

回顾整个开发过程,其实我们一直在进行一场精妙的\"填空游戏\":先搭建起整体的框架结构,再逐步填充每个模块的具体实现。这种由宏观到微观的开发方式,能够让我们始终保持清晰的思路,即使面对复杂系统也不会迷失方向。

在这个过程中,我自己的开发经历也是如此——从最初对各个模块的陌生,到逐步拆解需求、研究技术细节,最终独立完成整个功能的实现。这段经历让我深刻体会到,对于初学者而言,**勤于动手实践**至关重要。

至此,我们本阶段的实现就告一段落了。建议大家可以好好消化吸收这些内容,尝试自己动手扩展更多监控类型。期待在接下来的学习中与大家再次相遇!

过程问题\u0026\u0026解决方案1. **`#[async_trait::async_trait] `这种宏的作用是什么?** 答:它是 async-trait 宏,用来让 trait 里的异步方法可用。核心点: - Rust 原生的 `trait` 里写 `async fn(或返回 impl Future)在用作 trait object(如 Box\u003cdyn Monitor\u003e)`时不满足对象安全,编译不过。 - `#[async_trait::async_trait]` 会把你的 `async fn 自动展开成返回 Pin\u003cBox\u003cdyn Future\u003cOutput =  *\u003e + Send + '* \u003e\u003e `的形式,从而让 trait 可以作为 `dyn Trait` 使用。 ```rust // 原始写法 #[async_trait::async_trait] trait Monitor { async fn check(\u0026self, cfg: \u0026MonitorConfig) -\u003e CheckResult; }

// 展开后大致等价 trait Monitor { fn check\u003c'a\u003e(\u0026'a self, cfg: \u0026'a MonitorConfig) -\u003e core::pin::Pin\u003cBox\u003cdyn core::future::Future\u003cOutput = CheckResult\u003e + Send + 'a\u003e\u003e;} ```2. 在`src/async_monitor.rs`中使用`mpsc`、`Box::pin`、`tokio::spawn`都是用来干嘛的?答:把一个异步块变成“可返回/可存放”的 Future,用来统一返回类型并在堆上固定(Pin)它,便于在外部 await 与存入集合。要点解释: - `async move {...}`: 生成一个 `Future`,并把 `target、config` 的所有权移动进去,确保在 `tokio::spawn` 中满足 `'static` 要求。 - `Box::pin(...):` 把这个 `Future` 放到堆上并固定位置(Pin),再通过 `dyn Future` 做类型擦除,得到统一的返回类型 `PinnedReceiverFuture = Pin\u003cBox\u003cdyn Future\u003cOutput = mpsc::Receiver\u003c_\u003e\u003e + Send\u003e\u003e`。 - `mpsc通道`:函数里创建 `tx/r`x,后台循环每次 `check` 后用 `tx` 发送结果;函数本身返回 `rx`(通过 `await` 得到)。

写在最后诚然,本篇内容最初定位为企业级监控系统,但在实际开发过程中,我才深刻体会到什么叫做“无知者无畏”。若要真正打造一个称得上“企业级”的监控系统,需要考虑的维度远超想象。

在我看来,“可用”与“能用”之间那道看似无形的鸿沟,本质上是由**用户规模**与**资金投入**共同决定的。当用户量达到一定规模时,那些在 demo 阶段看似无足轻重的细节——比如性能瓶颈、数据一致性、高可用架构——都会骤然成为系统稳定性的致命缺口。而一旦涉及资金流转或商业损失,对系统的可靠性要求更是会跃升至全新的量级。

因此,很多时候我们认为“简单”的系统或功能,其实并非真的简单,只是尚未经历大规模用户与真实资金的考验。本次我们实现的,仅仅是其中一个基础的 HTTP 监控模块,距离完整的企业级方案仍有大量功能有待完善。

但即便如此,对于一名初学者而言,能够一步步走完这个从零到一的过程,理解监控系统的核心架构与实现逻辑,已经是极具价值的成长。愿这份实践经验,能成为你走向更复杂系统设计的坚实第一步。

在AI技术如此普及的今天,我想特别分享一点心得:请不要过度依赖AI的代码生成能力。优秀的开发者应该将AI视为提升效率的**工具**,而非替代思考的**大脑**。重要的是保持自己的思考主导权——**由你来驾驭技术,而不是被技术所驾驭**。


# column  # 循环  # 数据结构  #   # Struct  # Regex  # 线程  # 多线程  # len  # map  # delete  # 并发  # channel  # 对象  # default  # 异步  # bool  # 算法  # http  # https  # udp  # 内容检测  # 创建一个  # 随机数  # 都是  # 是否存在  # 在这里  # 让我们  # 自己的  # 监控系统  # 这是  # 相关信息  # Static  # git  # json  # go  # 正则表达式  # github  # 字节  # 工具  # ssl  # ai  # unix  # dns  # cdn  # rust  # 架构  # xss  # js  # String  # Object  # if  # for  # while  # 封装  # 多态  # format  # Error  # 枚举类型  # continue  # enum  # 字符串  # 结构体 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化91478 】 【 技术知识72672 】 【 云计算0 】 【 GEO优化84317 】 【 优选文章0 】 【 营销推广36048 】 【 网络运营41350 】 【 案例网站102563 】 【 AI智能45237


相关推荐: AI电子书写作终极指南:ChatGPT和Canva实战教程  提升效率:使用AI代理自动生成视频标题的实用指南  百度输入法蓝色图标怎么关 百度输入法ai图标消除  终极游戏工作站:帝王蝎椅沉浸式体验评测  普通人如何用DeepSeek月入过万?2026最新赚钱路径全解析!  Filmora AI 语音增强和降噪终极指南  Excel AI:5大免费AI功能提升数据分析效率  2025年AI招聘大师班:初学者友好且功能强大  Google Gemini 辅助进行 Android Studio 代码开发  提升房地产业务:AI语音助手赋能房地产经纪公司  如何用AI一键给视频自动加字幕  通义万相做小红书配图怎么用_通义万相做小红书配图使用方法详细指南【教程】  播客数据深度解析:揭秘全球听众分布和增长策略  Depseek能否批量生成部门总结_Depseek多部门总结批量生成步骤【方法】  软件测试进化史:从手动到AI,迎接测试新纪元  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  ChatGPT 4o 辅助学生复习 GRE 词汇的方法  Vizeo AI视频生成器:无需技术,轻松打造营销利器  轻松生成二维码:免费AI工具终极指南  tofai怎么调整层级顺序 tofai图层上下移动方法【步骤】  利用 DeepSeek 辅助进行编译器原理课程学习  怎么用ai写产品说明书 AI功能介绍与使用步骤详解【实操】  百度浏览器ai助手怎么关闭 百度浏览器ai功能禁用  通义千问怎样写文案_通义千问文案写作教程【指南】  N8N 自动化教程:HR 简历智能分析系统搭建指南  提升效率的AI工具:Jace、Yutori、Dia等效率神器测评  Claude怎么用新功能故事创作_Claude故事创作使用【方法】  tofai官方网站入口 tofai在线网页版登录  Semrush Summary Generator: 高效总结长篇文章的终极指南  New You KIN Skin Analyzer:焕发肌肤新生的终极指南  AI如何一键生成PPT大纲_利用AI工具制作演示文稿方法【教程】  ChatGPT一键生成PPT怎么加目录_ChatGPTPPT目录添加【步骤】  暖心“小艺通话”:让语障人士告别沟通困境,拥抱平等生活  提升企业效率:QR Platform管理后台功能全面解析  ChatGPT如何进行数据可视化构思 ChatGPT图表设计指南  通义万相做海报怎么用_通义万相做海报使用方法详细指南【教程】  AI Notebooks: 知识工作者的未来?赋能理解与洞察的工具  lovemo网页版地址 lovemo官网手机登录  ChatGPT一键生成PPT怎么加内容_ChatGPTPPT内容添加【方法】  百度AI搜索怎么用语音提问_百度AI搜索语音输入与识别优化【指南】  5分钟教你用AI生成短视频分镜脚本,小白也能拍大片  AI简历优化指南:如何让你的简历轻松通过ATS筛选系统  一键改变发型:Gemini AI 助你轻松打造时尚造型  智行ai抢票能否抢下铺票_智行ai抢票下铺优先设置与成功率提升【技巧】  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  动态规划解题:攀登楼梯的独特方法与技巧  Pictory AI视频制作平台深度评测:功能、价格与使用指南  Gemini 与 Google Drive 结合的文件智能检索  利用 ChatGPT 设计高效的个人健身与饮食计划  佐糖AI抠图如何免费使用_佐糖AI免费额度获取与消耗查看【指南】 

 2025-12-03

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

南京市珐之弘网络技术有限公司


南京市珐之弘网络技术有限公司

南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 87067657

 13565296790

 87067657@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.