Skip to content

网络优化

鸿蒙网络优化:连接复用、压缩、缓存、超时策略、并发控制。


1. 连接复用

1.1 连接池

typescript
import { rcp } from '@kit.NetworkKit'

// 使用 rcp 连接池(自动复用 TCP 连接)
let client = rcp.createClient({
    baseUri: 'https://api.example.com',
    connectionPoolSize: 10,      // 连接池大小
    keepAliveTimeout: 60000,     // 保活超时
    maxConnectionsPerHost: 5
})

// 多次请求复用同一个 TCP 连接,减少握手开销
Promise.all([
    client.request({ path: '/users' }),
    client.request({ path: '/posts' }),
    client.request({ path: '/comments' })
])

2. 请求压缩

2.1 请求压缩

typescript
// 启用 gzip 压缩
let httpClient = http.createHttp()

httpClient.request('https://api.example.com/data', {
    method: http.HttpRequestMethod.GET,
    header: {
        'Accept-Encoding': 'gzip'  // 服务端 gzip 响应
    }
}).then((response: http.HttpResponse) => {
    if (response.header.get('Content-Encoding') === 'gzip') {
        // 自动解压
        console.log('响应已解压')
    }
})

3. 请求缓存

3.1 HTTP 缓存

typescript
// HTTP 200 OK 的响应可缓存
// Cache-Control: max-age=3600 → 1 小时内使用缓存

// 手动缓存实现
class HttpResponseCache {
    private cache: Map<string, CacheEntry> = new Map()

    async request<T>(url: string, options: http.HttpRequestOptions): Promise<T> {
        let cached = this.cache.get(url)
        if (cached && Date.now() - cached.timestamp < cached.ttl) {
            console.log('使用缓存:', url)
            return cached.data as T
        }

        // 缓存未命中,发起请求
        let httpClient = http.createHttp()
        let response = await httpClient.request(url, options)
        httpClient.destroy()

        // 存入缓存
        let maxAge = response.header.get('Cache-Control')?.match(/max-age=(\d+)/)
        let ttl = maxAge ? parseInt(maxAge[1]) * 1000 : 3600000

        this.cache.set(url, {
            data: JSON.parse(response.result as string),
            timestamp: Date.now(),
            ttl: ttl
        })

        return response.result as T
    }
}

class CacheEntry {
    data: any
    timestamp: number
    ttl: number
}

4. 并发控制

4.1 请求限流

typescript
class RequestRateLimiter {
    private maxPerSecond: number = 10
    private tokens: number = this.maxPerSecond
    private lastRefill: number = Date.now()

    async acquire(): Promise<void> {
        while (true) {
            let now = Date.now()
            let elapsed = (now - this.lastRefill) / 1000
            this.tokens += elapsed * this.maxPerSecond
            if (this.tokens > this.maxPerSecond) {
                this.tokens = this.maxPerSecond
            }
            this.lastRefill = now

            if (this.tokens >= 1) {
                this.tokens--
                return
            }

            await new Promise(resolve => setTimeout(resolve, 100))
        }
    }
}

// 使用
let limiter = new RequestRateLimiter()

async function requestWithLimit(url: string): Promise<any> {
    await limiter.acquire()
    return httpClient.request(url, { method: http.HttpRequestMethod.GET })
}

5. 超时与重试

5.1 超时配置

typescript
httpClient.request('https://api.example.com/data', {
    method: http.HttpRequestMethod.GET,
    connectTimeout: 5000,  // 连接超时 5 秒
    readTimeout: 10000     // 读取超时 10 秒
})

5.2 自动重试

typescript
async function retryRequest<T>(url: string, maxRetries: number = 3): Promise<T> {
    let lastError: Error | null = null

    for (let i = 0; i < maxRetries; i++) {
        try {
            let httpClient = http.createHttp()
            let response = await httpClient.request(url, {
                method: http.HttpRequestMethod.GET,
                connectTimeout: 5000,
                readTimeout: 10000
            })
            httpClient.destroy()

            if (response.statusCode === 200) {
                return JSON.parse(response.result as string) as T
            }
            throw new Error(`HTTP ${response.statusCode}`)
        } catch (err) {
            lastError = err as Error
            if (i < maxRetries - 1) {
                await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
            }
        }
    }

    throw lastError!
}

6. 面试高频考点

Q1: 网络优化策略?

回答:连接复用(rcp 连接池)、请求压缩(gzip)、HTTP 缓存、并发限流、超时重试。

Q2: 如何防止网络抖动导致失败?

回答:超时配置 + 自动重试(指数退避)+ 连接池保活。


🐱 小猫提示:网络优化记住 "连接复用、gzip 压缩、HTTP 缓存、限流、超时重试"