一、前言

在云原生架构高速迭代的背景下,基础设施的性能瓶颈与安全隐患成为技术演进的关键挑战。本文系统记录了团队基于Rust语言改造Nginx组件的完整技术路径:从接触Cloudflare的quiche库,引发对Rust安全特性的探索,到通过FFI实现核心逻辑的跨语言调用;从突破传统C模块开发范式自研 ngx_http_rust_module SDK ,到全面采用Pingora框架构建新一代DLB 2.0流量调度平台。

实践表明,Rust的内存安全机制与异步高并发能力可显著提升负载均衡组件的性能边界与可靠性,为超大规模流量调度场景提供全新解决方案。本技术演进过程将详述架构设计、核心模块实现及性能优化策略,为同类基础设施升级提供可复用的工程经验。

二、Nginx+Rust 的模块化探索

探索的起点源于和quiche(cloudflare开发的高效quic实现)的初次邂逅,这扇门将项目组成员引入了 Rust 语言的世界。Rust 以其卓越的内存安全、无惧并发的特性以及出色的性能潜力,迅速展示了其作为系统级编程语言的优势。这份吸引力促使我们思考:能否将 Rust 的安全与性能注入我们更广泛的基础设施中?作为核心组件的 Nginx 自然成为了探索的焦点。

我们首先聚焦于FFI(外部函数接口)技术,通过它构建Rust与C语言的交互桥梁。借助FFI,我们将核心业务逻辑以Rust实现,并将Rust代码编译为符合C-ABI规范的动态链接库。这种设计使得Nginx能够像调用原生C模块一样无缝集成Rust编写的库,在保障系统稳定性的同时提升性能。

采用该方案的限流模块示例如下:

鉴于单向调用模式在应用场景上的局限性,如果仅仅支持上面的单向调用流,使用的场景将大打折扣,目前Nginx 中大量的功能以三方模块的形式呈现,C module的开发难度较高,需要理解的组件概念颇多,团队尝试开发了ngx_http_rust_module模块作为一个探索期的折中方案。

ngx_http_rust_module本质上是一个Rust SDK,是对传统C模块开发模式的一种现代化补充尝试。SDK层封装好的胶水function极大便利了rust module上层开发,可以实现纯Rust编码来实现业务功能,实践验证具备较高工程价值。

目前已封装的部分SDK展示以及设置响应header方法示例:

三、全面拥抱Rust进入DLB2.0阶段

完成Nginx模块的初步探索后,团队技术路线转向Cloudflare开源的Pingora框架,该高性能Rust框架专为构建可编程、高可靠的流量调度平台而设计。

核心优势

  • 云原生架构 :通过异步任务调度消除Nginx的进程隔离瓶颈,实现CPU负载均衡与高效连接复用。

  • 性能突破 :实测每秒可处理10万请求,资源消耗降至传统方案的三分之一。

  • 协议生态 :原生支持HTTP/1-2、Websocket端到端代理。

  • 安全演进 :基于Rust内存安全特性,集成FIPS认证的加密模块解决C/C++方案的安全隐患。

  • 扩展能力 :提供可编程负载均衡API与热升级机制,满足超大规模流量调度需求。

在原型验证其技术可行性之后,团队决定在该框架骨干上构建了DLB 2.0产品体系:

核心能力设计

  • 声明式配置管理提供基于YAML的声明式配置接口,显著提升配置可读性与维护效率。支持热加载机制,实现流量无损的配置更新,彻底规避传统代理重载导致的503服务中断。

  • 流量处理支持单一端口多域名TLS证书托管能力,简化HTTPS服务部署。提供与Nginx完全兼容的server/path路由匹配逻辑,确保无缝迁移。实现路径重写引擎,满足复杂流量调度需求。采用模块化Filter链设计,支持按需插拔流量处理组件。

  • 服务发现集成静态资源配置与动态DNS服务发现双模式。支持sylas注册中心。企业级监控。提供增强型访问日志。输出完全兼容DLB 1.0的监控指标(VTS格式)。保留流量录制数据规范,确保监控体系平滑升级。

每个模块的设计均遵循"高内聚低耦合"原则,在保障生产环境稳定性的前提下,为超大规模流量调度场景提供可扩展的技术支撑,后续将逐一拆解部分关键模块的技术实现细节与性能优化策略。

配置体系

静态配置

