阅读视图

发现新文章,点击刷新页面。
🔲 ☆

当“安全性”遭遇“交付速度”:2026 年,我为什么告别了 Rust

本文永久链接 – https://tonybai.com/2026/02/21/safety-vs-delivery-speed-why-farewell-rust-in-2026

大家好,我是Tony Bai。

在软件工程的铁三角中,Rust 占据了“安全性”与“性能”的绝对高地。凭借借用检查器(Borrow Checker)和极其严格的类型系统,它向开发者承诺了一个没有内存错误、没有空指针崩溃的完美世界。

然而,在商业软件开发的战场上,还有一个至关重要的维度往往被技术纯粹主义者忽视,那就是——交付速度(Delivery Speed)

近日,资深工程师 Dmitry Kudryavtsev 发表了长文《Farewell, Rust》,详述了他为何忍痛将一个运行了多年、已盈利的 Rust 项目全盘重写为 Node.js 的心路历程。这篇文章也引发了一场关于“为了极致的安全性,我们是否值得牺牲过多的交付速度?”的深刻辩论。

缘起:一个 C/C++ 老兵的“安全梦”

Dmitry 绝非那些被即时编译(JIT)宠坏的脚本小子。相反,他的技术底色是硬核的 C/C++。

早在高中时代,他就沉迷于指针的魔力,痴迷于手动管理内存的掌控感。他写过 3D 渲染器、IRC 机器人,甚至操作系统内核。然而,由于第一份工作是 PHP Web 开发,他被迫进入了动态语言的世界。虽然 PHP、Python 和 Ruby 带来了 Web 开发的极速体验,但在内心深处,他始终怀念 C 语言那种“压榨硬件每一滴性能”的快感,同时也痛恨 C 语言中防不胜防的内存安全漏洞。

直到 Rust 横空出世。

对于像 Dmitry 这样的工程师来说,Rust 简直就是“鱼与熊掌兼得”的梦想:

  • 低级控制力:像 C 一样精确控制内存布局。
  • 安全性:编译器在编译阶段就能消除一整类内存错误。
  • 现代体验:拥有像 Cargo 这样优秀的包管理工具。

于是,他做了一个所有热血工程师都会做的决定:为了追求极致的质量与安全,用 Rust 从零构建一个商业 Web 应用。

起初,一切都很完美。他在 2023 年底成功上线了项目,甚至因此受邀在两个技术大会上发表演讲。但随着时间的推移,业务逻辑日益复杂,“安全性”的红利开始被“交付速度”的损耗所抵消。到了 2026 年初,为了项目的生存,他不得不做出了那个艰难的决定:告别 Rust

深度复盘:Rust 在 Web 交付中的“五大减速带”

Dmitry 的文章之所以珍贵,是因为他用亲身经历证明了:在 Web 开发的特定场景下,Rust 引以为傲的“安全性”机制,如何一步步变成了拖慢“交付速度”的罪魁祸首。

1. 模板与视图:类型安全 vs. 迭代速度

在后端逻辑中,Rust 的类型系统坚不可摧。但当数据流向前端(HTML/Email 模板)时,这种为了安全而设计的严格性,变成了修改 UI 时的噩梦。

  • 安全性的代价:为了保证编译时的类型安全,Rust 社区诞生了 Maud 或 Askama 这样的编译时模板库。它们通过宏(Macro)在编译期检查 HTML 模板中的每一个变量引用。这听起来很棒,意味着你永远不会渲染出错误的变量。
  • 速度的牺牲:但这带来的副作用是,每次修改 HTML 哪怕一个标点符号,都会触发漫长的重新编译。在 Web 前端开发这种需要“所见即所得”的高频迭代场景下,这种等待是毁灭性的。
  • 对比 Node.js:TypeScript 配合 JSX/TSX 提供了全链路的类型安全,同时保持了极快的热重载(Hot Reload)速度。重构一个字段,VS Code 会立即标红所有受影响的视图组件,修改后毫秒级生效。这种“安全且快”的体验,是 Rust 目前无法提供的。

