javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > 前端页面并发请求解决

前端JavaScript页面大规模并发请求的解决方案详解

作者:北辰alk

本文将全面探讨前端页面面临大规模并发请求时的解决方案,涵盖从浏览器限制,请求优化到架构设计的完整技术体系,有需要的可以了解一下

1. 问题背景与挑战

1.1 什么是前端并发请求问题

在现代Web应用中,前端页面经常需要同时向服务器发送多个API请求来获取数据。当这些请求数量过多时,就会面临浏览器并发限制服务器压力过大页面响应缓慢等问题。

1.2 浏览器并发连接限制

各浏览器对同一域名的并发请求数有严格限制:

浏览器HTTP/1.1 并发数HTTP/2 并发数
Chrome6无限
Firefox6无限
Safari6无限
Edge6无限

1.3 大规模并发带来的问题

2. 技术解决方案总览

3. 浏览器层面优化方案

3.1 HTTP/2 协议的优势

HTTP/2 的多路复用特性可以显著提升并发性能:

// 检测浏览器是否支持 HTTP/2
function checkHTTP2Support() {
    const protocol = performance.getEntriesByType('navigation')[0].nextHopProtocol;
    return protocol === 'h2';
}

// 使用 HTTP/2 的优化策略
if (checkHTTP2Support()) {
    console.log('使用 HTTP/2,可以充分利用多路复用');
    // 在 HTTP/2 下可以更激进地并发请求
} else {
    console.log('使用 HTTP/1.1,需要注意并发限制');
    // 在 HTTP/1.1 下需要更谨慎地控制并发
}

3.2 域名分片技术

通过多个域名分散请求,绕过浏览器限制:

class DomainSharding {
    constructor(domains) {
        this.domains = domains;
        this.currentIndex = 0;
    }
    
    // 轮询获取域名
    getNextDomain() {
        const domain = this.domains[this.currentIndex];
        this.currentIndex = (this.currentIndex + 1) % this.domains.length;
        return domain;
    }
    
    // 使用分片域名发起请求
    async fetchWithSharding(url, options = {}) {
        const domain = this.getNextDomain();
        const shardedUrl = url.replace(/https:\/\/api\.example\.com/, domain);
        
        try {
            const response = await fetch(shardedUrl, options);
            return await response.json();
        } catch (error) {
            console.error(`Request to ${shardedUrl} failed:`, error);
            throw error;
        }
    }
}

// 使用示例
const sharding = new DomainSharding([
    'https://api1.example.com',
    'https://api2.example.com',
    'https://api3.example.com'
]);

// 并发发起多个请求
const requests = Array(10).fill(0).map((_, index) => 
    sharding.fetchWithSharding('/api/data', {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' }
    })
);

3.3 资源合并策略

// 批量请求合并工具
class BatchRequest {
    constructor(baseURL, batchDelay = 50) {
        this.baseURL = baseURL;
        this.batchDelay = batchDelay;
        this.batchQueue = [];
        this.timeoutId = null;
    }
    
    // 添加请求到批处理队列
    addRequest(endpoint, data) {
        return new Promise((resolve, reject) => {
            this.batchQueue.push({ endpoint, data, resolve, reject });
            
            if (!this.timeoutId) {
                this.timeoutId = setTimeout(() => this.processBatch(), this.batchDelay);
            }
        });
    }
    
    // 处理批处理请求
    async processBatch() {
        if (this.batchQueue.length === 0) return;
        
        const batch = this.batchQueue.splice(0, this.batchQueue.length);
        this.timeoutId = null;
        
        try {
            const response = await fetch(`${this.baseURL}/batch`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    requests: batch.map(item => ({
                        endpoint: item.endpoint,
                        data: item.data
                    }))
                })
            });
            
            const results = await response.json();
            
            // 分发结果
            batch.forEach((item, index) => {
                item.resolve(results[index]);
            });
        } catch (error) {
            // 所有请求都失败
            batch.forEach(item => {
                item.reject(error);
            });
        }
    }
}

// 使用示例
const batchRequest = new BatchRequest('https://api.example.com');

// 并发多个请求,但会被合并为单个批处理请求
const request1 = batchRequest.addRequest('/users', { id: 1 });
const request2 = batchRequest.addRequest('/products', { category: 'electronics' });
const request3 = batchRequest.addRequest('/orders', { status: 'pending' });