DLB 2.0在配置层面按类型拆分成多个细粒度的yaml文件,其中最核心的是 server.yaml 以及 upstream.yaml ,为了对标Nginx核心概念、这部分不引入新的术语,继续沿用 server 、 location 、 upstream 三大基础模块。

  • 通过 server 模块声明虚拟主机,支持多域名监听及端口绑定,兼容 server_name 的泛域名解析能力,同时实现单端口多域名 TLS 证书的精准匹配。

  •  location 模块完整继承 Nginx 的路径匹配逻辑(含精确匹配 = 、正则匹配 ~ 等模式),支持基于路径的请求路由与正则表达式重写规则,确保策略迁移的零成本适配。同时支持 proxy_pass 、 if 、 proxy_headers 、 return 等核心指令。

  •  upstream 动态服务发现机制支持权重负载均衡,通过 YAML 结构化配置实现后端集群的声明式管理,并与DNS的服务发现深度集成,彻底消除传统配置中硬编码 IP 的维护负担。

- id: "hjob.shizhuang-inc.com"server_name: "hjob.shizhuang-inc.com"service_in:- "default_80"- "default_443"redirect: truelocation:- path: "/"access_rule_names:- "access_allow_d803a06f39ad4dcd8dfe517359a33a61"- "access_deny_all"client_max_body_size: "100M"proxy_headers:- "clientport:$remote_port"- "Upgrade:$http_upgrade"- "Connection:$http_connection"- "Host:$host"- "X-Forwarded-For:$proxy_add_x_forwarded_for"- "X-Forwarded-Proto:$scheme"proxy_pass: "http://hangzhou-csprd-hjob-8899"- name: "hangzhou-csprd-hjob-8899"peers:- server: "1.1.1.1:8899"weight: 100backup: falsedown: false- server: "2.2.2.2:8899"weight: 1backup: falsedown: falsemax_fails: 3fail_timeout: "10s"max_connections: 1000

配置解析

在DLB 2.0的配置模型中, server 、 location 、 upstream 三者构成层次化路由架构:

  •  server 作为虚拟服务单元,通过 Vec<LocationConf> 聚合任意数量的 location 路由规则。

  •  location 作为请求路径处理器,可独立关联至不同的 upstream 服务组。

  •  upstream 采用原子引用计数机制( Arc )封装配置,通过Arc::strong_count() 实时监控引用状态,避免冗余配置拷贝,基于Rust的并发安全特性,最终设计为 Arc<Mutex<UpstreamConf>> 结构: Mutex 保障多线程环境下的内部可变性,支撑配置热更新需求。 Arc 维持跨线程的只读共享能力,确保访问高效性。

main thread解析完server.yaml与upstream.yaml后,将生成两个核心哈希映射:

  •  server 配置映射表:关联域名与路由规则集。

  •  upstream 线程安全容器:托管负载均衡服务组状态。

/// A map of server names to their respective configurations.
#[serde(skip)]
pub servers: HashMap<String, Arc<Mutex<ServerConf>>>,
/// A map of upstream names to their respective configurations.
#[serde(skip)]
pub upstreams: HashMap<String, Arc<Mutex<UpstreamConf>>>,

运行时配置转化

上述的 ServerConf 与 UpstreamConf 面向的是用户,特点是易于理解与维护、支持YAML反序列化。

而为了专注运行时效率(比如负载均衡策略中的字符串转化为枚举类型),我们会将 UpstreamConf 转化为 RunTimeUpStream 结构, ServerConf 同理。

impl TryFrom<&UpstreamConf> for RunTimeUpStream {type Error = Error;fn try_from(value: &UpstreamConf) -> std::result::Result<Self, Self::Error> {}
}

转化之后得到全局唯一的 GlobalConf :

pub static GLOBAL_CONF: Lazy<RwLock<GlobalConf>> = Lazy::new(|| {RwLock::new(GlobalConf {main_conf: MainConf::default(),runtime_upstreams: HashMap::with_capacity(16),runtime_servers: HashMap::with_capacity(16),host_selectors: HashMap::with_capacity(16),})
});#[derive(Default)]
pub struct GlobalConf {// main static configurationpub main_conf: MainConf,//one-to-one between upstreams and runtime_upstreamspub runtime_upstreams: HashMap<String, Arc<RunTimeUpStream>>,//one-to-one between servers and runtime_servers;pub runtime_servers: HashMap<String, Arc<RunTimeServer>>,//one service one host selectorpub host_selectors: HashMap<String, Arc<HostSelector>>,
}

流量处理

域名匹配