2. 国际化(i18n):生态缺失带来的效率黑洞

对于商业应用,支持多语言是刚需。

虽然 Mozilla 开发了 Project Fluent,但 Rust 生态中缺乏成熟的、开箱即用的 i18n 解决方案。你往往需要为了“正确性”而去处理繁琐的加载逻辑和类型绑定,编写大量的胶水代码。而Node.js生态中的i18next 等库不仅极其成熟,还能配合 TypeScript 提供键值级别的类型安全。Node.js 原生内置了完整的 ICU 标准(Intl API),处理货币、日期、复数格式化信手拈来。在这一点上,Rust 开发者需要花费数倍的时间来实现同样的功能,严重拖慢了产品推向全球市场的速度。

3. “动态”业务 vs. “静态”约束

Web 业务充满了动态性:用户提交的 JSON 结构可能是不确定的,筛选条件的组合可能是无穷的。Rust 试图用静态类型系统去约束这些动态行为,结果就是开发效率的暴跌。

  • 序列化之痛:serde 是 Rust 的瑰宝,但在处理复杂的、充满 Option 的业务数据时,为了安全地取出一个嵌套字段,你不得不编写大量的 match 或 unwrap 处理代码。为了优雅地处理错误,Dmitry 定义了十几个自定义错误枚举。虽然代码很健壮,但写起来太慢了。
  • SQL 的僵局:sqlx 提供了极其强大的编译时 SQL 检查,这在静态查询时非常棒。但是,一旦你需要根据用户输入动态构建查询(例如:用户选了 A 筛选条件就加个 WHERE 子句),Rust 的强类型系统就变成了噩梦。你无法像在 Node.js 中使用 Kysely 或 Prisma 那样,流畅地拼接查询片段。为了“安全”地构建 SQL,你付出了巨大的代码复杂度成本。

4. 编译时间:CI/CD 的隐形杀手

这是最让 Dmitry 崩溃的一点,也是“交付速度”最直观的体现。

  • Rust 的等待:随着依赖增多(尤其是使用了大量宏的 Web 框架),编译时间呈指数级增长。Dmitry 的 CI 流程需要 12-14 分钟 才能完成部署。“每次我在 Sentry 上看到一个简单的 Bug,想到修复它需要等待 15 分钟的构建流程,我就失去了修复的动力。”
  • Node.js 的极速:迁移到Node.js后,完整的 CI 流程(含 Lint 和测试)仅需 5 分钟。部署速度提升了 3 倍。这意味着“发现 Bug -> 修复 -> 上线”的反馈闭环被大大缩短了。在商业竞争中,修复速度往往比绝对的“无 Bug”更重要。

5. 生态成熟度:造轮子的时间成本

Rust 的 Web 生态虽然在成长,但面对长尾需求时仍显稚嫩。

  • 场景:你需要集成一个冷门的第三方支付网关,或者处理一个特定的 Webhook 签名验证。
  • Rust 的困境:官方 SDK?没有。社区库?两年前就不更新了。为了安全,你不得不对着 API 文档,自己手写 HTTP 请求、自己实现加密验签逻辑。这占用了大量本该用于开发业务核心功能的时间。
  • Node.js 的便利:npm install 通常能解决一切。几乎所有 SaaS 服务商都会提供第一方的 Node.js SDK。“拿来主义”是提升交付速度的最佳捷径。

总结与反思:我们到底为了什么而编程?

Dmitry 的文章并没有否定 Rust 的价值。相反,他依然热爱 Rust,依然怀念那些与编译器“斗智斗勇”并最终获得完美代码的日子。