Promise.all([request1, request2, request3]).then(results => {
    console.log('All batch requests completed:', results);
});

4. 请求层面优化方案

4.1 智能请求队列管理系统

class RequestScheduler {
    constructor(maxConcurrent = 6, retryCount = 3) {
        this.maxConcurrent = maxConcurrent;
        this.retryCount = retryCount;
        this.activeCount = 0;
        this.queue = [];
        this.requestCache = new Map();
    }
    
    // 添加请求到队列
    async add(requestFn, priority = 0, cacheKey = null) {
        // 检查缓存
        if (cacheKey && this.requestCache.has(cacheKey)) {
            return this.requestCache.get(cacheKey);
        }
        
        return new Promise((resolve, reject) => {
            this.queue.push({
                requestFn,
                priority,
                resolve,
                reject,
                retries: 0,
                cacheKey
            });
            
            this.queue.sort((a, b) => b.priority - a.priority);
            this.processQueue();
        });
    }
    
    // 处理队列中的请求
    async processQueue() {
        if (this.activeCount >= this.maxConcurrent || this.queue.length === 0) {
            return;
        }
        
        this.activeCount++;
        const requestItem = this.queue.shift();
        
        try {
            const result = await this.executeWithRetry(requestItem);
            
            // 缓存结果
            if (requestItem.cacheKey) {
                this.requestCache.set(requestItem.cacheKey, result);
            }
            
            requestItem.resolve(result);
        } catch (error) {
            requestItem.reject(error);
        } finally {
            this.activeCount--;
            this.processQueue(); // 继续处理下一个请求
        }
    }
    
    // 带重试的执行
    async executeWithRetry(requestItem) {
        try {
            return await requestItem.requestFn();
        } catch (error) {
            if (requestItem.retries < this.retryCount && this.isRetryableError(error)) {
                requestItem.retries++;
                console.log(`Retrying request (${requestItem.retries}/${this.retryCount})`);
                return await this.executeWithRetry(requestItem);
            }
            throw error;
        }
    }
    
    // 判断错误是否可重试
    isRetryableError(error) {
        return !error.response || error.response.status >= 500;
    }
    
    // 清空队列
    clear() {
        this.queue = [];
    }
    
    // 获取队列状态
    getStatus() {
        return {
            active: this.activeCount,
            queued: this.queue.length,
            cached: this.requestCache.size
        };
    }
}

// 使用示例
const scheduler = new RequestScheduler(4); // 最大并发4个请求

// 模拟API请求函数
const createApiRequest = (endpoint, delay = 1000) => () => 
    new Promise((resolve) => 
        setTimeout(() => resolve(`Response from ${endpoint}`), delay)
    );

// 添加多个不同优先级的请求
const highPriorityRequest = scheduler.add(
    createApiRequest('/api/important', 500), 
    10, // 高优先级
    'important-data'
);

const mediumPriorityRequest = scheduler.add(
    createApiRequest('/api/normal', 1000), 
    5, // 中优先级
    'normal-data'
);

const lowPriorityRequest = scheduler.add(
    createApiRequest('/api/background', 2000), 
    1, // 低优先级
    'background-data'
);

// 监控状态
setInterval(() => {
    console.log('Scheduler status:', scheduler.getStatus());
}, 1000);

4.2 请求优先级与预加载策略

class PriorityManager {
    static PRIORITY = {
        CRITICAL: 100,    // 关键渲染数据
        HIGH: 75,         // 用户交互相关
        NORMAL: 50,       // 普通内容
        LOW: 25,          // 预加载内容
        BACKGROUND: 0     // 后台任务
    };
    
    constructor() {
        this.visibleElements = new Set();
        this.intersectionObserver = null;
        this.initIntersectionObserver();
    }
    
    // 初始化交叉观察器监控元素可见性
    initIntersectionObserver() {
        this.intersectionObserver = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                const element = entry.target;
                if (entry.isIntersecting) {
                    this.visibleElements.add(element);
                    this.updateElementPriority(element, PriorityManager.PRIORITY.HIGH);
                } else {
                    this.visibleElements.delete(element);
                    this.updateElementPriority(element, PriorityManager.PRIORITY.LOW);
                }
            });
        }, { threshold: 0.1 });
    }
    
    // 更新元素优先级
    updateElementPriority(element, priority) {
        const requests = element.querySelectorAll('[data-request]');
        requests.forEach(request => {
            request.dataset.priority = priority;
        });
    }
    
    // 观察需要优先级管理的元素
    observeElement(element) {
        this.intersectionObserver.observe(element);
    }
    
    // 根据用户行为调整优先级
    handleUserInteraction(element) {
        this.updateElementPriority(element, PriorityManager.PRIORITY.CRITICAL);
        
        // 短暂提升优先级后恢复
        setTimeout(() => {
            if (!this.visibleElements.has(element)) {
                this.updateElementPriority(element, PriorityManager.PRIORITY.NORMAL);
            }
        }, 5000);
    }
}