如果仅有上面的 runtime_servers 这一个哈希表,还不能实现复杂的Nginx域名匹配规则,Nginx域名匹配的优先级机制包括:精确匹配>前置通配符>正则匹配(后置通配符在1.0版本未使用,暂且忽略),为了确保无缝迁移,需要提供与Nginx完全兼容的server匹配逻辑,考虑到代码可维护性,可以这样组织运行时数据:

  • 为精确域名使用HashMap,实现O(1)查找。

  • 前置通配符匹配存储为Vec,且确保最长匹配优先。

  • 正则表达式只能顺序匹配,保持Vec<Regex>原顺序。

最终得到这样的结构体:

/// A struct to manage server selection based on host names.
///
/// This struct contains three fields: `equal`, `prefix`, and `regex`.
/// The `equal` field is a HashMap that stores server names and their corresponding IDs
/// when the server name exactly matches the host.
/// The `prefix` field is a Vec of tuples, where each tuple contains a prefix and its corresponding server ID.
/// The `regex` field is a Vec of tuples, where each tuple contains a Regex and its corresponding server ID.
///
/// The `HostSelector` struct provides methods to insert server names and IDs,
/// and to match a given host name with a server ID based on the rules defined in the struct.
#[derive(Clone)]
pub struct HostSelector {pub equal: HashMap<String, String>,pub prefixes: Vec<(String, String)>,  //原始前通配符数据pub prefix_nested_map: NestedHashMap, // 嵌套哈希结构优化匹配效率pub regex: Vec<(Regex, String)>,
}

其中需要留意的是成员 prefix_nested_map ,为了确保最长匹配优先,我们将 prefixes: Vec<(String, String)> 转化为了 NestedHashMap 结构, NestedHashMap 为一个嵌套哈希结构,可基于域名分段实现高效检索。

#[derive(Debug, Clone)]
pub struct NestedHashMap {data: HashMap<String, NestedHashMap>, //层级域名节点value: Option<String>, // 终端节点关联服务器ID
}impl NestedHashMap
{/// 基于域名分段实现高效检索(从右向左匹配)pub(crate) fn find(&self, key: &str) -> Option<String> {let tokens = key.split('.').collect::<Vec<&str>>();let mut current_map = self;let mut result = None;// 遍历域名层级(如 www.example.com → [com, example, www])for token in tokens.iter().rev() {// 优先记录当前层级的有效值(实现最长匹配)if current_map.value.is_some() {result = Some(current_map.value.as_ref().unwrap());}// 向下一级域名跳转let child = current_map.data.get(*token);match child{Some(child) => {current_map = child;}None => {break;}}}result.map(|value| value.to_owned())}
}

路由匹配

讲完了域名匹配,我们再深入路由匹配,在开始之前,我们先回顾一下Nginx的location指令。

Syntax:location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default:—
Context:server, location

 location 通常在 server{} 块内定义,也可以嵌套到 location{} 内,虽然这不是一种推荐的配置方式,但它确实是被语法规则支持的, localtion 语法主要有如下几种形式:

※  修饰符语义及优先级(依匹配精度降序排列)

  1.  = :精确匹配(Exact Match),URI必须与模式完全一致时生效(最高优先级)。

  2.  ^~ :最佳前缀匹配(Prefix Match),选中最长非正则路径后终止搜索(优先级次于=)。

  3.  ~ :区分大小写的正则匹配(Case-Sensitive Regex)。

  4.  ~* :不区分大小写的正则匹配(Case-Insensitive Regex)。

  5.  @ :内部定位块(Named Location),仅限 try_files 或 error_page 指令调用,不对外暴露。

Nginx在解析完 location 之后会进行一系列的工作,主要包括:

  • 分类:  根据location的修饰符参数标识不同的类型,同时去除name前面的修饰符

  • 排序: 对一个server块内的所有location进行排序,经过排序之后将location分为了3类通用类型,通用类型的location将建立一棵最长前缀匹配树正则类型,顺序为配置文件中定义的顺序,正则会用pcre库先进行编译内部跳转类型,顺序也为配置文件中定义的顺序

  • 拆分:将分类的3种类型拆分,分门别类的处理

其中最复杂的是最长前缀匹配树的构建,假设location规则如下,构造一棵最长前缀匹配树会经过如下几个步骤:

  1. 把locations queue变化locations list,假设一个location的name是A的话,所有以A前缀开头的路由节点都会放到A节点的list里(最长前缀匹配)。