他的结论非常客观,为所有正在做技术选型的团队提供了一把衡量“安全”与“速度”的标尺:

  1. 资源占用 vs. 开发效率的账本
    Rust 版本的应用内存占用仅 60-80MB,而 Node.js 版本约为 117MB。
    Rust 确实更省资源。但对于业务应用来说,这 50MB 的内存差异,在云服务器几美元一个月的成本面前不值一提。然而,为了节省这 50MB 内存,开发者付出了几倍的开发时间、调试精力以及心智负担。这笔账,在商业逻辑上是划不来的。

  2. 技术选型的“黄金法则”

    • 何时拥抱“安全性”(选 Rust):如果你在构建数据库内核、搜索引擎、高频交易系统、嵌入式设备固件,或者像 Lambda 这样对冷启动时间极度敏感的 Serverless 函数。在这些场景下,性能和稳定性是核心竞争力,为了安全牺牲开发速度是值得的。
    • 何时拥抱“交付速度”(选 Node.js/Go/Python):如果你在构建 CRUD 后端、SaaS 业务逻辑、内部管理工具,或者处于需要快速试错、频繁变更需求的初创阶段。在这些场景下,迭代速度(Velocity)才是核心竞争力。
  3. 给 Go 开发者的启示
    有趣的是,Dmitry 在注脚中提到了 Go:“Yes, there is Go. But I never really had the chance to like Go.”
    这其实是一个非常有意思的信号。在 Rust 的“极致安全”和 Node.js 的“极致速度”之间,Go 恰恰占据了那个“黄金平衡点”

    • 它有静态编译和类型系统,比 Node.js 更安全、性能更好。
    • 它有极快的编译速度和简单的语法,比 Rust 的心智负担低得多。
    • 它有极其成熟的中间件和微服务生态。

    对于那些厌倦了 Node.js 运行时错误,又被 Rust 借用检查器拖慢脚步的 Web 开发者来说,Go 依然是当下最务实的选择。

小结

技术选型从来没有绝对的优劣,只有“最适合当下约束条件的工具”。

Dmitry 的故事提醒我们:不要因为手里拿着“安全性”这把锤子(Rust),就无视了“交付速度”这个钉子。在商业软件的世界里,有时候,为了让产品活下去,为了让用户更快用上新功能,“足够好”且“跑得快”的代码,往往比“完美但迟到”的代码更有价值。

Rust 是系统编程的未来,但这并不意味着它是所有 Web 业务的终点。对于独立开发者或初创团队而言,“快”,本身就是一种极其重要的功能。

资料链接:https://yieldcode.blog/post/farewell-rust/


你会为了“安全”放弃“速度”吗?

软件工程永远是权衡的艺术。在你的项目中,你是否也曾为了追求某种“先进特性”,而导致项目进度失控?如果给你 50MB 的内存节省,你愿意多等 10 分钟的编译时间吗?

欢迎在评论区分享你的选型纠结!


还在为“复制粘贴喂AI”而烦恼?我的新专栏 AI原生开发工作流实战 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.

🔲 ⭐

2024年的后端和Web开发趋势

在本文中,我们将揭示定义 2024 年的主要趋势,为你提供保持领先地位的工具和知识。无论你是经验丰富的开发人员,还是寻求推动创新的产品负责人,这都是你的成功路线图。

不断变化的数字创新格局可能让人感觉像是一场无情的竞赛。作为开发人员,你的痛苦是真实的——交付尖端产品、保持竞争力、跟上不断变化的用户期望,综合起来你的压力可能是压倒性的。

但是,如果我们告诉你有一个指南针可以驾驭这个复杂的形势呢?

在本文中,我们将揭示定义 2024 年的主要趋势,为你提供保持领先地位的工具和知识。无论你是经验丰富的开发人员,还是寻求推动创新的产品负责人,这都是你的成功路线图。

1、人工智能和机器学习集成

人工智能和机器学习不再是学术概念,而是开发人员武器库中的强大工具。在后端开发中,它们在自动化任务、分析大量数据集和做出数据驱动的决策方面发挥着关键作用。以下是你如何利用它们来发挥自己的优势:

  • 代码生成:你可以生成代码片段甚至完整的块,从而节省时间并减少人为错误的机会。看看ChatGPT等工具:它们根据自然语言描述编写代码。
  • 安全性和代码质量改进:使用基于 AI 的代码审查工具分析代码库并识别潜在的 bug、安全漏洞和质量问题。例如,DeepCode 和 CodeClimate 可帮助开发人员编写更安全的代码。
  • 个性化:借助人工智能,你可以分析用户行为和偏好,以提供量身定制的内容和产品推荐。这样,你的 Web 和移动应用程序就会获得更高的用户参与度和留存率。
  • 预测分析:使用机器学习模型,可以预测用户操作。因此,你可以制定预防措施来解决可能出现的问题。
  • 推荐引擎:人工智能驱动的推荐系统根据客户的偏好和行为向客户推荐产品、服务或内容。利用这一趋势来提高用户参与度和转化率。
  • 聊天机器人和虚拟助手:要提升你的客户服务水平,请将 AI 驱动的聊天机器人集成到你的应用程序或网站中。他们可以处理客户查询,提供 24/7 全天候即时支持。

