这是长篇深入探讨。如需更快、略读的版本,请参阅 同伴博客文章.

1. 简介:习惯堆栈与实际工作负载
成熟组织中的技术选择很少会失败,因为没有人阅读基准博客文章。他们失败是因为 过程 选择是很弱的:大声的高级工程师的偏好,充满一种语言的招聘渠道,或者会议上令人印象深刻的演示。与此同时,该产品混合了对延迟敏感的 API、批量协调、NGINX 中的边缘身份验证、内部 CLI 以及偶尔出现的无服务器峰值。一个运行时间不可能对所有这些形状都是最佳的。
这篇文章解释了 多语言基准 — 实时比较仪表板和开放的 工作流程示例/基准 背后的安全带——作为 决策框架,不是粉丝排行榜。目标是您可以附加到架构决策记录 (ADR) 的证据:相同的端点、相同的负载生成器、相同的容器布局、多种语言。
我不会在散文中发明吞吐量数字。当您运行该工具时,仪表板会显示该硬件和 Docker 设置的测量请求数和延迟百分位数。将此处的任何静态排名视为与线束的测试系列和仪表板的内置判决副本一致的定性模式。
2. 什么是多语言基准?
多语言基准 托管于 多语言基准.fictionally.org (工作流示例生态系统中虚构品牌的基础设施)。登陆标题比较:
- NGINX NJS — Stock NGINX 中的 JavaScript 模块
- OpenResty Lua — Lua 处于 OpenResty 的边缘
- Python FastAPI — Uvicorn ASGI 应用程序
- 转到网络/http — 标准库服务器
- Rust Actix-web — Actix 上的异步 HTTP
- 包子 — 使用本机 HTTP 服务器的 JavaScript 运行时
- Java (Javalin / Jetty) — Jetty 上的轻量级 JVM HTTP
- Kotlin (Ktor / Netty) — Netty 上协程友好的 JVM HTTP
直播标题是 8种语言 比较: njs、Lua、Python、Go、Rust、Bun、Java、Kotlin。副标题阐述了意图:性能 长轮询/聊天/队列/API 工作负载 — 大量连接、大量 JSON 和大量路由的路径,而不是单一的“hello world”战车竞赛。 JVM 商店最终获得了与 Go/Rust/Bun 相同的公平表面,而不是一个单独的“企业”轶事。
2.1 仪表板显示内容
当运行进行时,UI 会进行轮询 /data/results.json 每两秒渲染一次:
- 请求/秒(吞吐量) — 汇总自
wrk每个语言每个测试 - 平均延迟 和 P99 尾部潜伏期 — 来自 wrk 延迟模型的毫秒数
- TTFB(第一个字节的时间) — 来自curl 计时 JSON 和 wrk
- 汇总表 — 每次测试的获胜者在最佳细胞上具有 ★ 标记
- 详细的测试卡 — 条形图和指标表(P50、P90、P99.9、错误)
- 延迟百分位分布 - 测试的平均值
- 结论——最适合您的用例 - 一旦状态为叙述
complete
这种结构故意是 ARB 友好的:幻灯片图表、电子表格表格、ADR 风险部分的叙述。
3. 工作流程示例工具
一切可复制的东西都生活在 benchmarks/ 在 工作流程示例 存储库。顶层布局:
benchmarks/
bench.sh # orchestrates tests, writes results.json
wrk_json.lua # wrk done() → JSON summary (RPS, percentiles)
docker-compose.yml # eight app services + dashboard + bench runner
njs/ # NGINX + njs module
lua/ # OpenResty nginx.conf
python/ # FastAPI + Dockerfile
golang/ # net/http main.go
rust/ # Actix-web + Cargo
bun/ # Bun server.ts
java/ # Javalin on Jetty
kotlin/ # Ktor on Netty
dashboard/ # static index.html + nginx.conf
3.1 Docker Compose拓扑
docker-compose.yml 定义共享网络上的隔离服务:
nginx-njs— 端口 8081,配置来自./njsopenresty-lua— 端口 8082python-fastapi— 端口 8084,构建于./pythongo-server— 端口 8085rust-actix— 端口 8086bun-server— 端口 8087java-server— 端口 8088,Javalin / Jetty 来自./javakotlin-server— 端口 8089,Ktor / Netty 来自./kotlindashboard— 端口 8083,提供 HTML 服务并安装results体积在/databench— 安装的 Alpine 容器curl,wrk,jq,等待依赖关系,运行bench.sh
板凳跑者分享 results 与仪表板的音量,因此结果实时显示,无需手动复制。
3.2 bench.sh方法论
shell 驱动程序显式地编码公平规则:
- 期间:
10s每个端点每种语言 - 主题: 4
- 连接: 100个并发
- 热身: 50发射击
/hello在定时测试之前在每台服务器上 - 每台服务器: 卷曲计时 JSON(dns、connect、ttfb、total)加上 wrk
wrk_json.lua
脚本中的七个测试是用竖线分隔的:
| ID | 姓名 | 意图 | 端点 |
|---|---|---|---|
| 1 | 纯文本 | 基线——最小响应、框架开销 | /hello |
| 2 | JSON序列化 | 构建并序列化 100 项 JSON 数组 | /json |
| 3 | CPU-绑定(fib 30) | 递归斐波那契(30) — 纯 CPU | /cpu?n=30 |
| 4 | 字符串操作 | 构建、拆分、大写、重新连接 1000 个段 | /string |
| 5 | 请求检查 | 标头、方法、参数 → JSON | /request_info?foo=bar&baz=123 |
| 6 | 子请求+转换 | 内部子请求、解析JSON、转换 | /subrequest |
| 7 | 路由逻辑 | 查询参数的条件路由 | /route?action=greet&name=bench |
每种语言都实现相同的路线表面(请参阅 golang/main.go, python/main.py, java/, kotlin/、NGINX 配置等),因此差异反映了运行时和框架,而不是不匹配的规格。
4. 为什么“多语言”很重要(没有狂热)
多语言架构并不意味着每个工程师都学习八种语言。这意味着 有界上下文 获得适合的运行时:
- 边平面 — 身份验证、速率限制、路由:您已经在 NGINX 中运行 Lua 或 njs
- 核心API平面 — SLO 的业务逻辑:Go 或 Rust
- JVM平面 — 现有的 Spring/Jakarta 庄园、共享库、招聘深度:Java (Javalin) 或 Kotlin (Ktor)
- 数据平面 — ETL、笔记本、ML 胶水:Python
- 实时JS飞机 — WebSockets,与前端共享的类型:速度获胜的 Bun 或 Node
统一堆栈优化人力资源和采购。多语言基准优化 适合每个工作负载 并进行可衡量的权衡。
5. 重要的尺寸
原始请求/秒是 Slack 上传输速度最快的指标。也是最容易误读的。使用多列标题:
| 标准 | 当…时占主导地位 | 线束信号 |
|---|---|---|
| p50 / p99 潜伏期 | 面向用户的 API、聊天、长轮询 | wrk 延迟百分位数;仪表板P99图表 |
| 吞吐量(RPS) | 高扇出网关、批量聚合器 | 工作 RPS;获奖者总结专栏 |
| 每个连接的内存 | 数千个闲置 WebSocket | 定性+生产分析(未完全掌握) |
| TTFB | CDN未命中、冷路径、移动网络 | 卷曲 time_starttransfer 在结果 JSON 中 |
| LOC/复杂性 | 初创企业,受监管的变更控制 | 比较跨文件夹的实现 |
| 构建和 CI 时间 | 部署频繁,服务众多 | Docker 为每种语言构建配置文件 |
| 运营负担 | 小平台团队 | 现有 NGINX 技能 → Lua/njs;其他容器 |
| 托管费用 | 始终开启与缩放至零 | 源自内存+负载下的CPU(生产) |
6. 决策矩阵
下图是我们在评论中使用的定性地图 - 说明性领导者,不能替代在您的套件上运行线束。