2.按照上述步骤递归初始化A节点的所有list节点,最终得到下面的list。

图片

3.在上述创建的list基础上,确定中间节点,然后从中间节点把location分成两部分,然后递归创建左右子树,最后处理list队列,list队列创建的节点会加入到父节点的tree中,最终将生成一棵多叉树。

现在你应该已经明白了最长前缀匹配树的构建流程,让我们回到2.0的设计上来,这部分同样维护了三个结构分别对应精确匹配、正则匹配以及最长前缀匹配。

#[derive(Clone, Default)]
#[allow(unused)]
/// A struct representing a shared runtime server configuration.
pub struct RunTimeServer {/// Unique identifier for the server.pub id: String,/// Name of the server.pub server_name: String,/// Indicates whether the server should redirect requests.pub redirect: bool,/// A HashMap storing equal-matched locations, where the key is the path and the value is the location.pub equal_match: HashMap<String, Arc<RunTimeLocation>>,// 精确匹配字典/// A Vec storing regex-matched locations, where each tuple contains a Regex and the location.// 正则匹配队列pub regex_match: Vec<(Regex, Arc<RunTimeLocation>)>,/// The root node of the static location tree.pub prefix_root: Option<Arc<static_location_tree::TreeNode>>,
}

精确匹配、正则匹配比较简单,我们重点介绍最长前缀匹配,最长前缀匹配树的构建基本上是把Nginx代码原原本本的翻译过来,通过 create_list() 分组节点、 create_tree() 生成多叉树。通过 find_location 遍历树结构查找最长有效路径,其中路径比较函数 path_cmp() 确保按字典序定位子树,匹配成功时返回( need_stop, location ),其中 need_stop 标志是否中止搜索(模拟 ^~ 行为)。

 pub fn find_location(path: &str, node: &Arc<TreeNode>) -> Option<(bool, Arc<RunTimeLocation>)> {let mut node = Some(node);let mut uri_len = 0;let mut search_node = None;while let Some(current) = node {let n = std::cmp::min(current.path.len(), path.len() - uri_len);let node_path = &current.path[..n];let temp_path = &path[uri_len..uri_len + n];match path_cmp(node_path, temp_path) {std::cmp::Ordering::Equal => {uri_len += n;search_node = Some((current.need_stop, current.val.clone()));node = current.tree.as_ref();if uri_len >= path.len() { break; }}std::cmp::Ordering::Greater => node = current.left.as_ref(),std::cmp::Ordering::Less => node = current.right.as_ref(),}}search_node
}

路由重写

路由重写是实现请求路径动态转换的核心能力,在语义层面,我们完全兼容Nginx的配置语义。

 regex replacement [flag] ,同时采用预编译正则引擎,在路由加载期完成规则编译。

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RewriteFlags {Break,Last,Redirect,Permanent,NONE,
}pub struct RewriteRule {pub reg_source: String,pub reg: Regex,pub target: String,pub flag: RewriteFlags,
}

模块化Filter链

Pingora 引擎已经将请求生命周期划分了足够细的各个阶段,为了更精细化控制同一phase执行的各个Filter,可通过自定义的 ProxyFilter trait,与 Pingora 引擎的phase关联起来。

#[async_trait]
pub trait ProxyFilter: Sync + Send {fn phase(&self) -> ProxyFilterPhase;fn name(&self) -> ProxyFilterName;fn order(&self) -> i32;async fn handle(&self, _session: &mut Session, _ctx: &mut ProxyContext) -> HandleResult {HandleResult::Continue}
}

 ProxyFilter 主要包含四个方法:

  •  phase : Filter 的执行阶段, 生命周期阶段锚点,可以根据实际需要进行扩展插入更细粒度的阶段进行请求处理

  •  name : Filter的名称。

  •  order : 在同一个phase内Filter的执行顺序。

  •  handle : Filter 的执行逻辑,若返回的是 HandleResult::Continue ,则表示当前filter执行完成,继续执行下一个 filter,否则停止filter chain 的执行动作。

#[derive(Debug, PartialEq, Clone, EnumString)]
pub enum HandleResult {/// 表示当前filter执行完成,继续执行下一个 filter。Continue,/// 表示当前filter操作被中断,停止filter chain 的执行动作。Break,
}

目前我们已经实现的Filter包括但不限于:

四、总结