2、无服务器架构

无服务器架构是 Web 开发的一种趋势,将在 2024 年继续扩展。它通常被称为功能即服务 (FaaS),它消除了开发人员管理服务器的需要。相反,你可以专注于编写代码和部署函数,从而增强可扩展性和成本效益。

无服务器方法允许程序在基于云的服务器上运行。因此,你无需担心服务器可用性、容量或基础架构管理。AWS、Microsoft Azure Functions、Google Cloud Functions …

The post 2024年的后端和Web开发趋势 first appeared on Lenix Blog.

🔲 ☆

VoIP 中的话音失真问题分析

By KSkun, 2021/2

前言

2020 年的疫情使得我经历了一整个学期的网课。课程资源的电子化有方便保存和分享的有点,但是网络状况等问题依然使线上教学成为一件非常折磨人的事情。我依然记得,在这半年里我经历了无数次的自己掉线、老师掉线、声音卡顿、视频变静止或者变糊等一系列问题。有时声音还会变的不自然,有一种电音的感觉(导致了某同学被称为电音女王)

为什么网络状况不佳会导致声音的卡顿、不自然和出现电音一样的失真呢?这便是本文将要探讨的问题。

VoIP 是什么?

既然需要研究在线语音通话,就必须先了解其工作原理。

面对面说话时,声音作为机械波通过空气等传播;打电话时,声音被转换为电信号,并通过电话网络传播到对方电话,再将电信号转换回声音;线上语音通话时,声音通过麦克风被设备采集为数字信号,再通过 IP 网络传输到对方设备上,这便基于 VoIP 技术。

图 1 VoIP 的系统结构[1]

VoIP(Voice over IP,基于 IP 的语音传输)是指利用 IP 网络与相关编码、协议、算法,对语音进行采集、处理、传输与还原的一种语音通话技术。[2]根据描述,我们可以把 VoIP 的工作流程整理如下:

  1. 输入:声音从麦克风输入设备,设备将其转换为数字信号;
  2. 编码:将一定时长的声音信号按指定规则编码;
  3. 传输:使用 RTP(Realtime Transport Protocol,实时传输协议)协议在 IP 网络上传输声音数据;
  4. 处理:利用一些规则与算法减少网络抖动的影响、提高声音质量与抑制回声等;
  5. 输出:通过音频设备输出处理后的声音。

网络不佳主要影响第 3 步的传输过程。为了提供更好的实时性,RTP 协议工作在 UDP 协议之上,而 UDP 协议提供无保证的传输,因此容易发生丢包、乱序等问题。RTP 协议中,一个数据包包含一些必要的信息与一小段声音数据,因此丢包造成的影响直接体现为缺失某一段声音。[3]

话音失真现象

我们已经知道使用在线语音通话时,声音失真的问题应该是由丢包导致的,但丢包如何导致我们观察到的这些现象呢?接下来我们就将研究这一问题。

请注意:以下内容使用的示例可能会让您血压升高。

语音卡顿

由于 VoIP 基于 UDP 协议传输数据,而 UDP 是不可靠的,导致丢包时有发生。且因为通话的实时性,我们也无法重传丢失的数据,因此如何填充音频流中的空缺部分成为一个问题。

一个选择是直接填充空白,这可能导致说话时,音节中出现不自然的空白。这种情况听起来一卡一卡的,即卡顿现象。下面是一段在 10% 丢包率下,以空白填充缺失部分的语音示例:[4]