// 预加载管理器
class PreloadManager {
    constructor() {
        this.preloaded = new Set();
        this.linkElements = new Map();
    }
    
    // 预加载关键资源
    preloadCritical(resources) {
        resources.forEach(resource => {
            if (this.preloaded.has(resource.url)) return;
            
            const link = document.createElement('link');
            link.rel = 'preload';
            link.as = resource.type;
            link.href = resource.url;
            link.crossOrigin = 'anonymous';
            
            document.head.appendChild(link);
            this.linkElements.set(resource.url, link);
            this.preloaded.add(resource.url);
        });
    }
    
    // 预测性预加载
    predictivePreload(userBehavior) {
        const likelyResources = this.predictResources(userBehavior);
        this.preloadCritical(likelyResources);
    }
    
    // 基于用户行为预测资源
    predictResources(behavior) {
        // 简化的预测逻辑,实际项目中可以使用机器学习模型
        const predictions = {
            'viewing_products': [
                { url: '/api/recommendations', type: 'fetch' },
                { url: '/api/user-preferences', type: 'fetch' }
            ],
            'checking_out': [
                { url: '/api/shipping-options', type: 'fetch' },
                { url: '/api/payment-methods', type: 'fetch' }
            ]
        };
        
        return predictions[behavior] || [];
    }
}

4.3 请求取消与竞态处理

class CancelableRequest {
    constructor() {
        this.controllerMap = new Map();
    }
    
    // 创建可取消的请求
    async fetchWithCancel(key, url, options = {}) {
        // 取消之前的相同key的请求
        this.cancel(key);
        
        const controller = new AbortController();
        this.controllerMap.set(key, controller);
        
        try {
            const response = await fetch(url, {
                ...options,
                signal: controller.signal
            });
            
            this.controllerMap.delete(key);
            return response;
        } catch (error) {
            if (error.name === 'AbortError') {
                console.log(`Request ${key} was canceled`);
            }
            throw error;
        }
    }
    
    // 取消指定请求
    cancel(key) {
        if (this.controllerMap.has(key)) {
            this.controllerMap.get(key).abort();
            this.controllerMap.delete(key);
        }
    }
    
    // 取消所有请求
    cancelAll() {
        this.controllerMap.forEach(controller => controller.abort());
        this.controllerMap.clear();
    }
}

// 竞态处理保护
class RaceConditionProtector {
    constructor() {
        this.requestTokens = new Map();
    }
    
    // 为请求生成令牌
    generateToken(key) {
        const token = Symbol(key);
        this.requestTokens.set(key, token);
        return token;
    }
    
    // 验证令牌有效性
    isValid(key, token) {
        return this.requestTokens.get(key) === token;
    }
    
    // 执行受保护的请求
    async protectedFetch(key, url, options = {}) {
        const token = this.generateToken(key);
        
        try {
            const response = await fetch(url, options);
            
            // 检查令牌是否仍然有效
            if (!this.isValid(key, token)) {
                throw new Error('Request was superseded by newer request');
            }
            
            return response;
        } catch (error) {
            if (!this.isValid(key, token)) {
                console.log(`Request ${key} was superseded`);
            }
            throw error;
        } finally {
            this.requestTokens.delete(key);
        }
    }
}

// 使用示例
const cancelable = new CancelableRequest();
const protector = new RaceConditionProtector();

// 搜索框的防抖和取消处理
const searchInput = document.getElementById('search');
let searchTimeout;

searchInput.addEventListener('input', (e) => {
    const query = e.target.value;
    
    // 清除之前的定时器
    clearTimeout(searchTimeout);
    
    if (query.length < 2) return;
    
    // 防抖处理
    searchTimeout = setTimeout(async () => {
        try {
            const results = await protector.protectedFetch(
                'search', 
                `/api/search?q=${encodeURIComponent(query)}`
            );
            await cancelable.fetchWithCancel(
                'search',
                `/api/search?q=${encodeURIComponent(query)}`
            );
            displaySearchResults(results);
        } catch (error) {
            if (error.name !== 'AbortError') {
                console.error('Search failed:', error);
            }
        }
    }, 300);
});