按行优先阅读:选择您的工作负载形状,然后选择权重列。如果两个标准发生冲突(例如最佳 RPS 与最低 LOC),那么 ADR 讨论就值得讨论这种张力。
7. 大小写模式(示例标签)
下面将测试系列与架构选择进行了映射。跑步后,机器上的领先者会出现在仪表板上 - 不要将此部分视为固定分数。
7.1 API 延迟敏感(测试 1–2、5–7)
JSON API 和路由密集型处理程序镜像测试 2、5 和 7。编译的异步运行时(Rust Actix、Go)通常在此类综合 HTTP 基准测试中领先于吞吐量和尾部延迟; Bun 经常位于 JSON 密集的路径上,具有 JS 人体工程学原理。 Java (Javalin) 和 Kotlin (Ktor) 让 JVM 团队能够公平地了解那些走相同路线的领导者——当问题是“用更轻的堆栈留在 JVM 上”与“用 Go/Rust 重写”时,这很有用。 Python FastAPI 用原始 RPS 来换取开发速度——仪表板判决明确指出了这一点。
7.2 CPU绑定的微工作(测试3)
Fibonacci(30) 隔离 CPU,无需 I/O。期待 Rust 和 Go 能够大放异彩;解释堆栈支付开销;预热后,JVM JIT 看起来比冷的 10 秒窗口所暗示的更强大 — 如果这是您的真实配置文件,请延长持续时间。如果您的实际服务受 I/O 限制,请不要过度重视这一行 — 这是对计算密集型中间件的压力测试,而不是典型的 CRUD。
7.3 边缘变换(测试 6-7,NGINX 变体)
子请求和路由测试在哪里 OpenResty Lua 和 NGINX NJS 属于:零额外跳跃、共享工作内存、运维团队已经管理 NGINX。该工具的结论建议将 Go/Rust 用于核心聊天/队列后端,而将 Lua/njs 用于边缘——这是许多企业已经非正式运行的明智划分。
7.4 批量ETL和数据管道
HTTP 工具不会模拟 Spark 或仓库负载。对于批处理,团队通常会优先考虑 Python 生态系统和编排(Airflow、Dagster)或 Go 工作线程以提高吞吐量。使用多语言基准 API 表面和控制平面 这些作业公开,而不是针对批处理引擎本身。
7.5 快速内部工具
具有低 QPS 和高变更率的内部管理 API:Python 或 Bun/Node 通常在速度和招聘方面获胜。运行测试 2 (JSON) 和测试 5(检查)以确保开销是可以接受的;如果 p99 的连接数峰值低于 100 个,请在升级到面向客户的级别之前重新考虑。
7.6 JVM 空间(Java 和 Kotlin)
许多企业已经运行 Java 或 Kotlin 来实现共享库、合规工具和招聘深度。安全带的 java-server (Jetty 上的 Javalin,端口 8088)和 kotlin-server (Netty 上的 Ktor,端口 8089)实现与 Go 和 Rust 相同的七个端点,因此您可以在重写之前量化较轻的 JVM HTTP 堆栈对于给定的 SLO 是否“足够好”。当协程式并发和 Kotlin 优先团队很重要时,首选 Kotlin;当周围的环境和库图已经以 Java 为中心时,更喜欢 Java。使用实时仪表板行 - 不要假设 Spring Boot 编号等于 Javalin/Ktor 编号。
8. 工作流程图

