最佳实践
优化性能、安全性和可靠性的专业建议
API密钥安全
保护您的API密钥
- 永远不要在客户端代码或公共代码库中暴露API密钥
- 使用环境变量存储API密钥
- 为不同环境(开发、测试、生产)使用不同的API密钥
- 定期轮换API密钥
- 如果密钥泄露,立即删除并创建新密钥
环境变量配置
# .env 文件
AOXSI_API_KEY=your_api_key_here
AOXSI_API_URL=https://api.aoxsi.com
# 不要将 .env 文件提交到版本控制
# 添加到 .gitignore
echo ".env" >> .gitignore服务器端代理
对于Web应用,通过服务器端代理调用API:
// 客户端调用您的服务器
fetch('/api/translate', {
method: 'POST',
body: JSON.stringify({ text: 'Hello' })
});
// 服务器端代理到Aoxsi API
app.post('/api/translate', async (req, res) => {
const response = await fetch('https://api.aoxsi.com/api/ai/translate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AOXSI_API_KEY}`
},
body: JSON.stringify(req.body)
});
res.json(await response.json());
});错误处理
实现健壮的错误处理
async function callApiWithErrorHandling(endpoint, data) {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
const error = await response.json();
// 根据错误码处理
switch (error.error.code) {
case 'E1001':
throw new Error('余额不足,请充值');
case 'E1004':
throw new Error('API密钥无效');
case 'E5001':
throw new Error('服务暂时不可用,请稍后重试');
default:
throw new Error(`API错误: ${error.error.message}`);
}
}
return await response.json();
} catch (error) {
console.error('API调用失败:', error);
throw error;
}
}重试策略
对于临时性错误,实现指数退避重试:
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
// 不重试的错误类型
if (error.code === 'E1004' || error.code === 'E1001') {
throw error;
}
if (i === maxRetries - 1) {
throw error;
}
// 指数退避: 1s, 2s, 4s
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}性能优化
缓存策略
对于重复的请求,使用缓存可以显著提高性能并降低成本:
// 使用Redis缓存
const redis = require('redis');
const client = redis.createClient();
async function translateWithCache(text, sourceLang, targetLang) {
const cacheKey = `translate:${sourceLang}:${targetLang}:${text}`;
// 尝试从缓存获取
const cached = await client.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
// 调用API
const result = await translateText(text, sourceLang, targetLang);
// 缓存结果(24小时)
await client.setex(cacheKey, 86400, JSON.stringify(result));
return result;
}批量处理
合并多个请求以减少网络开销:
// 批量翻译
async function batchTranslate(texts, sourceLang, targetLang) {
// 使用Promise.all并行处理
const results = await Promise.all(
texts.map(text =>
translateText(text, sourceLang, targetLang)
)
);
return results;
}
// 使用批处理队列
class BatchQueue {
constructor(batchSize = 10, delay = 100) {
this.queue = [];
this.batchSize = batchSize;
this.delay = delay;
}
async add(item) {
this.queue.push(item);
if (this.queue.length >= this.batchSize) {
await this.flush();
} else {
this.scheduleFlush();
}
}
scheduleFlush() {
if (this.timer) return;
this.timer = setTimeout(() => this.flush(), this.delay);
}
async flush() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
const batch = this.queue.splice(0, this.batchSize);
if (batch.length > 0) {
await this.processBatch(batch);
}
}
async processBatch(batch) {
// 处理批量请求
const results = await batchTranslate(
batch.map(item => item.text),
batch[0].sourceLang,
batch[0].targetLang
);
// 返回结果给各个请求
batch.forEach((item, index) => {
item.resolve(results[index]);
});
}
}连接池
复用HTTP连接以提高性能:
const http = require('http');
const https = require('https');
// 创建连接池
const agent = new https.Agent({
keepAlive: true,
maxSockets: 50,
maxFreeSockets: 10,
timeout: 60000
});
// 使用连接池
const response = await fetch(url, {
agent: agent,
// ... 其他选项
});速率限制管理
实现客户端速率限制
class RateLimiter {
constructor(maxRequests, timeWindow) {
this.maxRequests = maxRequests; // 最大请求数
this.timeWindow = timeWindow; // 时间窗口(毫秒)
this.requests = [];
}
async acquire() {
const now = Date.now();
// 清理过期的请求记录
this.requests = this.requests.filter(
time => now - time < this.timeWindow
);
// 检查是否超过限制
if (this.requests.length >= this.maxRequests) {
const oldestRequest = this.requests[0];
const waitTime = this.timeWindow - (now - oldestRequest);
await new Promise(resolve => setTimeout(resolve, waitTime));
return this.acquire();
}
this.requests.push(now);
}
}
// 使用示例
const limiter = new RateLimiter(60, 60000); // 每分钟60次
async function callApiWithRateLimit(data) {
await limiter.acquire();
return await callApi(data);
}监控速率限制
async function callApiWithMonitoring(data) {
const response = await fetch(url, options);
// 检查速率限制头
const limit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
console.log(`速率限制: ${remaining}/${limit}`);
// 如果接近限制,减慢请求速度
if (remaining < limit * 0.1) {
console.warn('接近速率限制,减慢请求速度');
await new Promise(resolve => setTimeout(resolve, 1000));
}
return await response.json();
}监控和日志
结构化日志
const logger = {
info: (message, meta = {}) => {
console.log(JSON.stringify({
level: 'info',
timestamp: new Date().toISOString(),
message,
...meta
}));
},
error: (message, error, meta = {}) => {
console.error(JSON.stringify({
level: 'error',
timestamp: new Date().toISOString(),
message,
error: {
message: error.message,
stack: error.stack
},
...meta
}));
}
};
// 使用示例
async function translateWithLogging(text, sourceLang, targetLang) {
const startTime = Date.now();
try {
logger.info('开始翻译', {
textLength: text.length,
sourceLang,
targetLang
});
const result = await translateText(text, sourceLang, targetLang);
logger.info('翻译成功', {
duration: Date.now() - startTime,
resultLength: result.length
});
return result;
} catch (error) {
logger.error('翻译失败', error, {
duration: Date.now() - startTime,
textLength: text.length
});
throw error;
}
}性能监控
class PerformanceMonitor {
constructor() {
this.metrics = {
totalRequests: 0,
successfulRequests: 0,
failedRequests: 0,
totalDuration: 0,
errors: {}
};
}
recordRequest(duration, success, errorCode = null) {
this.metrics.totalRequests++;
this.metrics.totalDuration += duration;
if (success) {
this.metrics.successfulRequests++;
} else {
this.metrics.failedRequests++;
this.metrics.errors[errorCode] =
(this.metrics.errors[errorCode] || 0) + 1;
}
}
getStats() {
return {
totalRequests: this.metrics.totalRequests,
successRate: this.metrics.successfulRequests /
this.metrics.totalRequests,
averageDuration: this.metrics.totalDuration /
this.metrics.totalRequests,
errors: this.metrics.errors
};
}
}
const monitor = new PerformanceMonitor();
async function monitoredApiCall(fn) {
const startTime = Date.now();
try {
const result = await fn();
monitor.recordRequest(Date.now() - startTime, true);
return result;
} catch (error) {
monitor.recordRequest(Date.now() - startTime, false, error.code);
throw error;
}
}成本优化
优化建议
- 使用缓存减少重复请求
- 批量处理多个请求
- 只请求需要的数据
- 实现请求去重
- 监控使用量,设置预算警报
- 定期审查API调用模式
请求去重
class RequestDeduplicator {
constructor() {
this.pending = new Map();
}
async deduplicate(key, fn) {
// 如果相同请求正在进行,等待结果
if (this.pending.has(key)) {
return await this.pending.get(key);
}
// 创建新请求
const promise = fn().finally(() => {
this.pending.delete(key);
});
this.pending.set(key, promise);
return await promise;
}
}
const deduplicator = new RequestDeduplicator();
async function translateWithDedup(text, sourceLang, targetLang) {
const key = `${text}:${sourceLang}:${targetLang}`;
return await deduplicator.deduplicate(
key,
() => translateText(text, sourceLang, targetLang)
);
}测试策略
单元测试
// 使用Jest进行单元测试
const { translateText } = require('./api');
// Mock API调用
jest.mock('./api', () => ({
translateText: jest.fn()
}));
describe('Translation Service', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('should translate text successfully', async () => {
translateText.mockResolvedValue('你好');
const result = await translateText('Hello', 'english', 'chinese');
expect(result).toBe('你好');
expect(translateText).toHaveBeenCalledWith('Hello', 'english', 'chinese');
});
test('should handle errors', async () => {
translateText.mockRejectedValue(new Error('API Error'));
await expect(
translateText('Hello', 'english', 'chinese')
).rejects.toThrow('API Error');
});
});集成测试
// 使用真实API进行集成测试
describe('API Integration Tests', () => {
// 使用测试环境的API密钥
const TEST_API_KEY = process.env.TEST_API_KEY;
test('should call real API successfully', async () => {
const result = await translateText(
'Hello',
'english',
'chinese'
);
expect(result).toBeTruthy();
expect(typeof result).toBe('string');
}, 10000); // 增加超时时间
});生产环境清单
在部署到生产环境之前,确保完成以下检查:
- API密钥使用环境变量存储
- 实现了错误处理和重试机制
- 配置了适当的超时时间
- 实现了速率限制管理
- 添加了日志和监控
- 使用缓存优化性能
- 设置了使用量警报
- 通过了集成测试
- 准备了故障恢复计划
- 文档化了API集成