作为《从Rust模块化探索到DLB 2.0实践》系列的第一篇,本文介绍了开发DLB 2.0的背景以及详述了DLB 2.0如何通过声明式配置管理、分层路由架构及与Nginx完全兼容的匹配逻辑,实现亿级流量调度场景下的高可用与零迁移成本。

当前成果验证了Rust在负载均衡产品中改造中的工程价值:依托线程安全的运行时结构(如 Arc<Mutex<T>> )、高效前缀树路由( HostSelector )及最长前缀匹配,性能与可维护性均突破传统方案边界。

在后续篇章中,我们将继续深入剖析服务发现、监控与日志等核心模块,为超大规模云原生架构提供完整的参考实践。

往期回顾

1.eBPF 助力 NAS 分钟级别 Pod 实例溯源|得物技术

2.正品库拍照PWA应用的实现与性能优化|得物技术

3.汇金资损防控体系建设及实践 | 得物技术

4.得物社区活动:组件化的演进与实践

5.从CPU冒烟到丝滑体验:算法SRE性能优化实战全揭秘|得物技术

文 / 雷泽

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

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

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

相关文章

【 MySQL】一点点相关的记录

打开 MySQL Workbench 并连接到你的数据库在 MySQL Connections 下&#xff0c;选择连接的数据库实例&#xff08; Local instance MySQL80&#xff09;登录时输入 用户名 和 密码。 root&#xff0c;密码是在 MySQL 安装时设置的密码创建新数据库登录后&#xff0c;在 MySQL W…

旅游企业如何通过数字化转型实现高效运营

在旅游行业竞争日益激烈、游客需求日趋多样的当下&#xff0c;数字化管理成为旅游企业提升竞争力的关键协同办公系统以其丰富功能与灵活特性&#xff0c;为旅游行业带来全新的数字化变革&#xff0c;助力企业高效运营。优化行程规划与调度旅游行程的规划与调度繁杂且关键。协同…

大数据Spark(六十二):Spark基于Yarn提交任务流程

文章目录 Spark基于Yarn提交任务流程 一、Yarn-Client模式 1、提交命令 2、任务执行流程 二、Yarn-Cluster模式 1、提交命令 2、任务执行流程 Spark基于Yarn提交任务流程 在Yarn模式下&#xff0c;Spark的任务提交同样根据Driver程序运行的位置不同&#xff0c;分为cli…

Docker 高级管理-容器通信技术与数据持久化

(1)创建一个叫 my-net 的 bridge 类型的网络(2)查看都有哪些网络(3)运行一个容器井连接到新建的 my-net 网络(4)运行一个容器井加入到 my-net 网络2:Host 模式由于使用了 Host 模式&#xff0c;容器会直接使用宿主机的网络端口&#xff0c;因此可以直接在宿主机上通过 localhos…

在 Ubuntu 24.04 中安装 Python 2.7、pip 及 mysqlclient==1.4.6 的完整指南

在 Ubuntu 24.04 中安装 Python 2.7、pip 及 mysqlclient1.4.6 的完整指南 前言 随着 Ubuntu 24.04 的发布&#xff0c;许多旧的软件包已被移除或更新&#xff0c;但老项目需要 Python 2 。本文将详细介绍自己如何在 Ubuntu 24.04 中成功安装 Python 2.7、pip 以及 mysqlclient…

doker以及网站案例

一.docker搭建1.安装dockerapt-get install docker.io docker-compose2.编写配置文件&#xff08;注意路径正确&#xff09;vim /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment"HTTP_PROXYhttp://科学上网访问的ip:端口" Environment&q…

【HarmonyOS Next之旅】DevEco Studio使用指南(四十一) -> 获取自定义编译参数

目录 1 -> HAP/HSP运行时获取编译构建参数 1.1 -> 生成BuildProfile类文件 1.2 -> 在代码中获取构建参数 1.3 -> 默认参数 1.4 -> 自定义参数 2 -> HAR运行时获取编译构建参数 2.1 -> 生成BuildProfile类文件 2.2 -> 在代码中获取构建参数 2.…

NGINX系统基于PHP部署应用

目录 部署 配置 部署 准备三台主机&#xff0c;一台服务端&#xff0c;两台客户端&#xff1b; 1.在两台客户端主机上分别安装 MySQL; [rootmaster /]#yum install -y mysql nginx; [rootmaster /]#yum install -y nginx PHP; [rootmaster /]#yum install -y php PHP-m…

ip地址可以精确到什么级别?如何获取/更改ip地址