可重现的循环:指定工作负载→运行 Compose 工具→将结果发布到 Fictionally 仪表板(或您的内部克隆)→使用配置元数据记录 ADR→在运行时或硬件更改时重新运行。
9. 如何进行自己的比较
- 克隆:
git clone https://github.com/bwalia/workflow-examples.git && cd workflow-examples/benchmarks - 启动堆栈:
docker compose up --build— 构建所有语言映像,在端口 8083 上启动仪表板,自动运行工作台。 - 手表: 打开
http://localhost:8083(或托管运行处于活动状态时的公共站点)。 - 延长: 添加文件夹
myruntime/,镜像端点路径,在中注册服务docker-compose.yml,将服务器附加到SERVERS在bench.sh. - 自定义负载: 编辑
DURATION,THREADS,CONNECTIONS在顶部bench.sh— 记录 ADR 中的变更。 - 添加生产型测试: 例如auth 中间件、ORM 查询、50KB 负载 — 保持跨语言的一致性。
对于 CI,在夜间工作流程中运行 Compose,存档 results.json 作为工件,并且仅在您定义的回归阈值上失败(例如,在测试 2 中,p99 每周增加 20%)。
10.反模式
- 仅选出测试 1 的获胜者 — 纯文本有利于最小的堆栈;它忽略了 JSON、CPU 和路由难题。
- 忽视团队能力 — 在没有导师的情况下,生产中的 Rust 在事故发生时成本高昂。
- 忽略托管成本 — 如果每个 Pod 的内存使您的账单翻倍,那么 2× RPS 就没用了。
- 在整个组织范围内强制使用一种语言 - 破坏合法的边缘与核心分裂。
- 替换生产分析 — 合成 HTTP ≠ 您的 ORM、缓存或区域延迟。
- 不同硬件的比较 — 笔记本电脑 Docker ≠ 裸机 ≠ K8s 限制;请注意 ADR 中的类别。
11. 工程领导力的好处
- ARB 包 — 导出仪表板屏幕截图 +
results.json+ 编写哈希。 - 供应商中立的证据 — 没有来自单一云或框架供应商的销售平台。
- 入职清晰度 — 新员工了解*为什么*服务 A 是 Go,服务 B 是 Python。
- 降低风险 — 在重写之前在影子服务中试运行亚军。
- 金融运营对话 — 将尾部延迟链接到自动缩放和内存空间。
- 平台路线图 — 与其他 K8s 微服务相比,证明 NGINX 技能投资的合理性。
12. 限制
- 综合工作负载 — 七个 HTTP 测试无法代表 Kafka 消费者、GPU 作业或复杂的 ORM 图。
- Docker 网络 ——增加开销;绝对数量与裸机不同。
- 单机类 — 托管结果反映了虚构使用的任何硬件;你的数字会有所不同。
- 无持久层 — 设计上不存在数据库和缓存效果。
- 运行时间短 — 每次测试 10 秒可能不会暴露 GC 暂停或预热悬崖;延长压力活动。
将连续分析(eBPF、APM、针对登台的负载测试)作为生产的真实来源。多语言基准缩小了范围 语言和框架 与可重复的基线进行辩论。
13. 结论
默认堆栈偏差很舒服;这也是团队为作业提供错误运行时的方式。 多语言基准 和 工作流程示例 驾驭转向“哪种语言获胜?”进入“哪种语言获胜 对于该工作负载行?” — 带有您的 ARB 可以引用的图表。
分叉存储库,添加看起来像热路径的端点,运行 Compose,并将结果附加到下一个架构决策。同伴 博客文章 是五分钟的分享版本;这篇文章是参考。
发布者: Workstation (workstation.co.uk)。基准仪表板托管于 多语言基准.fictionally.org 在虚构示例生态系统中。
本文的 SEO 快照
- 搜索引擎优化标题: 多语言基准:适合工作的正确工具
- 元描述: 在相同的 HTTP 工作负载上比较 njs、Lua、Python、Go、Rust、Bun、Java 和 Kotlin。可复制的工具、实时仪表板、建筑师的决策矩阵。
- 主要关键词: 多语言基准、语言比较、架构决策、工作流程示例、性能基准、Rust 与 Go、Java 与 Kotlin、FastAPI、Javalin、Ktor
- Twitter / X(280 个字符以下): 多语言基准:跨 njs、Lua、Python、Go、Rust、Bun、Java、Kotlin 的相同 7 个 HTTP 测试 — 实时仪表板 + 工作流程示例工具。没有一个赢家;决策框架。 #Rust #GoLang #Java #Kotlin #Bunjs #polyglot
- 领英帖子: 我们发表了一篇关于多语言基准的深入研究——如何停止从习惯中选择一个组织范围的堆栈,并开始将运行时与工作负载相匹配。八种语言(包括 Java/Javalin 和 Kotlin/Ktor)、七种可比较的测试、Docker Compose + wrk、polyglot-benchmarks.fictionally.org 上的实时结果,来源为 github.com/bwalia/workflow-examples/tree/main/benchmarks。包括决策矩阵、反模式和 ADR 指南。来自 Workstation 工程。 #Rust #GoLang #Java #Kotlin #Bunjs #Lua #Python #njs #FastAPI #Javalin #Ktor #OpenResty #polyglot #benchmarks