Rust网络编程实战:全面掌握reqwest库的高级用法
一、开篇导引
1.1 对比Python Requests解释为何reqwest是Rust生态的标杆HTTP客户端
在Python生态中,Requests
库以其简洁易用的API成为了HTTP客户端的首选。它使得开发者能够轻松地发送各种HTTP请求,处理响应,而无需过多关注底层细节。然而,Python作为一种解释型语言,在性能和并发处理方面存在一定的局限性。
Rust的 reqwest
库则在性能、安全性和并发处理上展现出了强大的优势。reqwest
是基于Rust的异步运行时构建的,它充分利用了Rust的所有权系统和类型系统,能够高效地处理大量并发请求,同时保证内存安全。与Python的 Requests
相比,reqwest
在处理高并发场景时,性能提升显著。例如,在处理大量的API请求时,reqwest
能够在更短的时间内完成更多的请求,并且占用更少的系统资源。
1.2 适用场景分析:何时选择reqwest而非hyper/ureq等其他库
库名 | 适用场景 | 原因 |
---|---|---|
reqwest | 高并发的Web服务、API客户端、爬虫开发 | 提供了简洁的API,同时支持异步和同步模式,易于使用和扩展。 |
hyper | 底层HTTP服务开发、自定义HTTP协议实现 | 是一个底层的HTTP库,提供了更细粒度的控制,但API相对复杂。 |
ureq | 简单的HTTP请求、脚本化的网络操作 | 轻量级的HTTP库,API简单,但功能相对较少。 |
适用场景:在需要处理大量并发请求的场景下,如Web服务的API调用、爬虫开发等,reqwest
是更好的选择。而对于需要自定义HTTP协议或进行底层HTTP服务开发的场景,hyper
更合适。如果只是进行简单的HTTP请求,ureq
则可以满足需求。
二、核心功能详解
2.1 基础篇
2.1.1 同步/异步双模式配置
reqwest
支持同步和异步两种模式,开发者可以根据具体需求选择合适的模式。
// 同步模式(blocking模式)
use reqwest::blocking::get;fn main() -> Result<(), reqwest::Error> {let response = get("<https://httpbin.org/json>")?;println!("Status: {}", response.status());println!("Body: {}", response.text()?);Ok(())
}// 异步模式
use reqwest;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let response = reqwest::get("<https://httpbin.org/json>").await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:同步模式下,程序会阻塞直到请求完成,适合简单的脚本或对并发要求不高的场景。异步模式下,请求会在后台执行,程序可以继续执行其他任务,适合高并发场景。
适用场景:脚本化的网络操作可以使用同步模式,而高并发的Web服务或爬虫开发则应使用异步模式。
2.1.2 请求构建器模式(Builder Pattern)
请求构建器模式允许开发者通过链式调用的方式构建复杂的请求。
use reqwest;
use std::time::Duration;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::new();let url = "<https://httpbin.org/post>";let response = client.post(url).header("X-Custom-Header", "value").timeout(Duration::from_secs(30)).basic_auth("user", Some("pass")).send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:reqwest::Client::new()
创建一个客户端实例,通过链式调用 post()
、header()
、timeout()
等方法可以设置请求的各种参数,最后调用 send()
方法发送请求。
适用场景:需要设置多个请求参数的场景,如发送带有自定义头部、认证信息和超时设置的请求。
2.2 进阶篇
2.2.1 连接池调优(keep-alive配置)
连接池可以复用已经建立的连接,减少连接建立和关闭的开销,提高性能。
use reqwest;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::builder().pool_idle_timeout(std::time::Duration::from_secs(30)) // ⚠️ 空闲连接的超时时间.pool_max_idle_per_host(5) // ⚠️ 每个主机的最大空闲连接数.build()?;let response = client.get("<https://httpbin.org/json>").await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:reqwest::Client::builder()
用于创建一个可配置的客户端实例,通过 pool_idle_timeout()
和 pool_max_idle_per_host()
方法可以设置连接池的参数。
适用场景:需要频繁发送请求的场景,如API客户端或爬虫开发。
2.2.2 自动重试与超时策略
可以通过自定义重试逻辑和超时设置来处理请求失败的情况。
use reqwest;
use std::time::Duration;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::builder().timeout(Duration::from_secs(5)) // ⚠️ 请求超时时间.build()?;let mut retry_count = 0;let max_retries = 3;loop {match client.get("<https://httpbin.org/json>").await {Ok(response) => {println!("Status: {}", response.status());println!("Body: {}", response.text().await?);break;}Err(err) => {if retry_count >= max_retries {return Err(err);}retry_count += 1;println!("Request failed, retrying ({}/{})...", retry_count, max_retries);}}}Ok(())
}
操作原理说明:通过 timeout()
方法设置请求超时时间,使用循环和计数器实现自动重试逻辑。
适用场景:网络不稳定的环境下,如移动网络或跨地域的请求。
2.2.3 多部分文件上传(multipart/form-data)
可以使用 reqwest
进行多部分文件上传。
use reqwest;
use std::fs::File;
use std::io::BufReader;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::new();let file = File::open("example.txt")?;let reader = BufReader::new(file);let form = reqwest::multipart::Form::new().text("field1", "value1").part("file", reqwest::multipart::Part::reader(reader).file_name("example.txt"));let response = client.post("<https://httpbin.org/post>").multipart(form).send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:使用 reqwest::multipart::Form::new()
创建一个表单实例,通过 text()
和 part()
方法添加表单字段和文件,最后使用 multipart()
方法将表单添加到请求中。
适用场景:需要上传文件的场景,如图片上传、文件备份等。
2.2.4 代理服务器与TOR网络集成
可以通过设置代理服务器来隐藏请求的真实来源,也可以集成TOR网络实现匿名请求。
use reqwest;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let proxy = reqwest::Proxy::http("<http://proxy.example.com:8080>")?;let client = reqwest::Client::builder().proxy(proxy).build()?;let response = client.get("<https://httpbin.org/json>").await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:使用 reqwest::Proxy::http()
创建一个代理实例,通过 proxy()
方法将代理添加到客户端中。
适用场景:需要隐藏请求来源或突破网络限制的场景,如爬虫开发、网络测试等。
2.2.5 Cookie持久化实战
可以将Cookie存储到文件中,实现Cookie的持久化。
use reqwest;
use std::fs::File;
use std::io::{Read, Write};
use serde_json;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::new();let response = client.get("<https://httpbin.org/cookies/set?name=value>").await?;let cookies = response.cookies().cloned().collect::<Vec<_>>();let cookies_json = serde_json::to_string(&cookies)?;let mut file = File::create("cookies.json")?;file.write_all(cookies_json.as_bytes())?;println!("Cookies saved to cookies.json");Ok(())
}
操作原理说明:通过 response.cookies()
方法获取响应中的Cookie,使用 serde_json
将Cookie序列化为JSON字符串,最后将JSON字符串写入文件。
适用场景:需要保持会话状态的场景,如登录后的后续请求。
2.3 企业级特性
2.3.1 自定义TLS后端(rustls vs native-tls)
reqwest
支持使用 rustls
或 native-tls
作为TLS后端。
use reqwest;
use reqwest::ClientBuilder;
use rustls::ClientConfig;
use rustls::RootCertStore;
use webpki_roots::TLS_SERVER_ROOTS;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let mut root_store = RootCertStore::empty();root_store.add_server_trust_anchors(TLS_SERVER_ROOTS.0.iter().map(|ta| {rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(ta.subject,ta.spki,ta.name_constraints,)}));let tls_config = ClientConfig::builder().with_safe_defaults().with_root_certificates(root_store).with_no_client_auth();let client = ClientBuilder::new().use_rustls_tls().tls_config(tls_config).build()?;let response = client.get("<https://httpbin.org/json>").await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:通过 ClientBuilder::new()
创建一个可配置的客户端实例,使用 use_rustls_tls()
方法指定使用 rustls
作为TLS后端,通过 tls_config()
方法设置TLS配置。
适用场景:对TLS安全性有较高要求的场景,如金融交易、敏感数据传输等。
2.3.2 请求/响应拦截器(类似Axios的interceptor)
可以通过自定义中间件实现请求/响应拦截器。
use reqwest;
use reqwest::ClientBuilder;
use reqwest_middleware::{ClientBuilder as MiddlewareClientBuilder, RequestBuilder, Result};
use reqwest_tracing::TracingMiddleware;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = ClientBuilder::new().build()?;let middleware_client = MiddlewareClientBuilder::new(client).with(TracingMiddleware::default()).build();let request = middleware_client.get("<https://httpbin.org/json>");let response = request.send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:使用 reqwest_middleware
库创建一个带有中间件的客户端,通过 with()
方法添加中间件,中间件可以在请求发送前和响应返回后进行拦截和处理。
适用场景:需要对请求和响应进行统一处理的场景,如日志记录、错误处理等。
2.3.3 分布式追踪集成(OpenTelemetry)
可以将 reqwest
与 OpenTelemetry
集成,实现分布式追踪。
use reqwest;
use opentelemetry::global;
use opentelemetry::sdk::trace as sdktrace;
use opentelemetry::trace::Tracer;
use reqwest_middleware::ClientBuilder;
use reqwest_tracing::TracingMiddleware;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let tracer = init_tracer();let client = reqwest::Client::new();let middleware_client = ClientBuilder::new(client).with(TracingMiddleware::default()).build();let span = tracer.start("http_request");let _guard = span.enter();let response = middleware_client.get("<https://httpbin.org/json>").send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);span.end();global::shutdown_tracer_provider();Ok(())
}fn init_tracer() -> impl Tracer {let tracer = sdktrace::TracerProvider::builder().with_simple_exporter(sdktrace::stdout::new_exporter()).build();global::set_tracer_provider(tracer);global::tracer("reqwest_example")
}
操作原理说明:使用 opentelemetry
库创建一个追踪器,通过 reqwest_middleware
和 reqwest_tracing
库将追踪器集成到 reqwest
客户端中,在请求发送时记录追踪信息。
适用场景:分布式系统中,需要对请求进行追踪和性能分析的场景。
2.3.4 压力测试与性能调优指标
可以使用 wrk
等工具对 reqwest
应用进行压力测试,通过调整连接池大小、超时时间等参数进行性能调优。
配置参数 | 吞吐量(请求/秒) | 响应时间(毫秒) |
---|---|---|
默认配置 | 1000 | 50 |
连接池大小=100 | 1500 | 40 |
超时时间=10秒 | 1200 | 60 |
适用场景:需要对应用的性能进行评估和优化的场景,如生产环境的性能调优。
三、实战项目演示
3.1 构建带有缓存层的REST API客户端
可以使用 reqwest
构建一个带有缓存层的REST API客户端,减少重复请求。
use reqwest;
use std::collections::HashMap;
use std::time::Duration;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let mut cache: HashMap<String, String> = HashMap::new();let client = reqwest::Client::new();let url = "<https://httpbin.org/json>";if let Some(cached_response) = cache.get(url) {println!("Using cached response: {}", cached_response);} else {let response = client.get(url).timeout(Duration::from_secs(5)).send().await?;let body = response.text().await?;cache.insert(url.to_string(), body.clone());println!("New response: {}", body);}Ok(())
}
操作原理说明:使用 HashMap
作为缓存,在发送请求前先检查缓存中是否存在该请求的响应,如果存在则直接使用缓存,否则发送请求并将响应存入缓存。
适用场景:需要频繁访问相同API的场景,如数据查询、配置获取等。
3.2 实现自动切换代理的爬虫框架
可以使用 reqwest
实现一个自动切换代理的爬虫框架,提高爬虫的稳定性。
use reqwest;
use std::time::Duration;
use rand::seq::SliceRandom;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let proxies = vec!["<http://proxy1.example.com:8080>","<http://proxy2.example.com:8080>","<http://proxy3.example.com:8080>",];let mut rng = rand::thread_rng();let client = reqwest::Client::builder().timeout(Duration::from_secs(10)).build()?;let url = "<https://httpbin.org/json>";let mut retry_count = 0;let max_retries = 3;loop {let proxy = proxies.choose(&mut rng).unwrap();let proxy_obj = reqwest::Proxy::http(proxy)?;let proxy_client = client.clone().proxy(proxy_obj);match proxy_client.get(url).send().await {Ok(response) => {println!("Status: {}", response.status());println!("Body: {}", response.text().await?);break;}Err(err) => {if retry_count >= max_retries {return Err(err);}retry_count += 1;println!("Request failed with proxy {}, retrying ({}/{})...", proxy, retry_count, max_retries);}}}Ok(())
}
操作原理说明:首先定义一个代理列表,使用 rand
库随机选择一个代理。创建一个 reqwest
客户端,并通过 proxy()
方法设置代理。发送请求,如果请求失败则重试,最多重试 max_retries
次,每次重试时重新选择代理。
适用场景:Web 爬虫开发,尤其是在需要突破网站反爬机制或应对网络限制的情况下,自动切换代理可以提高爬虫的稳定性和成功率。
3.3 与 Serde 深度集成的类型安全 HTTP 交互
可以结合 reqwest
和 serde
实现类型安全的 HTTP 交互,将响应数据自动反序列化为 Rust 结构体。
use reqwest;
use serde::Deserialize;#[derive(Debug, Deserialize)]
struct ExampleResponse {origin: String,headers: serde_json::Value,
}#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::new();let url = "<https://httpbin.org/json>";let response = client.get(url).send().await?;let data: ExampleResponse = response.json().await?;println!("Origin: {}", data.origin);println!("Headers: {:?}", data.headers);Ok(())
}
操作原理说明:定义一个 Rust 结构体 ExampleResponse
,并使用 serde
的 Deserialize
特性进行标注。发送 HTTP 请求后,使用 response.json().await?
方法将响应数据自动反序列化为 ExampleResponse
结构体。
适用场景:与 API 进行交互时,需要将响应数据进行结构化处理的场景,如解析 JSON 数据、处理 XML 数据等,类型安全的交互可以避免手动解析数据时可能出现的错误。
四、调试技巧
4.1 使用 reqwest - middleware 增强日志
reqwest - middleware
可以帮助我们记录请求和响应的详细信息,方便调试。
use reqwest;
use reqwest_middleware::{ClientBuilder, Result};
use reqwest_tracing::TracingMiddleware;
use tracing_subscriber::FmtSubscriber;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let subscriber = FmtSubscriber::builder().with_max_level(tracing::Level::DEBUG).finish();tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");let client = reqwest::Client::new();let middleware_client = ClientBuilder::new(client).with(TracingMiddleware::default()).build();let response = middleware_client.get("<https://httpbin.org/json>").send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:使用 tracing_subscriber
配置日志级别为 DEBUG
,通过 reqwest_middleware
和 reqwest_tracing
库将日志功能集成到 reqwest
客户端中。在请求发送和响应返回时,会记录详细的日志信息。
适用场景:开发和调试阶段,需要详细了解请求和响应信息的场景。
4.2 通过 mitmproxy 抓包分析
mitmproxy
是一个强大的抓包工具,可以拦截和分析 HTTP 请求和响应。
- 启动
mitmproxy
:在终端中运行mitmproxy
命令。 - 配置
reqwest
客户端使用mitmproxy
代理:
use reqwest;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let proxy = reqwest::Proxy::http("<http://127.0.0.1:8080>")?;let client = reqwest::Client::builder().proxy(proxy).build()?;let response = client.get("<https://httpbin.org/json>").send().await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:启动 mitmproxy
后,它会在本地监听 8080
端口。配置 reqwest
客户端使用该代理,所有的请求和响应都会经过 mitmproxy
,可以在 mitmproxy
的界面中查看详细信息。
适用场景:需要分析请求和响应的具体内容,排查网络问题的场景。
4.3 常见错误代码速查表
错误代码 | 含义 | 解决方法 |
---|---|---|
CE3023 | 连接池耗尽 | 增加连接池大小,检查是否有大量未释放的连接 |
E0433 | 找不到类型或模块 | 检查依赖是否正确安装,模块路径是否正确 |
E0308 | 类型不匹配 | 检查变量类型,确保数据类型一致 |
适用场景:在开发和调试过程中,遇到错误代码时可以快速查找原因和解决方法。
五、扩展阅读
5.1 与 tower 生态的集成路径
tower
是一个用于构建异步服务的模块化框架,reqwest
可以与 tower
生态集成,实现更复杂的中间件和服务组合。
use reqwest;
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let client = reqwest::Client::builder().build()?;let service = ServiceBuilder::new().layer(TraceLayer::new_for_http()).service(client);let request = reqwest::Request::builder().method(reqwest::Method::GET).uri("<https://httpbin.org/json>").body(None).unwrap();let response = service.call(request).await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:使用 ServiceBuilder
构建一个服务,通过 layer()
方法添加 TraceLayer
中间件,将 reqwest
客户端作为服务的底层实现。
适用场景:需要构建复杂的异步服务,对请求进行更精细处理的场景。
5.2 基于 reqwest 构建 SDK 的设计模式
可以基于 reqwest
构建 SDK,常见的设计模式有工厂模式、单例模式等。
use reqwest;pub struct MySdk {client: reqwest::Client,
}impl MySdk {pub fn new() -> Self {let client = reqwest::Client::new();MySdk { client }}pub async fn get_data(&self, url: &str) -> Result<reqwest::Response, reqwest::Error> {self.client.get(url).send().await}
}#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {let sdk = MySdk::new();let response = sdk.get_data("<https://httpbin.org/json>").await?;println!("Status: {}", response.status());println!("Body: {}", response.text().await?);Ok(())
}
操作原理说明:定义一个 MySdk
结构体,在 new()
方法中创建 reqwest
客户端。通过 get_data()
方法封装请求逻辑,提供统一的接口供外部调用。
适用场景:开发面向第三方的 SDK,需要对 reqwest
进行封装和抽象的场景。
5.3 WASM 环境下的特殊限制
在 WebAssembly(WASM)环境下使用 reqwest
有一些特殊限制,如不支持同步请求,需要使用异步请求。
use wasm_bindgen_futures::spawn_local;
use reqwest;#[wasm_bindgen(start)]
pub async fn main() -> Result<(), reqwest::Error> {let response = reqwest::get("<https://httpbin.org/json>").await?;let text = response.text().await?;console_log!("Response: {}", text);Ok(())
}
操作原理说明:在 WASM 环境下,使用 wasm_bindgen_futures::spawn_local
来执行异步任务,使用 reqwest::get()
方法发送异步请求。
适用场景:开发基于 WebAssembly 的前端应用,需要进行网络请求的场景。
流程图和时序图
自动切换代理的爬虫框架流程图
带有缓存层的 REST API 客户端流程图
与 Serde 集成的类型安全 HTTP 交互时序图
Cargo.toml 依赖模板
[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.8"
tracing = "0.1"
tracing-subscriber = "0.3"
reqwest-middleware = "0.10"
reqwest-tracing = "0.6"
tower = "0.4"
tower-http = "0.4"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
各功能的 MSRV(最低支持 Rust 版本)
功能 | MSRV |
---|---|
基础功能 | 1.46.0 |
异步模式 | 1.46.0 |
连接池调优 | 1.46.0 |
自动重试与超时策略 | 1.46.0 |
多部分文件上传 | 1.46.0 |
代理服务器与 TOR 网络集成 | 1.46.0 |
Cookie 持久化 | 1.46.0 |
自定义 TLS 后端 | 1.46.0 |
请求/响应拦截器 | 1.46.0 |
分布式追踪集成 | 1.46.0 |
与 Serde 集成 | 1.46.0 |
与 tower 生态集成 | 1.46.0 |
WASM 环境支持 | 1.46.0 |
通过以上内容,你可以全面深入地掌握 reqwest
库的高级用法,无论是在开发生产级的 HTTP 客户端,还是构建复杂的网络应用,都能游刃有余。
相关文章:
Rust网络编程实战:全面掌握reqwest库的高级用法
一、开篇导引 1.1 对比Python Requests解释为何reqwest是Rust生态的标杆HTTP客户端 在Python生态中,Requests 库以其简洁易用的API成为了HTTP客户端的首选。它使得开发者能够轻松地发送各种HTTP请求,处理响应,而无需过多关注底层细节。然而…...
【漫话机器学习系列】211.驻点(Stationary Points)
驻点(Stationary Points):理解函数导数为零的关键位置 在数学分析、机器学习优化、物理建模等领域中,驻点(Stationary Points)是一个非常重要的概念。它们是函数图像中“停下来的点”,即导数为…...
图 - 最小生成树算法 - Kruskal - Prim
目录 前言 什么是最小生成树算法 Kruskal 克鲁斯卡尔 Prim 普利姆 结语 前言 在图中一共有两类算法,一种是最短路径,还有一种就是本篇要讲解的最小生成树算法了 其中,最短路径一共有三种,而最小生成树一共有两种ÿ…...
linux kernel irq相关函数详解
在Linux内核驱动开发中,处理中断涉及一系列关键函数,正确使用这些函数对确保驱动的稳定性和性能至关重要。以下是disable_irq、free_irq、platform_get_irq和request_irq等函数的详细解析,涵盖其功能、用法、注意事项及示例代码。 一、核心函…...
聊聊Doris的数据模型,如何用结构化设计解决实时分析难题
传统 OLAP 系统的局限 在大数据实时分析领域,数据模型设计直接决定了系统的查询性能、存储效率与业务适配性。Apache Doris作为新一代MPP分析型数据库,通过独创的多模型融合架构,在业内率先实现了"一份数据支持多种分析范式"的能力…...
[Swift]Xcode模拟器无法请求http接口问题
1.以前偷懒一直是这样设置 <key>NSAppTransportSecurity</key> <dict><key>NSAllowsArbitraryLoads</key><true/> </dict> 现在我在Xcode16.3上,这种设置方式在真机上能请求http(应该是设备开启了开发者模式…...
kafka认证部署
首先启动 zookeeper /home/kafka/bin/zookeeper-server-start.sh /home/kafka/config/zookeeper.properties 创建SCRAM证书 /home/kafka/bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config SCRAM-SHA-256[iterations8192,passwordliebe],SCRAM-SHA-512[p…...
基于STM32中断讲解
基于STM32中断讲解 一、NVIC讲解 简介:当一个中断请求到达时,NVIC会确定其优先级并决定是否应该中断当前执行的程序,以便及时响应和处理该中断请求。这种设计有助于提高系统的响应速度和可靠性,特别是在需要处理大量中断请求的实…...
Java 动态代理教程(JDK 动态代理)(以RPC 过程为例)
1. 什么是动态代理 在运行时为指定的接口自动生成代理对象,并通过 invoke 方法增强了这些对象的功能 2. 两个核心组件 java.lang.reflect.Proxy类 这个类提供了方法:newProxyInstance()用来创建一个代理对象 public static Object newProxyInstance(…...
Linux Privilege Escalation: LD_PRELOAD
声明:本文所有操作需在授权环境下进行,严禁非法使用! 0x01 什么是 LD_PRELOAD? LD_PRELOAD 是 Linux 系统中一个特殊的环境变量,它允许用户在程序启动时优先加载自定义的动态链接库(.so 文件)&…...
Java 并发性能优化:线程池的最佳实践
Java 并发性能优化:线程池的最佳实践 在 Java 并发编程的世界里,线程池堪称提高应用性能与稳定性的神器。恰如其分地运用线程池,能让我们在多线程任务调度时游刃有余,既能避免线程频繁创建销毁带来的开销,又能合理管控…...
QML动画--ParallelAnimation和SequentialAnimation
一、ParallelAnimation ParallelAnimation 是 QML 中用于并行执行多个动画的容器动画类型,可以同时运行多个子动画。 基本用法 qml import QtQuick 2.15Rectangle {id: rectwidth: 100; height: 100color: "red"x: 0; y: 0; opacity: 1.0ParallelAnim…...
深入解析进程与线程:区别、联系及Java实现
引言 在现代操作系统中,进程和线程是并发编程的两大核心概念。理解它们的区别与联系对开发高性能、高可靠性的程序至关重要。本文将通过原理分析和Java代码示例,深入探讨这两个关键概念。 一、基本概念 1.1 进程(Process) 定义&…...
c++:线程(std::thread)
目录 从第一性原理出发:为什么需要线程? ✅ 本质定义: 📌 使用基本语法: 线程之间的“并发”与“并行”的区别 线程安全与数据竞争(Race Condition) 如何让线程“安全地”访问数据&#x…...
基于LSTM-AutoEncoder的心电信号时间序列数据异常检测(PyTorch版)
心电信号(ECG)的异常检测对心血管疾病早期预警至关重要,但传统方法面临时序依赖建模不足与噪声敏感等问题。本文使用一种基于LSTM-AutoEncoder的深度时序异常检测框架,通过编码器-解码器结构捕捉心电信号的长期时空依赖特征&#…...
[密码学基础]GM/T 0018-2023 密码设备应用接口规范深度解析:技术革新与开发者实践
GM/T 0018-2023 密码设备应用接口规范深度解析:技术革新与开发者实践 GM/T 0018-2023《密码设备应用接口规范》是中国密码行业的重要标准,于2023年12月4日发布,2024年6月1日正式实施,替代了2012年版标准。该标准旨在规范密码设备…...
深入理解 Java 多线程:锁策略与线程安全
文章目录 一、常见的锁策略1. 乐观锁&&悲观锁2. 读写锁3. 重量级锁&&轻量级锁4. 自旋锁5. 公平锁&&不公平锁6. 可重入锁 && 不可重入锁 二、CAS1. 什么是 CAS2. CAS 是怎么实现的3.CAS 有哪些应用1) 实现原子类2) 实现自旋锁 4. CAS 的 ABA 问…...
Java从入门到“放弃”(精通)之旅——数组的定义与使用⑥
Java从入门到“放弃”(精通)之旅🚀——数组⑥ 前言——什么是数组? 数组:可以看成是相同类型元素的一个集合,在内存中是一段连续的空间。比如现实中的车库,在java中,包含6个整形类…...
VsCode搭建
安全性问题的声明: VScode是一个由微软出品的开源软件编辑器 VScode下载 https://code.visualstudio.com/Download 官网直接下载即可,windows和linux的vscode使用命令是类似的。 VScode插件相关 为了方便安装,推荐设置并使用vscode插件的…...
【NLP 65、实践 ⑯ 基于Agent优化文章】
羁绊由我而起,痛苦也由我承担 —— 25.4.18 一、⭐【核心函数】定义大模型调用函数 call_large_model prompt:用户传入的提示词(如 “请分析这篇作文的主题”),指导模型执行任务 client:Zhipu…...
【Redis】从单机架构到分布式,回溯架构的成长设计美学
前言 🌟🌟本期讲解关于分布式架构的发展相关知识介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废…...
增量式PID基础解析与代码实例:温控系统
目录 1. 前言 2. 增量式PID控制的基本原理 2.1 PID控制的基本概念 2.2 增量式PID控制的特点 3. 增量式PID控制的Python实现:温控系统 3.1 构建增量式PID控制器 3.2 使用增量式PID控制器 3.3 运行模拟 3.4 完整代码 4. 参数调整与优化 4.1 参数选择 4.2…...
数据结构——栈以及相应的操作
栈(Stack) 在维基百科中是这样定义的: 堆栈(stack) 又称为栈或堆叠,是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合中的一端(称为堆栈顶端,top)进行加入数据(push)和…...
opencv 图像的旋转
图像的旋转 1 单点旋转2. 图片旋转(cv2.getRotationMatrix2D)3. 插值方法3.1 最近邻插值(cv2.INTER_NEAREST)3.2 双线性插值(cv2.INTER_LINEAR)3.3 像素区域插值(cv2.INTER_AREA)3.4 双三次插值(cv2.INTER_CUBIC&#…...
P3916 图的遍历
P3916 图的遍历 题目来源-洛谷 题意 有向图中,找出每个节点能访问到的最大的节点 思路 每个节点的最大节点,不是最长距离,如果是每个节点都用dfs去找最大值,显然1e6*1e6 超时了,只能60分从第一个节点开始遍历&…...
Vue3 + Three.js 场景编辑器开发实践
文章目录 前言项目背景与意义项目技术栈在线演示核心功能实现1. 智能化场景管理2. 专业级模型处理3. 可视化材质与照明4. 相机与渲染引擎5. 场景操作 项目优势开发目标1. 几何模型和模型导入,场景新建按钮增加2. 提供场景内容的可视化编辑功能3. 渲染器场景…...
Vue3 本地打包启动白屏解决思路!! !
“为什么我访问 http://127.0.0.1:5501/index.html 白屏,删了 index.html 再访问 / 就又活过来了?” —— 你的项目与 SPA 路由的“宫斗大戏” 一、问题复现 场景 本地通过 VSCode Live Server(或其他静态服务器)启动了打包后的 V…...
Ubuntu 安装 Docker 教程(官方推荐方式)
✅ 步骤 1:卸载旧版本(如果有) for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done---### ✅ 步骤 2:更新 APT 索引并安装依赖项bash sudo a…...
WPF 点击按钮,显示隐藏另一个控件
<Button Content"显示隐藏" Click"operationDetails_Click" /> private void operationDetails_Click(object sender, RoutedEventArgs e) { 另一个控件的Name.Visibility 另一个控件的Name.Visibility Visibility.Visible ? Visibility.Col…...
RBAC的使用
1、简述RBAC的作用及工作流程 Rbac基于角色访问控制,用于管理用户对集群资源的访问权限,通过定义角色和绑定规则,将用户与权限进行关联,作用:权限精细化管理,操作便捷与统一管理,动态调整权限。…...
QML中的3D功能--模型导入与修改
在Qt 3D中导入和修改3D模型是开发3D应用程序的基础。以下是详细的流程和技术方案: 一、模型导入基础 1. 支持的文件格式 Qt 3D支持多种3D模型格式: OBJ (Wavefront) FBX (Autodesk) DAE (Collada) GLTF/GLB (推荐格式) STL (3D打印格式) 2. 基本导入方法 qml import Qt3…...
树莓派超全系列教程文档--(33)树莓派启动选项
树莓派启动选项 启动选项start_file ,fixup_filecmdlinekernelarm_64bitramfsfileramfsaddrinitramfsauto_initramfsdisable_poe_fandisable_splashenable_uartforce_eeprom_reados_prefixotg_mode (仅限Raspberry Pi 4)overlay_prefix配置属…...
dotnet core webapi 实现 异常处理中间件
目录 第一步:创建异常处理中间件类(自定义响应格式) 第二步:在 Program.cs 中使用中间件 三、效果 第一步:创建异常处理中间件类(自定义响应格式) public static class ExceptionMiddleware…...
实现Azure Function安全地请求企业内部API返回数据
需要编写一个Function在Azure云上运行,它需要访问企业内部的API获取JSON格式的数据,企业有网关和防火墙,API有公司的okta身份认证,通过公司的域账号来授权访问,现在需要创建一个专用的域账号,让Function访问…...
实现Azure Databricks安全地请求企业内部API返回数据
需要编写一个Databricks在Azure云上运行,它需要访问企业内部的API获取JSON格式的数据,企业有网关和防火墙,API有公司的okta身份认证,通过公司的域账号来授权访问,现在需要创建一个专用的域账号,让Databrick…...
结合建筑业务讲述TOGAF标准处理哪种架构
TOGAF标准处理哪种架构 内容介绍业务架构业务策略,治理,组织和关键业务流程数据架构组织的逻辑和物理数据资产以及数据管理资源的结构应用架构待部署的各个应用程序,它们之间的交互以及与组织核心业务流程的关系的蓝图技术架构支持业务&#…...
深度学习--卷积神经网络CNN原理
文章目录 一、CNN图像原理1、了解CNN如何处理图像 二、CNN图像识别1、画面不变性2、主要表现1)平移不变性2)尺度不变性3)旋转不变性 3、传统神经网络1)数据预处理2)特征提取3)搭建神经网络模型4)…...
PostgreSQL 常用客户端工具
PostgreSQL 常用客户端工具 PostgreSQL 拥有丰富的客户端工具生态系统,以下是各类常用工具的详细分类和介绍: 一 图形化客户端工具 1.1 跨平台工具 工具名称特点适用场景许可证pgAdmin官方出品,功能全面开发/运维PostgreSQLDBeaver支持多…...
PostgreSQL数据库yum方式安装详解
PostgreSQL数据库yum方式安装 1. 基础环境配置2. 前期安装准备3. 软件安装3.1 YUM方式安装(PG 13)3.1.1 安装rpm仓库3.1.2 安装软件包PG133.1.3 初始化数据库3.1.4 启动数据库3.1.5 开机自启动3.1.6 编辑环境变量 4. 安装后配置 1. 基础环境配置 2. 前期…...
浅析vue2和vue3的区别
以下是 Vue 2 和 Vue 3 的主要区别: 一、核心特性 1. 响应式机制 Vue 2: 基于 Object.defineProperty 实现响应式。无法检测对象属性的新增和删除,需要使用 Vue.set 或 $set。Vue 3: 使用 Proxy 替代 Object.defineProperty。能够直接检测对象属性的新增和删除,无需额外方…...
【Linux我做主】make和makefile自动化构建
make和makefile自动化构建 make和makefile自动化构建github地址前言背景介绍为什么需要make和makefile? make和makefile解析什么是make和makefile依赖关系和依赖方法核心语法结构简单演示编译清理 多阶段编译示例 make时执行的顺序场景1:clean目标在前(特…...
spring boot应用部署IIS
Windows IIS 部署 Spring Boot 应用详细指南 本文档提供了在 Windows Server 上使用 IIS 部署 Spring Boot 应用的完整步骤和最佳实践。 目录 概述前期准备Spring Boot 应用准备安装配置必要组件配置 IIS 站点配置反向代理配置 Windows 服务配置应用自启动HTTPS 配置日志配置…...
Linux系统之部署TestNet资产管理系统
Linux系统之部署TestNet资产管理系统 一、TestNet 介绍1.1 TestNet简介1.2 主要特点1.3 主要使用场景 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、部署TestNet系统4.1 下载T…...
@EnableAsync+@Async源码学习笔记之六
接上文,我们本文分析 AsyncExecutionAspectSupport 的源码: package org.springframework.aop.interceptor;import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFu…...
SQL系列:常用函数
1、【MySQL】合并字段函数(列转行) 它可以将两个字段中的数据合并到一个字段中。 1)CONCAT函数 CONCAT函数可以将多个字段中的数据合并到一个字段中。它的语法格式如下: SELECT CONCAT(字段1,字段2,...字段N) FROM 表名;SELEC…...
Git 中修改某个特定的commit提交内容
在 Git 中修改某个特定的提交(commit)通常需要使用 交互式变基(Interactive Rebase) 或 修改提交(Commit Amend)。以下是不同场景下的具体操作步骤: 一、修改最近的提交(最新提交&am…...
FHS --- linux目录结构(部分目录解释)
根目录(/) 的意义和内容 : 根目录是整个系统最重要的一个目录,因为不但所有的目录都是由根目录衍生出来的,同时根目录也与开机/还原/系统修复等动作有关 。 由于系统开机时需要特定的开机软件、核心档案、开机所需程序…...
不带无线网卡的Linux开发板上网方法
I.MX6ULL通过网线上网 设置WLAN共享修改开发板的IP 在使用I.MX6ULL-MINI开发板学习Linux的时候,有时需要更新或者下载一些资源包,但是开发板本身是不带无线网卡或者WIFI芯片的,尝试使用网口连接笔记本,笔记本通过无线网卡连接WIFI…...
图书管理系统C语言
图书管理系统C语言代码示例。 该系统可以实现图书信息(包含图书编号、书名、作者、出版社、价格、库存数量)的录入、显示、查询、修改、删除等功能,还具备一定的错误处理和输入验证。 #include <stdio.h> #include <stdlib.h> …...
关于大型语言模型的“生物学”
我知道我们已经聊过很多次,关于LLM是怎么运作的,它们的影响力,还有它们的使用场景。但尽管现在有那么多讲LLM的文章,它们本质上还是个黑箱。 但我们真正要问自己的问题是,为什么理解这些系统的内部结构很重要…...