5. 缓存策略优化

多层缓存系统

class MultiLevelCache {
    constructor() {
        this.memoryCache = new Map();
        this.sessionCache = new Map();
        this.localCache = new Map();
        this.cacheHierarchy = ['memory', 'session', 'local'];
    }
    
    // 设置缓存
    async set(key, value, options = {}) {
        const {
            ttl = 5 * 60 * 1000, // 默认5分钟
            level = 'memory'
        } = options;
        
        const cacheItem = {
            value,
            expiry: Date.now() + ttl,
            level
        };
        
        // 根据级别设置缓存
        switch (level) {
            case 'memory':
                this.memoryCache.set(key, cacheItem);
                break;
            case 'session':
                this.sessionCache.set(key, cacheItem);
                try {
                    sessionStorage.setItem(key, JSON.stringify(cacheItem));
                } catch (e) {
                    console.warn('Session storage full, falling back to memory');
                    this.memoryCache.set(key, cacheItem);
                }
                break;
            case 'local':
                this.localCache.set(key, cacheItem);
                try {
                    localStorage.setItem(key, JSON.stringify(cacheItem));
                } catch (e) {
                    console.warn('Local storage full, falling back to session');
                    this.sessionCache.set(key, cacheItem);
                }
                break;
        }
    }
    
    // 获取缓存
    async get(key) {
        // 按层级查找
        for (const level of this.cacheHierarchy) {
            const value = await this.getFromLevel(key, level);
            if (value !== null) {
                // 提升缓存级别
                if (level !== 'memory') {
                    this.set(key, value, { level: 'memory' });
                }
                return value;
            }
        }
        return null;
    }
    
    // 从指定级别获取缓存
    async getFromLevel(key, level) {
        try {
            let cacheItem;
            
            switch (level) {
                case 'memory':
                    cacheItem = this.memoryCache.get(key);
                    break;
                case 'session':
                    cacheItem = this.sessionCache.get(key) || 
                               JSON.parse(sessionStorage.getItem(key));
                    break;
                case 'local':
                    cacheItem = this.localCache.get(key) || 
                               JSON.parse(localStorage.getItem(key));
                    break;
            }
            
            if (cacheItem && cacheItem.expiry > Date.now()) {
                return cacheItem.value;
            } else {
                // 清理过期缓存
                this.delete(key, level);
                return null;
            }
        } catch (error) {
            console.warn(`Error reading from ${level} cache:`, error);
            return null;
        }
    }
    
    // 删除缓存
    delete(key, level = 'all') {
        if (level === 'all' || level === 'memory') {
            this.memoryCache.delete(key);
        }
        if (level === 'all' || level === 'session') {
            this.sessionCache.delete(key);
            sessionStorage.removeItem(key);
        }
        if (level === 'all' || level === 'local') {
            this.localCache.delete(key);
            localStorage.removeItem(key);
        }
    }
    
    // 清空所有缓存
    clear() {
        this.memoryCache.clear();
        this.sessionCache.clear();
        this.localCache.clear();
        sessionStorage.clear();
        localStorage.clear();
    }
}

// 智能缓存策略
class SmartCacheStrategy {
    constructor() {
        this.cache = new MultiLevelCache();
        this.patterns = new Map();
        this.initializePatterns();
    }
    
    initializePatterns() {
        // 定义缓存模式
        this.patterns.set('/api/user/', { ttl: 30 * 60 * 1000, level: 'local' });
        this.patterns.set('/api/products/', { ttl: 5 * 60 * 1000, level: 'session' });
        this.patterns.set('/api/search/', { ttl: 2 * 60 * 1000, level: 'memory' });
        this.patterns.set('/api/realtime/', { ttl: 10 * 1000, level: 'memory' });
    }
    
    // 获取URL的缓存配置
    getCacheConfig(url) {
        for (const [pattern, config] of this.patterns) {
            if (url.includes(pattern)) {
                return { ...config };
            }
        }
        return { ttl: 60 * 1000, level: 'memory' }; // 默认配置
    }
    