10pct_rand_silence.wav *请在参考资料中获取音频

通过这个示例,我们发现,如果空缺部分覆盖了语音的辅音,很容易造成语音难以辨认。且空白段的存在造成了部分爆破音与不自然的听感,听起来非常难受。

「电音」

在空缺部分填充空白的效果不佳,因此需要采用其他方法填充,这便是 PLC(Packet Loss Concealment,丢包隐藏)算法。一种常用的方法是重复输出最后收到的一小段,这在丢包率较低的时候效果良好,但当丢包率升高时,则容易出现类似合成声音的机械音(robotic)效果,也就是所谓的电音。下面是一段在 40% 丢包率下,以重复播放最后一段填充的语音示例:[5]

40pct_rand_plc.wav *请在参考资料中获取音频

接下来的问题是,为什么这种方法会使声音听起来像合成声音。不妨换个角度,先来看看如何制造听起来很机械的合成声音。Valve 公司开发的 Portal 系列游戏中有一个人工智能角色 GLaDOS,其语音就具有这样的特点,以下是 Portal 2 游戏中的一个片段:[6]

GLaDOS_voice.mp4 *请在参考资料中获取音频

Valve Developer Community 中给出了一种将正常语音处理出此效果的方法:固定声调、抑制声调变化[7],这可以通过某些声音处理软件实现。接下来,我们通过 Melodyne 软件来对一段正常的语音进行以上处理,以制造类似电音的效果。

【Melodyne 使用】 *请自行搜索相关示例

通过这个例子,我们知道,如果声调变化较小,声音听起来就像合成声音。而如果我们连续重复播放最后一段,由于传输时音频切分的较短,会使填充的部分声调单一化,出现类似以上处理的效果。这也说明,通过重复最后一段进行 PLC 处理的做法不总是能得到好的效果,我们需要改进。

ITU-T G.711 附录 I

国际电信联盟在文档 ITU-T G.711 附录 I 中提供了一种比较好的 PLC 算法。该算法工作在 PCM(Pulse Code Modulation,脉冲编码调制)编码下,采样频率为 8kHz,且一帧为 10ms(80 个样本),流程如下:[8]

  1. 在正常接收数据时,保存最后的 48.75ms 数据且延迟 3.75ms 输出;
  2. 遇到第一个丢帧时,进行如下工作:
    • 估计声音的周期:用最后的 20ms 声音向前计算相关性数值,取相关性最强的位置计算周期;
    • 填充第一个丢帧:使用计算出的最后一个周期重复来填充第一个丢帧,且前后各取 1/4 周期做平滑过渡的处理;
    • 将生成的一帧保存下来;
  3. 如果第一个丢帧之后还有丢帧,此时继续重复周期将可能生成不自然的声音,因此要引入变化与衰减来调整声音;
  4. 与之后正常数据的衔接处也需要平滑过渡处理。

这种处理方式引入了周期的估计、过渡平滑与引入衰减等处理,相比机械地重复最后一帧效果有极大提升。下面是一段 40% 丢帧率下,使用此方法填充丢帧的示例[9]

male1_3_itut_20ms_40.wav *请在参考资料中获取音频

可以观察到,此方法填充后效果良好。但与机械重复相比,此方法必须进行大量数学运算且必须引入延迟,可能影响通话效果。

结语

本文中,我们简单介绍了 VoIP,并研究了 VoIP 中影响通话质量的问题表现、原因,也讨论了几种对于此问题的解决方法。语音通话是一项要求强实时性的业务,用户可以忍受一定程度上的丢帧,我们必须在延迟和丢帧影响上做平衡。因此,也许我们可以使用更好的方法处理丢帧问题,但由于会引入延迟、消耗算力,实际应用中有时不会采用这些方法。

本文并未深入介绍 VoIP 的相关原理,也只提到了几种解决丢帧问题的方法。在这些方法之外,还有其他从信号处理或人工智能角度解决问题的方法,有兴趣的读者可以自行了解。

参考资料

The post VoIP 中的话音失真问题分析 first appeared on KSkun's Blog.
🔲 ☆

