C 语言中的现代 Web 应用
用 CGI、SQLite 和 OpenBSD 的 httpd 以纯 C 构建“现代” Web 应用,再次点燃了人们对极简技术栈的热情,同时也重新激起了关于 C 的安全性以及它是否适合暴露在互联网上的服务的长期争论。许多评论者喜欢单个静态二进制按请求调用所带来的简洁性、可预测性和极小依赖面,尤其是与 nginx、应用服务器和大型框架组成的多层架构相比。批评者则反驳说,字符串处理、并发和内存安全问题使 C 不如 Go、Rust 或 PHP/FastCGI 适合,并认为任何性能或架构上的收益都必须与安全风险以及现代可观测性和维护的现实相权衡。
C 和 BCHS 技术栈的选择
- 许多人对用纯 C、OpenBSD httpd 和 SQLite(BCHS)构建一个“现代” Web 应用感到好奇。
- 推测的动机包括:最少的依赖、可预测的行为、与 OpenBSD 的 pledge/unveil 紧密契合,以及那种 C“装得进脑子里”的感觉。
- 有人质疑为什么选择 C,而不是 C++、Rust、Go 或 PHP,认为其他语言也能提供类似的简洁性,同时具备更好的安全性和工具支持。
CGI、进程模型和性能
- 核心设计:CGI,每个请求启动一个全新的进程。支持者喜欢这种隔离、极其简单的部署方式(替换一个二进制文件即可),以及不需要复杂应用服务器。
- 批评者称 CGI 是“折中方案”且“低效”,指出进程创建有开销,并且缺乏共享状态;他们建议改用 FastCGI、进程内模块,或者自定义 HTTP 服务器。
- 也有人反驳说,现代内核让
fork对低/中流量来说已经足够便宜,并把这种模型比作今天的“serverless”函数。
SQLite 和并发
- 有人提出多个并发请求同时访问一个 SQLite 文件会怎样。
- 回应是:启用 WAL 模式后,可以实现多个并发读者和单个写者;文件锁机制处理进程并发。写入仍会串行化,但由于没有网络往返,速度很快。
字符串处理和 C 的易用性
- 有几位指出,用 C 输出 HTML/CSS 其实还能接受;真正痛苦的是解析和通用字符串处理。
- 有人通过自定义字符串构建器/视图以及固定大小缓冲区来缓解,从而避免分配。
安全性和语言选择
- 对于把新的 C 代码暴露到互联网上,分歧很大。
- 批评者:C 的内存不安全会导致反复出现远程代码执行(RCE);更安全的选择(Rust、“C 风格的 C++”)是存在的。
- 支持者:大多数底层基础设施(内核、Web 服务器、数据库)本来就是 C/C++;如果设计谨慎、利用 OpenBSD 的加固机制,并让代码规模小且可审计,C 也可以是安全的。
- Rust 因内存安全而受到称赞,但也因庞大的依赖图和“供应链”风险而受到批评;相比之下,C 被看作是在牺牲内存安全的同时,换来更简单、更小的依赖面。
简洁性与现代技术栈
- 许多人对 CGI 和早期 PHP/Perl 时代怀有怀旧之情,也对当今多层技术栈(nginx → 应用服务器 → 框架 → ORM 等)感到疲惫。
- 有些人认为现代各层带来了必要功能(可观测性、扩展、限流),而另一些人则认为这些对小型网站和内部工具来说过度了。
前端、用户体验与 AI 写作担忧
- 多位评论者觉得展示的网站设计难以阅读,且对比度很低。
- 有几位怀疑博客文章的部分内容是 AI 写的,不过也有人不同意,并指出 AI 检测器并不可靠。