    // 智能缓存请求
    async cachedFetch(url, options = {}) {
        const cacheKey = this.generateCacheKey(url, options);
        const cacheConfig = this.getCacheConfig(url);
        
        // 尝试从缓存获取
        if (options.method === 'GET') {
            const cached = await this.cache.get(cacheKey);
            if (cached) {
                console.log(`Cache hit for: ${url}`);
                return cached;
            }
        }
        
        // 执行请求
        const response = await fetch(url, options);
        const data = await response.json();
        
        // 缓存响应
        if (response.ok && options.method === 'GET') {
            await this.cache.set(cacheKey, data, cacheConfig);
        }
        
        return data;
    }
    
    // 生成缓存键
    generateCacheKey(url, options) {
        const keyData = {
            url,
            method: options.method || 'GET',
            body: options.body ? await this.hashBody(options.body) : null
        };
        return btoa(JSON.stringify(keyData));
    }
    
    // 哈希请求体
    async hashBody(body) {
        const encoder = new TextEncoder();
        const data = encoder.encode(body);
        const hash = await crypto.subtle.digest('SHA-256', data);
        return Array.from(new Uint8Array(hash))
            .map(b => b.toString(16).padStart(2, '0'))
            .join('');
    }
}

6. 架构层面解决方案

6.1 微前端架构下的请求管理

// 主应用请求协调器
class MainAppRequestCoordinator {
    constructor() {
        this.microFrontends = new Map();
        this.globalScheduler = new RequestScheduler(8);
        this.sharedCache = new MultiLevelCache();
    }
    
    // 注册微前端
    registerMicroFrontend(name, config) {
        this.microFrontends.set(name, {
            ...config,
            localScheduler: new RequestScheduler(config.maxConcurrent || 2)
        });
    }
    
    // 协调请求
    async coordinateRequest(mfName, requestFn, priority = 0) {
        const mf = this.microFrontends.get(mfName);
        if (!mf) {
            throw new Error(`Micro frontend ${mfName} not registered`);
        }
        
        // 使用全局调度器进行重要请求
        if (priority > 7) {
            return await this.globalScheduler.add(requestFn, priority);
        }
        
        // 使用本地调度器进行普通请求
        return await mf.localScheduler.add(requestFn, priority);
    }
    
    // 批量协调多个微前端的请求
    async coordinateBatchRequests(requests) {
        const criticalRequests = [];
        const normalRequests = [];
        
        // 分类请求
        requests.forEach(req => {
            if (req.priority > 7) {
                criticalRequests.push(req);
            } else {
                normalRequests.push(req);
            }
        });
        
        // 并行处理
        const [criticalResults, normalResults] = await Promise.all([
            this.processCriticalRequests(criticalRequests),
            this.processNormalRequests(normalRequests)
        ]);
        
        return { ...criticalResults, ...normalResults };
    }
    
    async processCriticalRequests(requests) {
        const results = {};
        await Promise.all(
            requests.map(async req => {
                results[req.id] = await this.coordinateRequest(
                    req.mfName, 
                    req.requestFn, 
                    req.priority
                );
            })
        );
        return results;
    }
    
    async processNormalRequests(requests) {
        // 实现正常请求的处理逻辑
        const results = {};
        for (const req of requests) {
            results[req.id] = await this.coordinateRequest(
                req.mfName, 
                req.requestFn, 
                req.priority
            );
        }
        return results;
    }
}

// 微前端基类
class MicroFrontendBase {
    constructor(name, coordinator) {
        this.name = name;
        this.coordinator = coordinator;
        this.localState = new Map();
    }
    
    // 发起受控请求
    async controlledFetch(url, options = {}) {
        const requestFn = () => fetch(url, options).then(r => r.json());
        return await this.coordinator.coordinateRequest(this.name, requestFn, options.priority || 0);
    }
    
    // 预加载关键数据
    async preloadCriticalData() {
        const criticalEndpoints = this.getCriticalEndpoints();
        const requests = criticalEndpoints.map(endpoint => ({
            id: endpoint,
            mfName: this.name,
            requestFn: () => fetch(endpoint).then(r => r.json()),
            priority: 10 // 高优先级
        }));
        
        return await this.coordinator.coordinateBatchRequests(requests);
    }
    
    getCriticalEndpoints() {
        // 由具体微前端实现
        return [];
    }
}

6.2 服务端渲染与流式渲染

// 流式渲染控制器
class StreamingRenderer {
    constructor() {
        this.suspenseQueue = new Map();
        this.placeholderCache = new Map();
    }
    