网络安全xss和csrf入门

在互联网的世界里面,安全始终是一个极为重要的问题。平时自己写demo时候往往会忽略这一点,但是,一旦想要成为产品,安全是一定要放在第一位的。在web开发中,理解常见的网络安全隐患,知道其原理并学会防护是一项重要的技能。

XSS

什么是xss

XSS全称跨站脚本攻击(Cross Site Scripting),是一种非常经典的网络攻击方式,它的攻击方法很简单,就是把脚本写到要攻击的网站上执行。

如何让别人的页面执行自己的脚本,这就是一个注入的过程,xss注入方式主要分两种,反射型xss和存储型xss。

存储型xss

存储型xss非常直接,向内容需要提交到数据库输入框中输入<script></script>标签,里面直接写自己的脚本,然后,数据存到数据库,别人浏览的时候从数据库读取内容,当浏览器解析到script标签的时候,就会执行里面的js代码,这就完成了一次简单的注入。注入的手段有很多,除了script之外,比如一个img标签,如果加载不到资源会触发一个onerror回调函数,这样也可以执行注入的脚本。存储型xss的特点就是,xss攻击内容是持久化的。

反射型xss

反射性xss的特点就是非持久化,需要用户交互,典型的方法比如在url参数中注入script标签,如果是需要获取请求参数的页面,页面加载的时候就会读取到脚本内容,从而执行攻击代码。这种方式工作的前提是诱导用户点击攻击url,不过脚本内容是不需要进入数据库的,进页面即可触发。

道理都是一样的,接下来就是做注入之后的事了。

一个网站上如果能随意执行其他人的脚本,其实是非常可怕的一件事。首先js能修改页面内容,能跳转链接,对方可以做很多恶意操作。而且,js可以获取cookie,cookie泄露的后果大家应该都懂。

xss防范

防范xss攻击是一个很重要的工作,最基本的原则就是,不要相信任何来自用户的输入,一切可以注入的机会都要严格防范。此外,即便保证输入安全,也要做好有不安全内容的准备,所以,在页面上展示的内容一定要经过转义编码,不要给任何外来脚本执行的机会。此外,可以将cookie设置HttpOnly,这样可以避免js获取cookie,避免了由于cookie泄露造成的危害,即便有xss漏洞,也能将损失降到最低。

CSRF

什么是CSRF

CSRF全称跨站请求伪造(Cross-site request forgery),指的是利用各种不法手段,在用户不知情的情况下以用户身份发送恶意请求。

举个简单的csrf例子,用户登录了a网站,此时登录攻击网站b,b网站如果直接跳过去操作a网站的话,是以登录用户的身份来做的,它可以在用户不知情的情况下以用户身份操控a网站,这就是csrf。

csrf防范

防范csrf的方式主要有三种:

  1. 验证HTTP Referer字段:在HTTP头中有Referer字段,它记录该HTTP请求的来源地址,如果跳转的网站与来源地址相符,那就是合法的,如果不符则可能是csrf攻击,拒绝该请求。

  2. 在请求地址中添加token并验证:在请求的时候加一个随机产生的token,token是存入数据库之后,后台返给客户端的,如果客户端再次登录的时候,后台发现token没有,或者通过查询数据库不正确,那么就拒绝该请求。

  3. 在HTTP头中自定义属性并验证:原理和上面其实一样,只是验证信息这次被加到了http请求头里面,每次只要验证即可。


以上是关于web安全的一点内容,只能算是认识了解了一下,安全无小事,网站的安全也应当高度重视。

🔲 ⭐

Pick 阿里巴巴前端练习生计划,成为专业前端人!

迈入大学校园的那一刻,除了满怀期待迎接大学生活的同时,同学们也开始了专业领域的知识储备,为走出校园、走向工作岗位打好基础。在这快速发展的互联网时代,如何选择一个有前景的领域,值得自己花上几年或几十年深入耕耘,择一行终生,爱一行终老,是很多即将步入社会的准毕业生最大的挑战。 得益于发达的信息分享...
❌