Penny Lens Serverless 技术架构
2026年6月24日 · 11 分钟阅读 · ixNieStudio
基于支付宝小程序云 Serverless 的云原生后端服务,为 Penny Lens 系统提供统一的数据存储、业务逻辑处理和 API 接口服务。
Penny Lens Serverless 技术架构
🎯 产品定位
Penny Lens Serverless 是基于支付宝小程序云 Serverless 的云原生后端服务,为 Penny Lens 系统提供统一的数据存储、业务逻辑处理和 API 接口服务。通过云原生架构,提供高可用性、自动扩缩容和低成本的后端解决方案。
✨ 核心价值
1. 云原生架构
- 自动扩缩容: 根据负载自动调整资源
- 高可用性: 99.9% 的服务可用性保证
- 弹性计算: 按需分配计算资源
- 成本优化: 按使用量付费,降低成本
2. 统一后端服务
- API 统一: 为 PC 端和移动端提供统一 API
- 数据同步: 多端数据实时同步
- 业务逻辑: 统一的业务逻辑处理
- 数据安全: 企业级数据安全保护
3. 开发效率
- 快速部署: 一键部署到云端
- 自动运维: 无需手动运维管理
- 监控告警: 自动监控和告警
- 日志管理: 自动日志收集和分析
🏗️ 系统架构
Penny Lens Serverless 采用云原生架构,基于支付宝小程序云 Serverless + TypeScript + MongoDB 构建,提供高可用性、自动扩缩容和低成本的后端解决方案。
🛠️ 技术栈
核心框架
- 支付宝小程序云 - 云原生 Serverless 平台
- TypeScript - 类型安全的 JavaScript 超集
- Node.js - JavaScript 运行时环境
数据库与存储
开发工具
📁 项目结构
src/├── config/ # 配置文件│ └── index.ts # 配置入口├── controllers/ # 控制器层│ ├── UserController.ts│ ├── AssetController.ts│ ├── AccountingController.ts│ ├── BudgetController.ts│ ├── StatisticsController.ts│ ├── SubscriptionController.ts│ ├── SavingsController.ts│ └── ShortLinkController.ts├── services/ # 服务层│ ├── UserService.ts│ ├── AssetService.ts│ ├── AccountingService.ts│ ├── BudgetService.ts│ ├── StatisticsService.ts│ ├── SubscriptionService.ts│ ├── SavingsService.ts│ └── ShortLinkService.ts├── types/ # 类型定义│ ├── BaseService.ts # 基础服务类│ ├── BaseController.ts # 基础控制器类│ ├── appResponse.ts # 统一响应格式│ ├── User.ts│ ├── Asset.ts│ ├── Accounting.ts│ ├── Budget.ts│ ├── Statistics.ts│ ├── Subscription.ts│ ├── Savings.ts│ └── ShortLink.ts├── exceptions/ # 异常处理│ └── AppException.ts├── enums/ # 枚举定义│ └── HttpEnum.ts├── router.ts # 路由配置├── routes.ts # 路由定义└── index.ts # 入口文件🔧 开发规约架构
1. 基础架构层
BaseService - 基础服务类
/** * 基础服务类 * 提供通用的数据库操作和业务逻辑处理 */export abstract class BaseService { /** * 构建基础查询条件 */ protected buildBaseQueryCondition(userInfo: UserResponse): any { return { userId: userInfo.id, delFlag: false }; }
/** * 分页查询 */ protected async paginateQuery<T>( collection: any, where: any, page: number, pageSize: number, orderBy: { field: string; order: "asc" | "desc"; }[] = [{ field: "createdAt", order: "desc" }] ): Promise<Page<T>> { // 分页查询实现 }
/** * 验证记录是否存在 */ protected async validateRecordExists( collection: any, condition: any, errorMessage: string ): Promise<any> { // 记录存在性验证实现 }
/** * 验证用户访问权限 */ protected async validateUserAccess( record: any, userInfo: UserResponse, errorMessage: string ): Promise<void> { // 用户权限验证实现 }}BaseController - 基础控制器类
/** * 基础控制器类 * 提供统一的请求处理和响应格式 */export abstract class BaseController { /** * 包装异步方法,自动处理异常 */ protected wrapAsync<T>( asyncFn: () => Promise<T>, successMessage: string = "操作成功" ): Promise<AppResponse<T>> { try { const data = await asyncFn(); return { code: 200, message: successMessage, data }; } catch (error) { // 统一异常处理 return this.handleError(error); } }
/** * 统一错误处理 */ private handleError(error: unknown): AppResponse<null> { if (error instanceof AppException) { return { code: error.code, message: error.message, data: null }; }
const errorMessage = error instanceof Error ? error.message : "未知错误"; return { code: 500, message: `服务器错误: ${errorMessage}`, data: null }; }}2. 异常处理架构
/** * 应用异常基类 */export abstract class AppException extends Error { constructor( public code: number, public message: string, public data?: any ) { super(message); this.name = 'AppException'; }}
/** * 验证异常 */export class ValidationException extends AppException { constructor(message: string, data?: any) { super(400, message, data); }}
/** * 认证异常 */export class AuthenticationException extends AppException { constructor(message: string = 'Authentication failed') { super(401, message); }}
/** * 授权异常 */export class AuthorizationException extends AppException { constructor(message: string = 'Access denied') { super(403, message); }}
/** * 未找到异常 */export class NotFoundException extends AppException { constructor(message: string = 'Resource not found') { super(404, message); }}
/** * 数据库异常 */export class DatabaseException extends AppException { constructor(message: string = 'Database operation failed') { super(500, message); }}3. 路由配置架构
/** * 路由配置接口 */export interface RouteConfig { controller: any; method: string; requireAuth: boolean;}
/** * 批量构建路由配置 */export function buildRoutes( serviceName: string, actions: Array<{ action: string; requireAuth: boolean }>, controller: any): Record<string, RouteConfig> { const routes: Record<string, RouteConfig> = {};
actions.forEach(({ action, requireAuth }) => { const routeKey = `${serviceName}.${action}`; const methodName = METHOD_MAPPINGS[routeKey] || action;
routes[routeKey] = { controller, method: methodName, requireAuth }; });
return routes;}
/** * 方法映射表(特殊 action 到 service 方法名的映射) */export const METHOD_MAPPINGS: Record<string, string> = { "asset.record.queryByAssetId": "queryListByAssetId", "user.generateQrCodeLogin": "generateQrCodeLogin", "user.confirmQrCodeLogin": "confirmQrCodeLogin", "user.pollQrCodeLogin": "pollQrCodeLogin",};🔧 核心功能模块
1. 用户管理模块
功能: 用户注册、登录、信息管理、QR码登录
技术实现:
- JWT Token 认证
- 多平台登录支持(微信、支付宝)
- QR码跨设备登录
- 用户信息加密存储
- 权限控制
开发规约实现:
// Service 层export class UserService extends BaseService { public async create(params: UserCreateRequest, userInfo: UserResponse): Promise<{ id: string; }> { // 使用 buildBaseQueryCondition 构建查询条件 // 使用 validateRecordExists 验证记录存在性 // 抛出具体的业务异常 }}
// Controller 层export class UserController extends BaseController { async create(params: UserCreateRequest, userInfo: UserResponse): Promise<AppResponse<{ id: string; }>> { return this.wrapAsync( async () => { return this.userService.create(params, userInfo); }, "创建用户成功", ); }}相关文件:
controllers/UserController.ts- 用户控制器services/UserService.ts- 用户服务types/User.ts- 用户类型定义
2. 资产管理模块
功能: 资产增删改查、余额管理、转账功能
技术实现:
- 多账户类型支持
- 实时余额计算
- 资产变化记录
- 转账功能
开发规约实现:
// Service 层export class AssetService extends BaseService { public async create(params: AssetCreateRequest, userInfo: UserResponse): Promise<{ id: string; }> { // 参数验证 if (!params.name) { throw new ValidationException("资产名称不能为空"); }
// 构建基础查询条件 const baseCondition = this.buildBaseQueryCondition(userInfo);
// 检查资产是否已存在 const existingAsset = await assetCollection .where({ ...baseCondition, name: params.name, delFlag: false }) .get();
if (existingAsset.data.length > 0) { throw new ValidationException("资产名称已存在"); }
// 创建资产记录 const assetData = { ...params, userId: userInfo.id, delFlag: false, createdAt: Date.now(), updatedAt: Date.now() };
const result = await assetCollection.add(assetData); return { id: result._id }; }}相关文件:
controllers/AssetController.ts- 资产控制器services/AssetService.ts- 资产服务types/Asset.ts- 资产类型定义
3. 记账管理模块
功能: 收入、支出、转账记录管理
技术实现:
- 复式记账法
- 分类管理
- 批量操作
- 数据验证
开发规约实现:
// Service 层export class AccountingService extends BaseService { public async create(params: AccountingCreateRequest, userInfo: UserResponse): Promise<{ id: string; }> { // 使用 validateRecordExists 验证资产存在 const asset = await this.validateRecordExists( assetCollection, { _id: params.assetId, userId: userInfo.id }, "资产不存在" );
// 使用 validateUserAccess 验证用户权限 await this.validateUserAccess(asset, userInfo, "无权限操作该资产");
// 业务逻辑处理 // ... }}相关文件:
controllers/AccountingController.ts- 记账控制器services/AccountingService.ts- 记账服务types/Accounting.ts- 记账类型定义
4. 预算管理模块
功能: 预算设置、执行监控、预警提醒
技术实现:
- 分类预算设置
- 实时执行监控
- 超支预警系统
- 预算分析报告
开发规约实现:
// Service 层export class BudgetService extends BaseService { public async query(params: BudgetQueryRequest, userInfo: UserResponse): Promise<Page<Budget>> { const baseCondition = this.buildBaseQueryCondition(userInfo); const whereCondition = { ...baseCondition, ...(params.categoryId && { categoryId: params.categoryId }), ...(params.status && { status: params.status }) };
return this.paginateQuery( budgetCollection, whereCondition, params.page || 1, params.pageSize || 20, [{ field: "createdAt", order: "desc" }] ); }}相关文件:
controllers/BudgetController.ts- 预算控制器services/BudgetService.ts- 预算服务types/Budget.ts- 预算类型定义
5. 统计分析模块
功能: 收支统计、趋势分析、报表生成
技术实现:
- 多维度统计分析
- 实时数据计算
- 报表生成
- 数据导出
开发规约实现:
// Service 层export class StatisticsService extends BaseService { public async getIncomeStatistics(params: StatisticsRequest, userInfo: UserResponse): Promise<StatisticsResponse> { // 使用 buildBaseQueryCondition 构建查询条件 const baseCondition = this.buildBaseQueryCondition(userInfo);
// 复杂的统计查询逻辑 // ... }}相关文件:
controllers/StatisticsController.ts- 统计控制器services/StatisticsService.ts- 统计服务types/Statistics.ts- 统计类型定义
🔄 数据流架构
请求处理流程
用户请求 → 路由分发 → 权限验证 → 控制器处理 → 服务层业务逻辑 → 数据库操作 → 响应返回 ↓ ↓ ↓ ↓ ↓ ↓ ↓ 路由匹配 身份验证 参数验证 业务处理 数据查询 结果处理 状态返回开发规约流程:
- 路由分发: 使用
buildRoutes函数批量构建路由配置 - 权限验证: 根据
requireAuth属性进行身份验证 - 控制器处理: 使用
wrapAsync包装业务逻辑,自动处理异常 - 服务层业务逻辑: 继承
BaseService,使用工具方法进行数据库操作 - 数据库操作: 使用统一的查询条件和分页查询
- 异常处理: 使用具体的业务异常类,提供清晰的错误信息
数据同步机制
实时同步
- 用户操作: 用户操作实时同步到数据库
- 状态更新: 服务状态实时更新
- 数据一致性: 保证数据一致性
批量同步
- 定时任务: 定时同步数据
- 数据备份: 定期数据备份
- 统计分析: 定期统计分析
开发规约数据流
// 1. 路由配置export const routes: Record<string, RouteConfig> = { ...buildRoutes("user", userActions, userController), ...buildRoutes("asset", assetActions, assetController),};
// 2. 控制器处理export class UserController extends BaseController { async create(params: UserCreateRequest, userInfo: UserResponse): Promise<AppResponse<{ id: string; }>> { return this.wrapAsync( async () => { // 简单的参数验证 if (!params.username) { throw new ValidationException("用户名不能为空"); }
// 调用服务层 return this.userService.create(params, userInfo); }, "创建用户成功", ); }}
// 3. 服务层业务逻辑export class UserService extends BaseService { public async create(params: UserCreateRequest, userInfo: UserResponse): Promise<{ id: string; }> { // 构建基础查询条件 const baseCondition = this.buildBaseQueryCondition(userInfo);
// 检查用户名是否已存在 const existingUser = await userCollection .where({ ...baseCondition, username: params.username, delFlag: false }) .get();
if (existingUser.data.length > 0) { throw new ValidationException("用户名已存在"); }
// 创建用户记录 const userData = { ...params, userId: userInfo.id, delFlag: false, createdAt: Date.now(), updatedAt: Date.now() };
const result = await userCollection.add(userData); return { id: result._id }; }}🔐 安全架构
认证机制
// JWT Token 认证export class AuthService { generateToken(user: User): string { return jwt.sign( { userId: user._id, username: user.username }, process.env.JWT_SECRET!, { expiresIn: '7d' } ); }
verifyToken(token: string): any { return jwt.verify(token, process.env.JWT_SECRET!); }}权限控制
// 权限中间件export const requireAuth = (req: Request, res: Response, next: NextFunction) => { const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) { throw new AuthenticationException('Token required'); }
try { const decoded = authService.verifyToken(token); req.user = decoded; next(); } catch (error) { throw new AuthenticationException('Invalid token'); }};数据加密
// 数据加密服务export class EncryptionService { encrypt(text: string): string { const cipher = crypto.createCipher('aes-256-cbc', process.env.ENCRYPTION_KEY!); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); return encrypted; }
decrypt(encryptedText: string): string { const decipher = crypto.createDecipher('aes-256-cbc', process.env.ENCRYPTION_KEY!); let decrypted = decipher.update(encryptedText, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; }}⚡ 性能优化
数据库优化
// 数据库索引export const createIndexes = async () => { // 用户索引 await db.collection('users').createIndex({ username: 1 }, { unique: true }); await db.collection('users').createIndex({ email: 1 }, { unique: true });
// 资产索引 await db.collection('assets').createIndex({ userId: 1 }); await db.collection('assets').createIndex({ type: 1 });
// 记账记录索引 await db.collection('accounting').createIndex({ userId: 1, date: -1 }); await db.collection('accounting').createIndex({ categoryId: 1 });};缓存机制
// 缓存服务export class CacheService { private cache = new Map<string, { data: any; timestamp: number; ttl: number }>();
set(key: string, data: any, ttl: number = 300000): void { this.cache.set(key, { data, timestamp: Date.now(), ttl }); }
get(key: string): any | null { const item = this.cache.get(key); if (!item) return null;
if (Date.now() - item.timestamp > item.ttl) { this.cache.delete(key); return null; }
return item.data; }}🧪 测试策略
单元测试
// 用户服务测试describe('UserService', () => { let userService: UserService;
beforeEach(() => { userService = new UserService(); });
it('should create user successfully', async () => { const userData = { username: 'testuser', email: 'test@example.com', password: 'password123' };
const result = await userService.createUser(userData); expect(result).toBeDefined(); expect(result.username).toBe(userData.username); });});集成测试
// API 集成测试describe('User API', () => { it('should login successfully', async () => { const response = await request(app) .post('/api/user/login') .send({ username: 'testuser', password: 'password123' });
expect(response.status).toBe(200); expect(response.body.code).toBe(200); expect(response.body.data.token).toBeDefined(); });});🚀 部署架构
开发环境
- 本地开发: 本地开发环境
- 热重载: 实时代码更新
- 调试工具: 调试工具支持
- 代码检查: ESLint + TypeScript
生产环境
- 云函数部署: 自动部署到云端
- 数据库配置: 生产数据库配置
- 监控告警: 生产环境监控
- 备份恢复: 数据备份和恢复
📊 监控和运维
性能监控
- 服务监控: 服务性能监控
- 数据库监控: 数据库性能监控
- 错误监控: 错误日志监控
- 业务监控: 业务指标监控
日志管理
- 访问日志: 用户访问记录
- 错误日志: 系统错误和异常
- 业务日志: 业务操作记录
- 性能日志: 性能指标记录
🔄 持续集成
代码管理
- 版本控制: Git 版本控制
- 代码审查: Pull Request 代码审查
- 自动化测试: 单元测试、集成测试
- 代码质量: ESLint、TypeScript 检查
部署流程
- 自动化构建: CI/CD 自动化构建
- 环境管理: 开发、测试、生产环境
- 回滚机制: 快速回滚机制
- 灰度发布: 渐进式发布
📈 扩展性
功能扩展
- 模块化设计: 模块化功能设计
- 插件系统: 可扩展的插件系统
- 接口标准化: 标准化接口设计
- 版本兼容: 版本兼容性管理
技术扩展
- 微服务化: 微服务架构演进
- 容器化: 容器化部署
- 云原生: 云原生架构
- 智能化: AI 和机器学习集成
📋 开发规约总结
核心规约要点
-
Service 层规范:
- 继承
BaseService基类 - 使用
buildBaseQueryCondition构建查询条件 - 使用
paginateQuery进行分页查询 - 使用
validateRecordExists验证记录存在性 - 使用
validateUserAccess验证用户权限 - 抛出具体的业务异常类
- 继承
-
Controller 层规范:
- 继承
BaseController基类 - 使用
wrapAsync包装业务逻辑 - 不使用
public关键字 - 使用
async () => { return ... }格式 - 未使用的参数使用下划线前缀
- 继承
-
路由配置规范:
- 使用
buildRoutes函数批量构建路由 - 明确指定
requireAuth属性 - 使用
METHOD_MAPPINGS处理特殊方法映射
- 使用
-
异常处理规范:
- 使用统一的异常处理机制
- 抛出具体的业务异常类
- 提供清晰的错误信息
-
数据库操作规范:
- 统一在文件顶部定义数据库连接和集合
- 使用
cloud.database()获取数据库实例 - 集合名称使用小写复数形式
- 避免链式 where 调用
开发检查清单
在开发新功能时,请确保:
- Service 类继承
BaseService - Controller 类继承
BaseController - 使用
wrapAsync包装业务逻辑 - 不使用
public关键字 - 使用
buildBaseQueryCondition构建查询条件 - 使用
paginateQuery进行分页查询 - 使用具体的业务异常类
- 在
routes.ts中注册路由 - 遵循统一的命名规范
- 添加完整的 JSDoc 注释
🎯 目标用户
主要用户群体
-
开发者
- 需要云原生后端服务的开发者
- 需要快速部署的开发者
- 需要低成本解决方案的开发者
-
企业用户
- 需要高可用性服务的企业
- 需要自动扩缩容的企业
- 需要统一后端服务的企业
-
个人用户
- 需要数据同步的用户
- 需要多端支持的用户
- 需要数据安全的用户
Penny Lens Serverless - 让后端服务更简单、更可靠、更高效 🚀