    // 创建可流式渲染的组件
    createStreamableComponent(componentFn, fallback = null) {
        return async (props) => {
            const cacheKey = this.generateCacheKey(componentFn, props);
            
            // 检查是否有缓存
            if (this.placeholderCache.has(cacheKey)) {
                return this.placeholderCache.get(cacheKey);
            }
            
            // 创建占位符
            const placeholder = fallback || this.createLoadingPlaceholder();
            this.placeholderCache.set(cacheKey, placeholder);
            
            try {
                // 异步加载实际内容
                const content = await componentFn(props);
                this.placeholderCache.set(cacheKey, content);
                this.triggerRerender();
                return content;
            } catch (error) {
                const errorContent = this.createErrorPlaceholder(error);
                this.placeholderCache.set(cacheKey, errorContent);
                this.triggerRerender();
                return errorContent;
            }
        };
    }
    
    // 批量处理 suspense 组件
    async renderWithSuspense(components) {
        const promises = components.map(comp => comp.render());
        const results = await Promise.allSettled(promises);
        
        return results.map((result, index) => ({
            component: components[index],
            status: result.status,
            value: result.status === 'fulfilled' ? result.value : null,
            error: result.status === 'rejected' ? result.reason : null
        }));
    }
    
    createLoadingPlaceholder() {
        return `<div class="skeleton-loading">Loading...</div>`;
    }
    
    createErrorPlaceholder(error) {
        return `<div class="error-placeholder">Failed to load: ${error.message}</div>`;
    }
    
    generateCacheKey(componentFn, props) {
        return `${componentFn.name}-${JSON.stringify(props)}`;
    }
    
    triggerRerender() {
        // 触发重新渲染逻辑
        if (this.rerenderCallback) {
            this.rerenderCallback();
        }
    }
    
    onRerender(callback) {
        this.rerenderCallback = callback;
    }
}

7. 监控与容错机制

7.1 全面性能监控

class PerformanceMonitor {
    constructor() {
        this.metrics = new Map();
        this.thresholds = {
            requestTime: 1000,
            concurrentRequests: 10,
            errorRate: 0.1
        };
        this.setupPerformanceObserver();
    }
    
    // 设置性能观察器
    setupPerformanceObserver() {
        // 监控资源加载
        const resourceObserver = new PerformanceObserver((list) => {
            list.getEntries().forEach(entry => {
                this.recordMetric('resource_load', {
                    name: entry.name,
                    duration: entry.duration,
                    size: entry.transferSize
                });
            });
        });
        resourceObserver.observe({ entryTypes: ['resource'] });
        
        // 监控长任务
        const longTaskObserver = new PerformanceObserver((list) => {
            list.getEntries().forEach(entry => {
                if (entry.duration > 50) {
                    this.recordMetric('long_task', {
                        duration: entry.duration,
                        startTime: entry.startTime
                    });
                }
            });
        });
        longTaskObserver.observe({ entryTypes: ['longtask'] });
    }
    
    // 记录请求指标
    recordRequestMetrics(url, startTime, endTime, success = true) {
        const duration = endTime - startTime;
        
        this.recordMetric('request', {
            url,
            duration,
            success,
            timestamp: Date.now()
        });
        
        // 检查是否超过阈值
        if (duration > this.thresholds.requestTime) {
            this.recordMetric('slow_request', { url, duration });
        }
    }
    
    // 记录通用指标
    recordMetric(type, data) {
        if (!this.metrics.has(type)) {
            this.metrics.set(type, []);
        }
        this.metrics.get(type).push({
            ...data,
            timestamp: Date.now()
        });
        
        // 清理旧数据
        this.cleanupOldMetrics();
    }
    
    // 清理过期指标数据
    cleanupOldMetrics() {
        const now = Date.now();
        const maxAge = 5 * 60 * 1000; // 保留5分钟数据
        
        this.metrics.forEach((entries, type) => {
            this.metrics.set(type, entries.filter(
                entry => now - entry.timestamp < maxAge
            ));
        });
    }
    
    // 获取性能报告
    getPerformanceReport() {
        const requests = this.metrics.get('request') || [];
        const errors = this.metrics.get('request')?.filter(r => !r.success) || [];
        
        return {
            totalRequests: requests.length,
            errorRate: requests.length ? errors.length / requests.length : 0,
            averageResponseTime: requests.length ? 
                requests.reduce((sum, r) => sum + r.duration, 0) / requests.length : 0,
            slowRequests: this.metrics.get('slow_request') || [],
            currentConcurrent: this.getCurrentConcurrent()
        };
    }
    