IP地址的精确级别和获取/更改方式取决于其类型&#xff08;公网IP vs 内网IP&#xff09;&#xff0c;以下是详细解答&#xff1a; 一、IP地址的精确级别 1. 公网IP地址&#xff08;互联网可见&#xff09; 定位级别精度范围说明国家/地区级约95%准确通过IP数据库&#xff08;…

Linux(Centos 7.6)命令详解:useradd

1.命令作用创建新用户或更新默认的新用户信息(create a new user or update default new user information)2.命令语法Usage: useradd [options] LOGINuseradd -Duseradd -D [options]3.参数详解OPTION:-b, --base-dir BASE_DIR&#xff0c;新帐户的主目录的基本目录&#xff1…

异步I/O库:libuv、libev、libevent与libeio

异步I/O编程是现代高性能网络服务的核心&#xff0c;而libuv、libev、libevent、libeio这四个库则是这一领域的常青树。它们虽同属事件驱动模型&#xff0c;却在设计哲学、适用场景和实现细节上各具特色。本文将深入剖析其异同。 一、共同点&#xff1a;异步事件驱动 事件循环&…

go go go 出发咯 - go web开发入门系列(四) 数据库ORM框架集成与解读

go go go 出发咯 - go web开发入门系列&#xff08;四&#xff09; 数据库ORM框架集成与解读 往期回顾 go go go 出发咯 - go web开发入门系列&#xff08;一&#xff09; helloworldgo go go 出发咯 - go web开发入门系列&#xff08;二&#xff09; Gin 框架实战指南go go g…

CD47.【C++ Dev】list的模拟实现(2)

目录 1.const修饰的迭代器的实现 方法1:分成两个类 完整代码 方法2:STL库的写法 2.STL库的第三个模版参数T*的解释 ->->的简写语法 3.其他成员函数 insert erase push_back、push_front、pop_front、pop_back size clear 析构函数~list() 拷贝构造函数(★…

UI前端与数字孪生融合新领域拓展:智慧教育的虚拟实验室建设

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;虚拟实验室 —— 打破教育边界的技术革命传统实验教学正面临 “设备昂贵、…

7. TCP 和 UDP 的区别

总结 TCP 面向连接&#xff0c;需要三次握手建立连接&#xff0c;UDP 无连接&#xff0c;不需要握手&#xff0c;直接发送数据。UDP 有较好的实时性&#xff0c;效率比 TCP 高。TCP 面向字节流&#xff0c;实际上是 TCP 把数据看成一连串无结构的字节流&#xff0c;UDP 是面向报…

iOS Widget 开发-7:TimelineProvider 机制全解析:构建未来时间线

在 WidgetKit 中&#xff0c;TimelineProvider 是小组件生命周期的核心机制之一。它控制着 数据获取时机、展示内容 与 刷新策略&#xff0c;是实现时间驱动内容更新的基础。 本文将介绍 TimelineProvider 的工作原理、设计模式、常见场景与高级用法&#xff0c;帮助大家构建智…

基于PHP/MySQL的企业培训考试系统源码,高并发、稳定运行,源码开源可二开

温馨提示&#xff1a;文末有资源获取方式这是一款专为企业设计的开源培训考试系统&#xff0c;采用PHPMySQL技术栈开发&#xff0c;具有高并发处理能力和稳定运行特性。系统源码完全开放&#xff0c;支持二次开发&#xff0c;可满足各类企业的培训考核需求。核心功能特点1. 高性…

时序数据库InfluxDB

一.定义 时序数据库 是一种专门用于高效存储和查询带有时间戳的数据的数据库。如果你的数据是随着时间变化而不断产生&#xff0c;并且你想知道过去某一时刻发生了什么&#xff0c;那么你应该用时序数据库。 这类数据通常具有以下特征&#xff1a; 数据点按时间顺序不断写入…

2025.07.09华为机考真题解析-第三题300分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 博物馆安保摄像头配置 问题描述 A先生负责为一家新开的博物馆设计安保监控系统。博物馆有多个展厅需要监控,每个展厅都有不同的面积。现在有多种型号的监控摄像头可供选择,每…

存储过程封装:复杂业务逻辑的性能优化

存储过程作为数据库层面的重要功能&#xff0c;能够显著提升复杂业务逻辑的执行效率。以下是存储过程在性能优化中的核心优势、实现策略和实际应用场景。一、存储过程的核心优势‌网络传输压缩‌存储过程将多条SQL语句封装为单次调用&#xff0c;相比应用层多次请求可减少60%-8…