飞牛 fnOS 深度解析(五):Web 后端架构深度解析
系列文章:
- 第一篇:系统基础与启动流程
- 第二篇:存储架构深挖
- 第三篇:系统目录结构与技术栈
- 第四篇:文件服务与用户权限体系
- 第五篇:Web 后端架构深度解析(本文)
- 第六篇:系统识别方法论与二次开发指南
如果说前四篇我们在看 fnOS 的"身体",那这一篇我们要看它的"大脑"——Web 后端架构。
fnOS 的 Web 管理界面是用户和系统交互的唯一入口,所有操作(创建用户、管理存储、安装应用)都通过它完成。搞清楚 Web 后端的架构,就等于拿到了二次开发的钥匙——你会知道 API 请求怎么走、后端服务怎么通信、自己的程序怎么耦合进去。
这一篇的内容全部来自实际的 Nginx 配置文件和系统探查,没有任何猜测。
一、整体请求链路
先看一张完整的请求链路图:
浏览器(React SPA)
↓ HTTP/HTTPS (5666/5667)
Nginx(自编译 + 自研模块)
↓ 反向代理
┌─────────────────────────────────────────────┐
│ 后端微服务集群(30+ 个,几乎全部 Unix Socket) │
│ │
│ 核心:trim_http_cgi (/cgi, /app/) │
│ 账户:accountsrv (/v1/accountapi) │
│ 相册:trim_photos (/p) │
│ 媒体:trim_media (/v) │
│ 分享:trim_share (/s/) │
│ 快照:trim_snapshots (/snapshot) │
│ 同步:trim_sync_server (/sync/) │
│ 搜索:trim_seek (/seek) │
│ 应用:trim_app_center (/app-center) │
│ Docker:dockermgr (/docker/*) │
│ 虚拟机:trim_vm (/vm) │
│ ...(共30+个后端服务) │
└─────────────────────────────────────────────┘
↓
PostgreSQL(127.0.0.1:5432,只监听本地)整个架构是典型的前后端分离 + 微服务:
- 前端是 React SPA,打包后的静态文件放在
/usr/trim/www/ - Nginx 既提供静态文件,又做反向代理,把 API 请求转发到后端服务
- 后端是 30+ 个微服务,每个负责一个功能模块
- 几乎所有后端服务都通过 Unix Socket 和 Nginx 通信,不是 TCP 端口
- 数据层是 PostgreSQL,只监听本地回环地址
二、Nginx:自编译 + 自研模块
fnOS 的 Nginx 不是系统自带的,而是自己编译的,安装在 /usr/trim/nginx/。主配置文件是 /usr/trim/nginx/conf/nginx.conf。
2.1 重大发现:飞牛自研了 Nginx 模块
load_module modules/ngx_http_trim_cert_module.so;飞牛编译了自己的 Nginx 动态模块 ngx_http_trim_cert_module,用于证书管理和动态切换。相关配置:
trim_cert_cfg_path /usr/trim/etc/network_gateway_cert.conf;
trim_hook_cert_switch on;
ssl_certificate $ssl_server_name;
ssl_certificate_key $ssl_server_name;| 配置 | 说明 |
|---|---|
trim_cert_cfg_path | 证书配置文件路径 |
trim_hook_cert_switch on | 开启证书切换功能 |
ssl_certificate $ssl_server_name | 动态证书——根据 SNI(服务器名称指示)选择对应证书 |
这说明飞牛对 Nginx 的定制不止是编译参数,还写了自己的模块。这个模块负责管理多域名证书、自动切换证书,可能和飞牛互联的远程访问域名有关。
2.2 监听端口与重定向
listen 0.0.0.0:5666 default_server;
listen [::]:5666 ipv6only=on default_server;
listen 0.0.0.0:5667 ssl http2 default_server;
listen [::]:5667 ssl http2 ipv6only=on default_server;
listen 0.0.0.0:80 default_server;
listen [::]:80 ipv6only=on default_server;
listen 0.0.0.0:443 ssl http2 default_server;
listen [::]:443 ssl http2 ipv6only=on default_server;
if ($server_port = 80) {
return 302 $scheme://$host:5666$request_uri;
}
if ($server_port = 443) {
return 302 $scheme://$host:5667$request_uri;
}| 端口 | 协议 | 作用 |
|---|---|---|
| 5666 | HTTP | Web 管理界面(主端口) |
| 5667 | HTTPS/HTTP2 | Web 管理界面(加密) |
| 80 | HTTP | 重定向到 5666 |
| 443 | HTTPS | 重定向到 5667 |
飞牛用 5666/5667 作为管理端口,80/443 只是重定向。这样做的好处是避免和其他 Web 服务冲突(比如用户自己装的 Nginx/Apache)。
2.3 性能与安全配置
user www-data;
worker_processes auto;
worker_connections 10240;
client_max_body_size 1000000g;
server_tokens off;| 配置 | 说明 |
|---|---|
worker_processes auto | 自动根据 CPU 核心数设置工作进程 |
worker_connections 10240 | 每个工作进程 10240 个连接(很大,支持高并发) |
client_max_body_size 1000000g | 上传文件大小限制 1000000G——几乎无限制,NAS 要传大文件 |
server_tokens off | 隐藏 Nginx 版本号,安全考虑 |
2.4 特殊 location
主配置里定义了几个特殊的 location:
# WebSocket
location /websocket {
proxy_pass http://trim_cgi;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 大文件上传
location /upload {
proxy_pass http://trim_upload;
proxy_request_buffering off;
client_body_buffer_size 512K;
tcp_nopush on;
}
# 下载
location /download {
alias /;
download_auth on;
}
# 应用 UI
location /appui {
alias /vol0/@appui;
}| location | 作用 | 特点 |
|---|---|---|
/websocket | WebSocket 连接 | 支持 Upgrade 头,转发到 trim_cgi |
/upload | 文件上传 | 关闭请求缓冲(proxy_request_buffering off),支持大文件流式上传 |
/download | 文件下载 | alias / 映射到根目录,download_auth on 开启下载认证 |
/appui | 应用 UI | 静态文件,在 /vol0/@appui |
2.5 Cookie v2→v1 转换
include globals/trim-cookie-v2-to-v1-map.conf;
proxy_set_header Cookie $trim_cookie_v2_to_v1_cookie;这是一个很有意思的细节:飞牛的认证系统有 v1 和 v2 两个版本的 Cookie,Nginx 层做了自动转换。说明认证系统在升级中,新旧版本兼容——老的后端服务只认 v1 Cookie,新的前端发 v2 Cookie,Nginx 在转发时自动转换。
三、30+ 后端服务的路由映射表
Nginx 主配置的最后一行是:
include conf.d/*.conf;所有 API 的反向代理规则都在 /usr/trim/nginx/conf/conf.d/ 目录下。我们看一下有多少个配置文件:
$ ls /usr/trim/nginx/conf/conf.d/
accountsrv.conf file_version.conf trimcon.conf
auto_thumbnailer.conf gzip.conf trim_docs.conf
baidu_netdisk.conf html_nocache.conf trim_http_cgi.conf
cloud_storage_dav.conf multiple_downloads.conf trim_iscsi.conf
docker_web.conf safe_code_access.conf trim_license.conf
download_web.conf trim_app_center.conf trim_media.conf
dsmgr.conf trim_chromium.conf trim_music.conf
trim_open_gateway.conf trim_photos.conf
trim_sac.conf trim_seek.conf
trim_sharelink.conf trim_snapshots.conf
trim_sync.conf trim_text_editor.conf
trim_txt_mime.conf trim_vm.conf一共 30 个配置文件,每个对应一个后端服务或功能模块。下面是完整的路由映射表:
3.1 核心服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim_http_cgi | /cgi、/app/ | Unix Socket | 核心 CGI 服务,大部分业务逻辑 |
| accountsrv | /v1/accountapi、/oauthapi | Unix Socket | 账户管理、OAuth 认证 |
| uploadsrv | /upload | Unix Socket | 文件上传(主配置里) |
3.2 媒体与内容服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim_photos | /p | Unix Socket | AI 相册 |
| trim_media | /v | Unix Socket | 媒体服务(视频转码等) |
| trim_music | /music | Unix Socket | 音乐服务 |
| auto_thumbnailer | /thumb | Unix Socket | 自动缩略图生成 |
| trim_seek | /seek | Unix Socket | 搜索(文件内容搜索?) |
| trim_docs | /docs | TCP localhost:10500 | 文档服务(OnlyOffice 文档服务) |
| onlyoffice | /onlyoffice/ | TCP localhost:10501 | 在线文档编辑 |
3.3 分享与同步服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim_share | /s/ | Unix Socket | 外部分享(分享链接) |
| trim_snapshots | /snapshot | Unix Socket | 快照管理 |
| trim_sync_server | /sync/ | Unix Socket | 文件同步(跨设备同步) |
| trim_sharelink | (独立配置) | Unix Socket | 收集链接 |
3.4 应用与虚拟化服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim_app_center | /app-center | Unix Socket | 应用中心 |
| dockermgr | /docker/* | Unix Socket | Docker 管理 |
| trim_vm | /vm | Unix Socket | 虚拟机管理 |
| trim_chromium | /chromium/ | TCP 127.0.0.1:3000 | 浏览器应用 |
| trim_iscsi | /iscsi | 静态文件 | iSCSI 管理 |
| file_version | /file-version | 静态文件 | 文件版本管理 |
| trim_text_editor | /app/text-editor | 静态文件 | 文本编辑器 |
3.5 系统与安全服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim_license | /license/ | Unix Socket | 许可证管理 |
| trim_sac | /sac/ | Unix Socket | 系统应用控制 |
| trim_open_gateway | /og.、/grpc. | gRPC over Unix Socket | 开放网关(gRPC 协议) |
| os-access-code | 全局 auth_request | Unix Socket | 安全访问码 |
| multiple-downloads | /multiple-download | Unix Socket | 多任务下载 |
| baidu_netdisk | /app-baidu-netdisk | Unix Socket | 百度网盘 |
| cloud_storage_dav | /cloud-storage | TCP 127.0.0.1:15244 | 云存储 |
3.6 飞牛互联服务
| 服务 | API 路径 | 通信方式 | 说明 |
|---|---|---|---|
| trim-connect | /trimfn | Unix Socket | 飞牛互联(远程访问) |
| trimcon | /trimcon/* | Nginx 直接处理 | 飞牛互联的 CORS 和重定向 |
四、重大发现:几乎全部 Unix Socket 通信
把上面的表统计一下:
| 通信方式 | 服务数量 | 占比 |
|---|---|---|
| Unix Socket | 25+ | ~85% |
| TCP(127.0.0.1) | 4 | ~13% |
| gRPC over Unix Socket | 1 | ~3% |
绝大多数后端服务都通过 Unix Socket 和 Nginx 通信,不是 TCP 端口。 比如:
- 相册:
unix:/var/run/trim_photos.sock - 媒体:
unix:/var/run/trim_media.sock - 分享:
unix:/var/run/trim_share.sock - 核心 CGI:
unix:/var/run/trim_http_cgi.socket
只有 4 个服务用 TCP:
- cloud_storage_dav → 127.0.0.1:15244
- docs → localhost:10500
- onlyoffice → localhost:10501
- chromium → 127.0.0.1:3000
这 4 个都是第三方组件(OnlyOffice、Chromium 等),不方便改成 Unix Socket,所以用 TCP。
为什么用 Unix Socket 而不是 TCP?
- 更安全:Unix Socket 只能本机访问,不对外暴露端口,减少攻击面
- 性能更好:Unix Socket 不经过 TCP/IP 协议栈,没有握手、序列号、校验和等开销,延迟更低
- 更简单:不需要管理端口分配,不用担心端口冲突,用文件名标识就行
这是一个非常好的架构设计——内部服务用 Unix Socket,只有需要对外暴露的才用 TCP。
五、gRPC:trim_open_gateway
在一堆 HTTP 反向代理中,有一个与众不同:
location ~ ^/(og|grpc)\. {
auth_request off;
grpc_pass grpc://unix:/var/run/trim_open_gateway.socket;
grpc_read_timeout 300s;
grpc_send_timeout 300s;
}trim_open_gateway 用的是 gRPC 协议,不是 HTTP。Nginx 用 grpc_pass 而不是 proxy_pass 来转发。
gRPC 是 Google 开源的高性能 RPC 框架,基于 HTTP/2,用 Protocol Buffers 序列化,性能比 RESTful JSON 好很多。这说明飞牛内部服务间通信可能用 gRPC,对外暴露时通过这个网关转换成 HTTP。
路径匹配 ^/(og|grpc)\.,说明 API 路径以 /og. 或 /grpc. 开头的都走 gRPC 网关。
六、全局安全访问码机制
在 safe_code_access.conf 里,有一个全局的认证机制:
auth_request /_access_code_check;
proxy_set_header X-Access-Code "";auth_request 是 Nginx 的认证请求模块——每个请求到达后端之前,先转发到 /_access_code_check 做认证,认证通过才转发到实际后端。
认证流程:
用户请求
↓
Nginx 先调用 /_access_code_check
↓
转发到 unix:/run/os-access-code.sock:/check
↓
├─ 认证通过 → 继续转发到实际后端
└─ 认证失败 → 重定向到 /_access_code_page(访问码输入页面)相关的 location:
| location | 作用 |
|---|---|
/_access_code_check | 内部认证端点,调用 os-access-code 服务的 /check |
/access_code_verify | 验证访问码 |
/_access_code_page | 访问码输入页面(内部,返回 HTML) |
/c/(code) | URL 访问码——访问 /c/xxxxxx 时自动验证访问码 |
这个机制支持多种访问码:
- 页面访问码:访问页面时弹出输入框
- URL 访问码:URL 里带
/c/xxxxxx,自动验证 - 设备访问码:通过
X-Device-ID头识别设备
对于 WebSocket 和 APP/TV 客户端,不返回 HTML 页面,而是直接返回 401:
if ($http_upgrade != "") { return 401; }
if ($http_sec_websocket_key != "") { return 401; }
if ($http_x_access_source = app) { return 401; }
if ($http_x_access_source = tv) { return 401; }这是飞牛的一个安全功能——可以给共享链接、特定页面设置访问密码,防止未授权访问。
七、WebSocket 与长连接
多个服务支持 WebSocket,用于实时推送:
| 服务 | WebSocket 路径 | 用途 |
|---|---|---|
| trim_http_cgi | /websocket、/app/ | 通用 WebSocket(系统通知等) |
| dockermgr | /docker/terminal、/docker/logs | 容器终端、容器日志(实时输出) |
| trim_seek | /seek/api/v1/ws | 搜索进度推送 |
| trim_sync_server | /sync/event/register | 同步事件推送 |
| trim_vm | /vm | 虚拟机控制台(VNC/SPICE over WebSocket) |
Docker 终端和日志的超时设为 20 分钟:
proxy_send_timeout 20m;
proxy_read_timeout 20m;同步服务的超时设为 7 天:
proxy_read_timeout 7d;
proxy_send_timeout 7d;
client_body_timeout 7d;因为文件同步可能需要很长时间,连接要保持很久。
八、前端技术栈回顾
在第三篇里我们已经分析过前端技术栈,这里快速回顾:
| 技术 | 证据 |
|---|---|
| React | lottie-react.js |
| TypeScript | tslib.es6.js |
| Semi Design | CSS 变量 --semi-color-bg-0(字节跳动组件库) |
| Rolldown | rolldown-runtime.js(新一代打包工具) |
| i18next | 国际化(多语言) |
| Lodash | 工具库 |
| Lottie | 动画 |
前端文件在 /usr/trim/www/,是打包后的静态文件。Nginx 的 root /usr/trim/www,所有未匹配到 API 的路径都返回 index.html(SPA 的 history 模式):
root /usr/trim/www;
index index.html index.htm;
error_page 404 /index.html;九、本地监听的内部服务
最后看一下只监听本地回环地址的内部服务:
$ ss -tlnp | grep 127.0.0.1
127.0.0.1:5432 ← PostgreSQL(只监听本地,安全)
127.0.0.1:7475 ← P2PClient(飞牛互联 P2P 客户端)
127.0.0.1:10000 ← baiduNas(百度网盘客户端)
127.0.0.1:10500 ← 文档服务
127.0.0.1:10501 ← OnlyOfficePostgreSQL 只监听 127.0.0.1:5432,不对外暴露,这是安全的标准做法。
十、本章小结
这一篇我们深度解析了 fnOS 的 Web 后端架构,核心发现:
- Nginx 是自编译的,还加了自研模块
ngx_http_trim_cert_module,用于动态证书管理 - 30+ 微服务架构,每个服务负责一个功能模块,通过 Nginx 反向代理统一入口
- 几乎全部 Unix Socket 通信——更安全、性能更好,只有第三方组件用 TCP
- 支持 gRPC——
trim_open_gateway用 gRPC 协议,说明内部服务间通信可能用 gRPC - 全局安全访问码机制——所有请求先经过
auth_request认证,支持页面访问码、URL 访问码 - Cookie v2→v1 转换——认证系统在升级,Nginx 层做新旧兼容
- 前端是 React + TypeScript + Semi Design + Rolldown,打包后的静态文件
这套架构的设计水平相当高——微服务解耦、Unix Socket 安全高效、统一认证、前后端分离。对于二次开发来说,只要在 /usr/trim/nginx/conf/conf.d/ 下加一个配置文件,把自己的 API 路径代理到自己的 Unix Socket,就能无缝耦合进系统。
下一篇是本系列的收官之作——系统识别方法论与二次开发指南。我们会总结出一套"拿到一台设备,5分钟判断是不是飞牛系统"的多维度识别方法(即使对方把进程名、目录名都改了也能判断),并给出基于 fnOS 做二次开发的完整路径。敬请期待。