    // 获取当前并发数
    getCurrentConcurrent() {
        // 实现并发数计算逻辑
        return 0;
    }
    
    // 检查系统健康状况
    checkHealth() {
        const report = this.getPerformanceReport();
        
        return {
            healthy: report.errorRate < this.thresholds.errorRate &&
                     report.currentConcurrent < this.thresholds.concurrentRequests,
            warnings: this.generateWarnings(report)
        };
    }
    
    generateWarnings(report) {
        const warnings = [];
        
        if (report.errorRate > this.thresholds.errorRate) {
            warnings.push('High error rate detected');
        }
        
        if (report.currentConcurrent > this.thresholds.concurrentRequests) {
            warnings.push('High concurrent request count');
        }
        
        if (report.slowRequests.length > 10) {
            warnings.push('Many slow requests detected');
        }
        
        return warnings;
    }
}

7.2 智能错误重试与降级

class IntelligentRetryStrategy {
    constructor() {
        this.retryConfigs = new Map();
        this.circuitBreakers = new Map();
        this.setupDefaultConfigs();
    }
    
    setupDefaultConfigs() {
        // 设置不同接口的重试策略
        this.retryConfigs.set('/api/payment', {
            maxRetries: 3,
            backoff: 'exponential',
            baseDelay: 1000,
            conditions: ['network_error', 'timeout', '5xx']
        });
        
        this.retryConfigs.set('/api/search', {
            maxRetries: 2,
            backoff: 'linear',
            baseDelay: 500,
            conditions: ['network_error', 'timeout']
        });
        
        this.retryConfigs.set('/api/analytics', {
            maxRetries: 1,
            backoff: 'fixed',
            baseDelay: 2000,
            conditions: ['network_error']
        });
    }
    
    // 执行带智能重试的请求
    async executeWithRetry(url, requestFn, options = {}) {
        const config = this.getRetryConfig(url);
        const circuitBreaker = this.getCircuitBreaker(url);
        
        // 检查熔断器
        if (circuitBreaker.isOpen()) {
            throw new Error(`Circuit breaker open for ${url}`);
        }
        
        let lastError;
        
        for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
            try {
                const result = await requestFn();
                circuitBreaker.recordSuccess();
                return result;
            } catch (error) {
                lastError = error;
                
                // 检查是否应该重试
                if (!this.shouldRetry(error, config, attempt)) {
                    circuitBreaker.recordFailure();
                    break;
                }
                
                // 计算延迟
                const delay = this.calculateBackoff(config, attempt);
                await this.delay(delay);
            }
        }
        
        circuitBreaker.recordFailure();
        throw lastError;
    }
    
    // 获取重试配置
    getRetryConfig(url) {
        for (const [pattern, config] of this.retryConfigs) {
            if (url.includes(pattern)) {
                return config;
            }
        }
        return {
            maxRetries: 1,
            backoff: 'fixed',
            baseDelay: 1000,
            conditions: ['network_error']
        };
    }
    
    // 判断是否应该重试
    shouldRetry(error, config, attempt) {
        if (attempt >= config.maxRetries) return false;
        
        const errorType = this.classifyError(error);
        return config.conditions.includes(errorType);
    }
    
    // 错误分类
    classifyError(error) {
        if (error.name === 'TypeError' && error.message.includes('network')) {
            return 'network_error';
        }
        if (error.name === 'TimeoutError') {
            return 'timeout';
        }
        if (error.response && error.response.status >= 500) {
            return '5xx';
        }
        if (error.response && error.response.status >= 400) {
            return '4xx';
        }
        return 'unknown';
    }
    
    // 计算退避时间
    calculateBackoff(config, attempt) {
        switch (config.backoff) {
            case 'exponential':
                return config.baseDelay * Math.pow(2, attempt);
            case 'linear':
                return config.baseDelay * (attempt + 1);
            case 'fixed':
            default:
                return config.baseDelay;
        }
    }
    
    // 获取熔断器
    getCircuitBreaker(url) {
        if (!this.circuitBreakers.has(url)) {
            this.circuitBreakers.set(url, new CircuitBreaker());
        }
        return this.circuitBreakers.get(url);
    }
    
    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

