第 7 部分 · 走向生产:工程化与实战
稳定上线——给 Racket Web 程序配好 Nginx
写好的 Racket Web 程序怎么对外服务?答案分两层:Racket 在本机一个端口上稳定响应 HTTP,剩下的——HTTPS、反向代理、静态资源、进程守护——全部交给 Nginx。这篇把这条最省心的部署路线完整走一遍。
不假设你熟悉运维,只假设你已经:
- 能用 Racket 写一个 Web 程序(
web-server或类似框架) - 能在服务器上运行 Racket 程序
为什么需要 Nginx
很多人会直接这样做:
racket main.rkt
然后让程序监听 0.0.0.0:8000,再直接通过 IP 访问。
这 可以跑,但并不适合正式部署,原因包括:
- Racket Web Server 不擅长处理大量并发连接
- HTTPS、证书管理很麻烦
- 静态资源(CSS / JS / 图片)效率低
- 端口暴露、进程管理不规范
Nginx 的角色是:
- 作为对外的 Web 入口(80 / 443)
- 处理 HTTPS、反向代理、静态资源
- 把请求转发给后端的 Racket 程序
经典结构如下:
[ Browser ]
|
v
[ Nginx ] :80 / :443
|
v
[ Racket Web ] :127.0.0.1:8000
一个最小可部署的 Racket Web 程序
我们先准备一个 最简单但规范 的 Racket Web 服务。
1. 示例代码
#lang racket
(require web-server/servlet
web-server/servlet-env)
(define (start req)
(response/xexpr
`(html
(head (title "Racket + Nginx"))
(body (h1 "Hello from Racket")))))
(serve/servlet start
#:port 8000
#:listen-ip "127.0.0.1"
#:servlet-path "/"
#:launch-browser? #f)
几个关键点:
127.0.0.1:只允许本机访问(安全)- 固定端口:便于 Nginx 转发
- 不自动打开浏览器
运行后,本机访问:
http://127.0.0.1:8000
Nginx 的核心概念(够用版)
在部署 Racket Web 时,你只需要理解三件事:
反向代理(reverse proxy)
Nginx 接收请求 → 转发给 Racket → 再把响应返回给客户端。
upstream(可选)
当你有多个后端实例时使用,新手可以先不用。
location
用来匹配 URL 路径,并指定处理方式。
最小 Nginx 配置(HTTP)
假设你的 Racket 程序运行在:
127.0.0.1:8000
创建站点配置
sudo nano /etc/nginx/sites-available/racket-app
基础配置内容
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
启用配置
sudo ln -s /etc/nginx/sites-available/racket-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
现在访问:
http://example.com
请求路径为:
Browser -> Nginx :80 -> Racket :8000
HTTPS(Let's Encrypt)
现实部署中 强烈建议使用 HTTPS。
安装 Certbot
sudo apt install certbot python3-certbot-nginx
自动配置证书
sudo certbot --nginx -d example.com
Certbot 会:
- 自动修改 Nginx 配置
- 添加 443 端口
- 配置证书路径
- 设置 HTTP → HTTPS 跳转
你不需要改 Racket 程序任何代码。
静态资源交给 Nginx
不要让 Racket 去处理 CSS / JS / 图片。
项目结构示例
app/
├─ main.rkt
└─ static/
├─ style.css
└─ app.js
Nginx 配置静态目录
location /static/ {
alias /home/user/app/static/;
}
Racket 中引用
<link rel="stylesheet" href="/static/style.css">
这样:
/static/*→ Nginx 直接返回/→ Racket 处理
性能和结构都会更清晰。
Racket 程序如何长期运行
不要用 SSH 会话跑
错误示例:
ssh server
racket main.rkt
使用 systemd(推荐)
创建服务文件:
sudo nano /etc/systemd/system/racket-app.service
[Unit]
Description=Racket Web Application
After=network.target
[Service]
User=www-data
WorkingDirectory=/home/user/app
ExecStart=/usr/bin/racket main.rkt
Restart=always
[Install]
WantedBy=multi-user.target
启动服务:
sudo systemctl daemon-reexec
sudo systemctl enable racket-app
sudo systemctl start racket-app
常见问题与排查思路
浏览器 502 Bad Gateway
- Racket 程序是否在跑?
- 端口是否一致?
- 是否监听在
127.0.0.1?
访问慢
- 静态资源是否仍由 Racket 提供?
- 是否开启 gzip(Nginx 默认支持)
路径不对
proxy_pass是否带/- Racket 是否假设根路径为
/
部署的心智模型
作为 Racket 开发者,你可以这样理解:
- Racket:业务逻辑、状态、规则
- Nginx:网络、协议、安全、性能
你只需要保证:
Racket 程序在本机一个端口上 稳定响应 HTTP
剩下的,全部交给 Nginx。
结语
Nginx 并不是 Racket 的对立面,而是它在生产环境中的 天然搭档。
一旦你掌握了这个部署模式,你会发现:
- 本地开发 → 服务器上线几乎无差别
- Racket Web 完全可以胜任严肃的服务端工作
这正是 Racket 作为「可扩展语言」在工程实践中的价值所在。