一个Erlang风格的纯Scheme Web服务器及更多内容
A Erlang style pure Scheme Webserver and further

原始链接: https://igropyr.com

这是一个基于 Scheme 的高性能 Web 框架,专为极致并发、容错能力和开发者控制而设计。该框架采用核心/框架分离的架构,利用轻量级“绿色”进程和基于延续(continuation)的抢占式调度,能够在不造成系统阻塞的情况下处理数千个并发请求,包括 CPU 密集型任务。 主要特性包括: * **弹性:** 基于监督者(supervisor)的进程池可处理崩溃、超时和自动重试。通过可选的“故障钩子”,支持结构化的 JSON 错误恢复。 * **有状态对话:** 进程可在多请求对话中保持实时状态(包括数据库事务),并确保在失败时自动回滚。 * **灵活性:** 支持热代码替换、WebSocket 升级、流式传输以及服务器推送事件(SSE)。 * **全栈支持:** 包含针对 Redis、MySQL 和 HTTP 的非阻塞客户端,并内置对会话、Cookie、表单和 Gzip 压缩的支持。 * **基础设施:** 提供稳健的运维工具,包括 `SO_REUSEPORT` 扩展、Prometheus 指标监控和优雅停机功能。 该框架通过非阻塞 I/O 模型(基于 libuv)实现了约每秒 3.5 万次请求的处理能力,同时保持了进程间的严格隔离。这是一个强大且“开箱即用”的工具集,借鉴了 Erlang/OTP 的设计理念,非常适合构建高扩展性、高可靠性且易于诊断的 Web 服务。

Hacker News 最新 | 往期 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 一个 Erlang 风格的纯 Scheme Web 服务器及更多内容 (igropyr.com) 9 分,发布者:guenchi,1 小时前 | 隐藏 | 往期 | 收藏 | 1 条评论 帮助 guenchi 1 小时前 [–] “Let It Crash”(任其崩溃)、热代码热交换、远程重试环、基于延续(Continuation)的 Web 编程、S-expr RPC(使用 goeteia.dev) 回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

Core / framework split, like Node and Express the core exposes one entry point, (http-listen port (lambda (req res) ...)); the bundled (igropyr express) layer (create-app, app-get, send-json!, ...) is optional, and alternative frameworks can be built on the same core

Green processes thousands of lightweight processes scheduled over one OS thread; continuation-based context switching with preemption, so even a CPU-spinning handler cannot freeze the system

Pure message passing spawn / send / receive / link / monitor; no shared state between processes

Fault tolerant by default a fixed worker pool behind a supervisor: crashed workers are replaced and the task retried (at most 3 times, then the client gets a 500); workers stuck for more than 30 s are killed and replaced; a slow or half-sent request only ever blocks its own reader process

Failure hook (remote retry ring) when retries are exhausted or a stuck worker is killed (killed first, so no execution is in flight), an optional on-failure handler answers a structured JSON fault instead of the plain 500, on the same keep-alive connection — the client resubmits (changed parameters, carried state) and gets a fresh retry round; unset, the plain 500 remains

Conversations (process-per-dialogue) a multi-request dialogue runs as one green process holding live state — even an open database transaction — across rounds; suspend! answers and parks, conversation-resume! continues, and death for any reason (crash, TTL) means guaranteed rollback: a later resume gets gone

Hot code swapping replace the handler (or individual routes) on a live server: the listener, open connections and worker pool stay up, in-flight requests finish on the old code

WebSocket RFC 6455 upgrade on the same port; each socket is its own green process, so server push is just a message send

Streaming responses & SSE chunked response body via res-begin!/res-write!/res-end!; Server-Sent Events helpers on top

OTP building blocks gen-server (call/cast/info), a process registry (register/whereis), and topic PubSub with automatic cleanup of dead subscribers

JSON a safe recursive-descent parser (no read; full escape and surrogate handling) and writer

S-expression RPC when the peer is also Scheme there is no codec: (igropyr sexpr) is a safe whitelisted parser (no read, depth-limited), and app-rpc / send-sexpr! / ws-send-sexpr! / sse-send-sexpr! carry one datum per message — exact ratios and bignums cross intact. The browser end is Goeteia's (web rpc/ws/sse)

Forms & cookies req-form parses urlencoded and multipart bodies (file uploads included); req-cookie / set-cookie!

Middleware suite cookie sessions (gen-server store, CSPRNG sids), CORS with preflight, security headers, and an access logger

Chunked transfer-encoding Transfer-Encoding: chunked request bodies are decoded transparently

Non-blocking Redis and MySQL clients pure Scheme, same event loop; callers park their green process while the OS thread keeps serving; MySQL comes with a self-healing connection pool

Non-blocking HTTP & WebSocket clients outbound http-get / http-post and ws-connect, both with async DNS (libuv thread pool) and the same park-the-caller model

Async file reads static files are read on libuv's thread pool, so a large or cold read never blocks the scheduler

gzip compression responses negotiated via Accept-Encoding; static files cache their compressed form

Ops-ready rate limiting, a global error handler, and a Prometheus /metrics endpoint

Runtime introspection & graceful shutdown http-stats (live connection/request/pool counters), http-shutdown! (drain in-flight requests, refuse new connections)

Multi-process scaling SO_REUSEPORT bind option for kernel-balanced multi-process listening on Linux (pair with pm2 or systemd)

HTTP/1.1 keep-alive & pipelining persistent connections by default on 1.1; each connection's reader process loops over successive requests

Fast ~35 k req/s at 500 concurrent connections on an Apple Silicon laptop (ab -n 50000 -c 500, zero failed requests)

联系我们 contact @ memedata.com