// 熔断器实现
class CircuitBreaker {
    constructor(failureThreshold = 5, resetTimeout = 60000) {
        this.failureThreshold = failureThreshold;
        this.resetTimeout = resetTimeout;
        this.failureCount = 0;
        this.lastFailureTime = null;
        this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    }
    
    isOpen() {
        if (this.state === 'OPEN') {
            // 检查是否应该尝试恢复
            if (Date.now() - this.lastFailureTime > this.resetTimeout) {
                this.state = 'HALF_OPEN';
                return false;
            }
            return true;
        }
        return false;
    }
    
    recordSuccess() {
        this.failureCount = 0;
        this.lastFailureTime = null;
        this.state = 'CLOSED';
    }
    
    recordFailure() {
        this.failureCount++;
        this.lastFailureTime = Date.now();
        
        if (this.failureCount >= this.failureThreshold) {
            this.state = 'OPEN';
        }
    }
}

8. 完整解决方案流程图

9. 实际应用示例

电商平台并发优化

class ECommerceRequestManager {
    constructor() {
        this.scheduler = new RequestScheduler(6);
        this.cache = new SmartCacheStrategy();
        this.retryStrategy = new IntelligentRetryStrategy();
        this.monitor = new PerformanceMonitor();
    }
    
    // 加载商品详情页
    async loadProductPage(productId) {
        const criticalData = await this.loadCriticalProductData(productId);
        const secondaryData = await this.loadSecondaryProductData(productId);
        
        return { ...criticalData, ...secondaryData };
    }
    
    // 加载关键数据(高优先级)
    async loadCriticalProductData(productId) {
        const requests = [
            {
                id: 'product',
                request: () => this.cache.cachedFetch(`/api/products/${productId}`),
                priority: 10
            },
            {
                id: 'price',
                request: () => this.cache.cachedFetch(`/api/prices/${productId}`),
                priority: 10
            },
            {
                id: 'inventory',
                request: () => this.cache.cachedFetch(`/api/inventory/${productId}`),
                priority: 8
            }
        ];
        
        return await this.executePriorityRequests(requests);
    }
    
    // 加载次要数据(低优先级)
    async loadSecondaryProductData(productId) {
        const requests = [
            {
                id: 'reviews',
                request: () => this.cache.cachedFetch(`/api/reviews/${productId}`),
                priority: 5
            },
            {
                id: 'recommendations',
                request: () => this.cache.cachedFetch(`/api/recommendations/${productId}`),
                priority: 4
            },
            {
                id: 'analytics',
                request: () => this.cache.cachedFetch(`/api/analytics/product/${productId}`),
                priority: 1
            }
        ];
        
        return await this.executePriorityRequests(requests);
    }
    
    // 执行优先级请求
    async executePriorityRequests(requests) {
        const results = {};
        
        // 按优先级排序
        requests.sort((a, b) => b.priority - a.priority);
        
        for (const request of requests) {
            try {
                const startTime = Date.now();
                results[request.id] = await this.scheduler.add(
                    () => this.retryStrategy.executeWithRetry(
                        request.id,
                        request.request
                    ),
                    request.priority
                );
                this.monitor.recordRequestMetrics(
                    request.id, 
                    startTime, 
                    Date.now(), 
                    true
                );
            } catch (error) {
                this.monitor.recordRequestMetrics(
                    request.id, 
                    startTime, 
                    Date.now(), 
                    false
                );
                results[request.id] = this.getFallbackData(request.id);
            }
        }
        
        return results;
    }
    
    // 获取降级数据
    getFallbackData(type) {
        const fallbacks = {
            'reviews': { averageRating: 0, reviews: [] },
            'recommendations': { products: [] },
            'analytics': { views: 0, clicks: 0 }
        };
        return fallbacks[type] || null;
    }
}

10. 总结

前端页面大规模并发请求的优化是一个系统工程,需要从多个层面综合考虑:

10.1 关键优化点总结

10.2 最佳实践建议

10.3 未来展望

随着Web技术的发展,诸如QUIC协议WebTransportService Worker等新技术将为前端并发优化提供更多可能性。持续关注新技术发展,不断优化前端性能,是提升用户体验的关键。

通过本文介绍的完整解决方案,前端开发者可以系统性地解决大规模并发请求带来的各种挑战,构建出高性能、高可用的现代Web应用。

以上就是前端JavaScript页面大规模并发请求的解决方案详解的详细内容,更多关于前端页面并发请求解决的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文