PSI进销存系统跨平台架构与性能优化
引言
PSI进销存系统基于 Node.js 构建天然具备跨平台能力,但要在不同平台上实现最佳性能和用户体验,需要进行针对性的架构设计和性能优化。本文介绍 PSI 的跨平台架构设计和性能优化实践。
跨平台架构设计
PSI 跨平台架构的核心组件:
| 组件 | 功能 | 跨平台策略 |
|---|---|---|
| 核心框架 | 业务逻辑处理 | Node.js原生兼容 |
| 数据库层 | 数据持久化 | 抽象适配层 |
| 缓存层 | 热点数据缓存 | 统一Redis接口 |
| 前端UI | 用户界面 | 响应式设计 |
跨平台兼容层实现
实现统一的跨平台兼容接口:
// 跨平台兼容层
class CrossPlatformAdapter {
constructor() {
this.platform = this.detectPlatform();
this.setPlatformSpecifics();
}
// 平台检测
detectPlatform() {
const platform = process.platform;
const arch = process.arch;
const osrelease = require('os').release();
// Windows 检测
if (platform === 'win32') {
return {
type: 'windows',
edition: this.detectWindowsEdition(),
arch: arch
};
}
// Linux 检测
if (platform === 'linux') {
const distro = this.detectLinuxDistro();
return {
type: 'linux',
distro: distro.name,
version: distro.version,
arch: arch
};
}
// macOS 检测
if (platform === 'darwin') {
return {
type: 'macos',
version: osrelease,
arch: arch
};
}
return { type: 'unknown' };
}
// 检测Windows版本
detectWindowsEdition() {
if (process.platform !== 'win32') return 'unknown';
try {
const { execSync } = require('child_process');
const result = execSync('systeminfo', { encoding: 'utf8' });
if (result.includes('Windows 11')) return 'win11';
if (result.includes('Windows 10')) return 'win10';
if (result.includes('Server')) return 'server';
} catch {}
return 'windows';
}
// 检测Linux发行版
detectLinuxDistro() {
const releaseFiles = [
'/etc/os-release',
'/etc/redhat-release',
'/etc/SuSE-release',
'/etc/debian_version'
];
for (const file of releaseFiles) {
try {
const content = require('fs').readFileSync(file, 'utf8');
if (content.includes('Kylin') || content.includes('Neokylin')) {
return { name: 'kylin', version: this.extractVersion(content) };
}
if (content.includes('UOS') || content.includes('UnionTech')) {
return { name: 'uos', version: this.extractVersion(content) };
}
if (content.includes('Ubuntu')) {
return { name: 'ubuntu', version: this.extractVersion(content) };
}
if (content.includes('CentOS')) {
return { name: 'centos', version: this.extractVersion(content) };
}
} catch {}
}
return { name: 'linux', version: 'unknown' };
}
extractVersion(content) {
const match = content.match(/(\d+\.\d+(\.\d+)?)/);
return match ? match[1] : 'unknown';
}
// 根据平台设置特定配置
setPlatformSpecifics() {
switch (this.platform.type) {
case 'windows':
this.pathSeparator = '\\';
this.lineEnding = '\r\n';
this.maxPathLength = 260;
break;
case 'linux':
case 'macos':
this.pathSeparator = '/';
this.lineEnding = '\n';
this.maxPathLength = 4096;
break;
}
}
// 路径处理
pathJoin(...segments) {
return segments.join(this.pathSeparator);
}
// 临时目录
getTempDir() {
if (this.platform.type === 'windows') {
return process.env.TEMP || process.env.TMP || 'C:\\Temp';
}
return process.env.TMPDIR || '/tmp';
}
}
// 文件操作跨平台适配
class FileAdapter {
constructor(platformAdapter) {
this.platform = platformAdapter;
}
// 安全的路径处理
safePath(filePath) {
// 规范化路径
let normalized = filePath.replace(/\\/g, '/');
// 防止路径遍历攻击
if (normalized.includes('..')) {
throw new Error('Invalid path: path traversal detected');
}
// Windows 保留字符检查
if (this.platform.platform.type === 'windows') {
const invalidChars = /[<>"|?*]/;
if (invalidChars.test(normalized)) {
throw new Error('Invalid path: contains invalid characters');
}
}
return normalized;
}
// 文件锁实现
async withLock(filePath, callback) {
const lockFile = filePath + '.lock';
// 尝试创建锁文件
const fs = require('fs').promises;
const maxRetries = 10;
let retries = 0;
while (retries < maxRetries) {
try {
await fs.writeFile(lockFile, String(process.pid));
break;
} catch (error) {
if (error.code === 'EEXIST') {
await new Promise(r => setTimeout(r, 100));
retries++;
} else {
throw error;
}
}
}
try {
return await callback();
} finally {
// 释放锁
try {
await fs.unlink(lockFile);
} catch {}
}
}
}
性能优化策略
全面的性能优化方案:
// 性能优化服务
class PerformanceOptimizer {
constructor(app) {
this.app = app;
this.metrics = {
requestTime: [],
memoryUsage: [],
cpuUsage: []
};
}
// 初始化优化中间件
initOptimizationMiddleware() {
const compression = require('compression');
const helmet = require('helmet');
return [
// 响应压缩
compression({
filter: (req, res) => {
if (req.headers['x-no-compression']) return false;
return compression.filter(req, res);
},
level: 6
}),
// 安全头
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"]
}
}
})
];
}
// 数据库查询优化
optimizeDatabaseQueries() {
return async (ctx, next) => {
const queryStart = Date.now();
const originalQuery = ctx.db.query;
// 包装查询方法,添加慢查询日志
ctx.db.query = async (sql, params) => {
const start = Date.now();
const result = await originalQuery.call(ctx.db, sql, params);
const duration = Date.now() - start;
// 记录慢查询
if (duration > 100) {
console.warn(`Slow query (${duration}ms): ${sql}`);
}
return result;
};
await next();
// 记录请求响应时间
this.metrics.requestTime.push({
path: ctx.path,
method: ctx.method,
duration: Date.now() - queryStart
});
};
}
// 缓存层实现
createCacheLayer(cacheConfig) {
const Redis = require('ioredis');
const redis = new Redis(cacheConfig);
const cache = {
async get(key) {
const data = await redis.get(key);
return data ? JSON.parse(data) : null;
},
async set(key, value, ttl = 3600) {
await redis.set(key, JSON.stringify(value), 'EX', ttl);
},
async invalidate(pattern) {
const keys = await redis.keys(pattern);
if (keys.length > 0) {
await redis.del(...keys);
}
}
};
// 缓存中间件
return async (ctx, next) => {
const cacheKey = `cache:${ctx.method}:${ctx.path}:${JSON.stringify(ctx.query)}`;
// GET 请求尝试从缓存读取
if (ctx.method === 'GET') {
const cached = await cache.get(cacheKey);
if (cached) {
ctx.set('X-Cache', 'HIT');
ctx.body = cached;
return;
}
ctx.set('X-Cache', 'MISS');
}
await next();
// 缓存响应
if (ctx.method === 'GET' && ctx.status === 200 && ctx.body) {
// 排除分页请求的缓存
if (!ctx.query.page || ctx.query.page === '1') {
await cache.set(cacheKey, ctx.body, 300); // 缓存5分钟
}
}
};
}
// 连接池优化
createDatabasePoolOptimizer(config) {
return {
// MySQL 连接池优化
mysql: {
pool: {
connections: config.maxConnections || 20,
queueLimit: config.queueLimit || 0,
waitForConnections: true,
enableKeepAlive: true,
keepAliveInitialDelay: 0
}
},
// Redis 连接池优化
redis: {
maxRetriesPerRequest: 3,
enableReadyCheck: true,
enableOfflineQueue: true,
family: 4, // IPv4
keepAlive: 30000
}
};
}
// 内存和CPU监控
startMonitoring() {
setInterval(() => {
const memUsage = process.memoryUsage();
const cpuUsage = process.cpuUsage();
this.metrics.memoryUsage.push({
rss: memUsage.rss,
heapUsed: memUsage.heapUsed,
heapTotal: memUsage.heapTotal,
timestamp: Date.now()
});
// 如果内存使用超过阈值,触发GC建议
if (memUsage.heapUsed > memUsage.heapTotal * 0.85) {
console.warn(`Memory usage high: ${(memUsage.heapUsed / memUsage.heapTotal * 100).toFixed(2)}%`);
}
}, 10000);
}
}
负载均衡配置
多实例部署的负载均衡方案:
// 会话保持配置
class SessionAffinity {
constructor(redisClient) {
this.redis = redisClient;
}
// 生成会话ID
generateSessionId() {
return `psi:${Date.now()}:${Math.random().toString(36).substr(2, 16)}`;
}
// 会话中间件
middleware() {
return async (ctx, next) => {
let sessionId = ctx.cookies.get('PSI_SESSION');
if (!sessionId) {
sessionId = this.generateSessionId();
ctx.cookies.set('PSI_SESSION', sessionId, {
httpOnly: true,
maxAge: 86400000, // 24小时
sameSite: 'lax'
});
}
// 将会话绑定到特定服务器实例
const instanceId = process.env.INSTANCE_ID || 'instance-1';
await this.redis.hset(`session:${sessionId}`, 'instance', instanceId);
ctx.sessionId = sessionId;
await next();
};
}
}
// 健康检查端点
function createHealthCheck() {
return async (ctx) => {
const health = {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
checks: {}
};
// 数据库检查
try {
await db.query('SELECT 1');
health.checks.database = 'ok';
} catch (error) {
health.checks.database = 'error';
health.status = 'degraded';
}
// Redis检查
try {
await redis.ping();
health.checks.redis = 'ok';
} catch (error) {
health.checks.redis = 'error';
health.status = 'degraded';
}
// 内存检查
const memUsage = process.memoryUsage();
if (memUsage.heapUsed / memUsage.heapTotal > 0.9) {
health.checks.memory = 'warning';
health.status = 'degraded';
} else {
health.checks.memory = 'ok';
}
ctx.status = health.status === 'ok' ? 200 : 503;
ctx.body = health;
};
}
// 优雅关闭
function setupGracefulShutdown(server) {
const shutdown = async (signal) => {
console.log(`Received ${signal}, starting graceful shutdown...`);
// 停止接受新连接
server.close(async () => {
console.log('HTTP server closed');
// 关闭数据库连接
await db.close();
console.log('Database connections closed');
// 关闭 Redis
await redis.quit();
console.log('Redis connection closed');
process.exit(0);
});
// 强制关闭超时
setTimeout(() => {
console.error('Forced shutdown after timeout');
process.exit(1);
}, 10000);
};
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
}
性能指标监控
| 指标 | 目标值 | 优化方法 |
|---|---|---|
| 响应时间 | P99 < 500ms | 缓存、数据库索引 |
| 吞吐量 | > 1000 QPS | 负载均衡、连接池 |
| CPU使用率 | < 70% | 异步处理、压缩 |
| 内存使用 | < 80% | 对象池、流处理 |
总结
PSI 进销存系统跨平台与性能优化的核心价值:
- 多平台支持:完美运行于 Windows、Linux、macOS 等主流系统
- 性能卓越:通过多层次优化实现快速响应
- 稳定可靠:完善的健康检查和优雅关闭机制
- 易于扩展:支持水平扩展和负载均衡部署
- 可观测性:全面的性能监控和告警能力
通过持续的架构优化和性能调优,PSI系统可以在各种环境下提供稳定、高效的服务体验。