1. 内网环境下的前后端分离架构选型思考
当我们需要在内网环境中部署前后端分离应用时,技术选型往往面临诸多限制和特殊考量。Ant Design Pro + Umi Max作为前端解决方案,FastAPI作为后端框架的组合,在当前企业级应用中展现出独特的优势。
我最近在一个金融行业内部系统中采用了这套技术栈,主要基于以下几点考虑:
- 前端资源本地化:Ant Design Pro提供了完整的UI组件库和脚手架,Umi Max则内置了路由、状态管理等企业级功能,可以打包成静态资源直接部署
- Python生态适配性:FastAPI的轻量级特性和自动文档生成对内部系统开发者特别友好
- 网络隔离要求:内网环境通常无法使用CDN和公共npm源,这套组合的依赖相对可控
重要提示:在内网部署前,务必确认所有依赖都能通过内网镜像或离线包获取。我曾经在一个政府项目中因为忽略了iconfont的CDN依赖,导致部署后图标全部失效。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 离线环境下的前端工程化实践
2.1 搭建本地npm镜像仓库
在内网环境中,我们需要先建立本地的npm仓库。推荐使用verdaccio:
bash复制# 在外网机器安装verdaccio
npm install -g verdaccio
verdaccio
# 配置需要缓存的包(特别注意umi和antd相关依赖)
cat > ~/.config/verdaccio/config.yaml <<EOF
storage: ./storage
packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
proxy: npmjs
EOF
打包所有依赖时,我发现一个常见陷阱是peerDependencies的缺失。建议使用以下命令生成完整的依赖清单:
bash复制npm list --production --parseable --depth=99 | grep -oE '[^/]+$' | sort -u > dependencies.txt
2.2 Umi Max的特殊配置调整
在.umirc.ts中需要特别注意这些配置项:
typescript复制export default {
npmClient: 'cnpm', // 指向内网镜像
mfsu: false, // 内网环境下建议关闭MFSU加速
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
}
},
// 必须设置inlineLimit防止字体文件被错误处理
chainWebpack(memo) {
memo.module
.rule('media')
.test(/\.(woff|woff2|eot|ttf|otf)$/)
.use('file-loader')
.loader(require.resolve('file-loader'))
}
}
3. FastAPI后端服务的部署优化
3.1 使用uvicorn的工业级配置
虽然FastAPI开发时常用uvicorn main:app --reload,但在生产环境需要更健壮的配置:
python复制# start_server.py
import uvicorn
from fastapi import FastAPI
app = FastAPI()
if __name__ == "__main__":
uvicorn.run(
app="main:app",
host="0.0.0.0",
port=8000,
workers=4,
loop="uvloop",
http="httptools",
reload=False,
access_log=False
)
关键参数说明:
workers:建议设置为CPU核心数的2-4倍loop="uvloop":比默认asyncio循环性能提升显著http="httptools":专门优化的HTTP解析器
3.2 接口代理的精细化控制
在内部系统中,我们经常需要处理复杂的代理需求。以下是我的常用代理中间件模板:
python复制from fastapi import Request
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.middleware.gzip import GZipMiddleware
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["internal.example.com", "localhost"]
)
app.add_middleware(GZipMiddleware)
@app.middleware("http")
async def proxy_middleware(request: Request, call_next):
path = request.url.path
if path.startswith("/api/v1"):
# 添加内网特有的请求头验证
request.scope["headers"].append((b"x-internal-auth", b"secret-key"))
response = await call_next(request)
return response
4. 前后端联调的关键技巧
4.1 跨域处理的正确姿势
虽然开发时可以用--cors参数,但生产环境应该这样配置:
python复制from fastapi.middleware.cors import CORSMiddleware
origins = [
"http://localhost:8000",
"http://internal-frontend:3000"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["X-Request-ID"]
)
4.2 接口Mock的平滑过渡
在前后端分离开发中,我习惯使用Umi的mock功能与FastAPI的真实接口无缝切换:
javascript复制// mock/api.ts
import { MockMethod } from 'umi';
export default [
{
url: '/api/users',
method: 'get',
response: () => {
return {
code: 0,
data: [
{ id: 1, name: '测试用户' }
],
};
},
},
] as MockMethod[];
然后在.umirc.ts中配置:
typescript复制export default {
mock: {
exclude: ['/api/auth/']
}
}
5. 部署后的监控与维护
5.1 日志收集方案
在内网环境中,我推荐以下日志处理方式:
python复制import logging
from pathlib import Path
LOG_DIR = Path(__file__).parent / "logs"
LOG_DIR.mkdir(exist_ok=True)
logging.config.dictConfig({
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
}
},
"handlers": {
"file": {
"class": "logging.handlers.RotatingFileHandler",
"filename": LOG_DIR / "app.log",
"maxBytes": 10 * 1024 * 1024,
"backupCount": 5,
"formatter": "standard"
}
},
"loggers": {
"": {
"handlers": ["file"],
"level": "INFO"
}
}
})
5.2 性能监控配置
对于内存和CPU监控,可以使用内置的:
python复制import psutil
from fastapi import APIRouter
router = APIRouter()
@router.get("/system-status")
async def get_system_status():
return {
"cpu_percent": psutil.cpu_percent(),
"memory": psutil.virtual_memory()._asdict()
}
在前端通过定时请求展示系统状态图表,这是我在多个项目中验证过的有效方案。
6. 安全加固实践经验
6.1 接口鉴权方案
内网系统也不能忽视安全,我常用的JWT鉴权模式:
python复制from datetime import datetime, timedelta
from fastapi.security import OAuth2PasswordBearer
from jose import jwt
SECRET_KEY = "your-internal-secret"
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/token")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(hours=8)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
6.2 敏感配置管理
对于数据库密码等敏感信息,我推荐使用python-dotenv结合环境变量:
python复制from dotenv import load_dotenv
import os
load_dotenv('.env.internal') # 专门的内网配置文件
DB_CONFIG = {
'host': os.getenv('DB_HOST'),
'password': os.getenv('DB_PASSWORD')
}
.env.internal文件应该被严格限制访问权限,并在部署脚本中自动加载。
7. 实际部署中的疑难问题
7.1 静态资源缓存问题
在某个项目中,我们遇到了浏览器缓存导致更新不生效的问题。最终解决方案是在Umi构建配置中添加:
typescript复制export default {
hash: true,
manifest: {
fileName: '../../config/asset-manifest.json'
}
}
同时在Nginx配置中添加:
nginx复制location /static {
alias /path/to/static;
expires 1d;
add_header Cache-Control "public, max-age=86400";
access_log off;
}
7.2 Windows服务化部署
对于Windows服务器,可以使用NSSM将服务注册为系统服务:
batch复制nssm install FastAPIService "C:\path\to\python.exe" "C:\path\to\start_server.py"
nssm set FastAPIService AppDirectory "C:\path\to\project"
nssm start FastAPIService
这个方案在某国企项目中稳定运行了两年多,比IIS方案更轻量可靠。
8. 性能优化实战记录
8.1 前端资源加载优化
通过分析构建产物,我发现antd的图标库体积较大。优化方案:
typescript复制export default {
extraBabelPlugins: [
[
'babel-plugin-import',
{
libraryName: '@ant-design/icons',
libraryDirectory: 'es/icons',
camel2DashComponentName: false
}
]
]
}
配合按需引入图标:
typescript复制import { SearchOutlined } from '@ant-design/icons';
这一改动使构建体积减少了约40%。
8.2 数据库连接池配置
对于高频查询的接口,正确的连接池配置很关键:
python复制from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
pool_size=20,
max_overflow=10,
pool_pre_ping=True
)
AsyncSessionLocal = sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False
)
这个配置在压力测试中表现优异,连接泄漏率低于0.1%。
9. 开发到部署的全流程checklist
根据多个项目经验,我总结了一份部署检查清单:
-
依赖验证
- [ ] 所有npm包已缓存到内网仓库
- [ ] Python依赖已生成requirements.txt
- [ ] 系统级依赖(如libpq)已安装
-
配置检查
- [ ] 数据库连接字符串已更新为内网地址
- [ ] 前端API基地址配置正确
- [ ] 敏感信息已从代码中移除
-
权限验证
- [ ] 静态文件目录有读写权限
- [ ] 日志目录已创建
- [ ] 服务端口未被占用
-
监控准备
- [ ] 健康检查接口已暴露
- [ ] 日志收集配置完成
- [ ] 备份策略已制定
这套组合方案已经在三个大型内网项目中成功实施,最长的稳定运行时间超过900天。关键是要根据具体网络环境调整部署策略,特别是处理好依赖管理和接口代理这两个核心环节。
