You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于NodeJS的联盟链接点击追踪服务:高并发适配与优化问询

联盟链接点击追踪服务的高并发适配与优化方案

我想要创建一个联盟链接点击追踪服务,逻辑很简单:用户点击服务提供的链接时,会被重定向至原始联盟链接。我用MongoDB存储数据,需要通过请求里的offerID获取对应的原始联盟链接。我写了以下代码:

app.get('/click', async (req, res) => {

    //Tracking link : https://myservice.com/click?a=500&o=15112

    const url =req.protocol + '://' + req.get('host') + req.originalUrl
    const affiliateId = new URL(url).searchParams.get('a')
    const offerID = new URL(url).searchParams.get('o')
    //Getting affiliateID and offerID from URL

    const link = await Links.findOne({oID: offerID}) //Getting the affiliate link from the MongoDB by passing offerID
    if (link == null) return res.sendStatus(404)

    const userAgent =  navigator.userAgent //Getting the userAgent
    const clickID = shortId.generate //Generating a unique clickID
    const finalLink = link.affiliateLink.concat(`&clickID=${clickID}&sub1=${affiliateId}`) //Creating the link from the affiliates
    //Link will be like https://offer.com/clicks?affiliateoffer=500&affiliateid=1000&clickID=12151212121&sub1=500

    const click = new Click({
        affID: affiliateId,
        oID: offerID,
        clickID: clickID,
        userAgent: userAgent,
    });

    Click.save(click) // Saving the click on the database(mongodb)
    res.redirect(finalLink) //Redirecting to affiliate link
})

一、数千次并发点击下的运行情况

当前代码存在多个致命问题,直接导致高并发场景下服务无法正常运行:

  • 异步操作未正确处理:Click.save(click)未使用await,数据库保存操作会在后台异步执行,高并发下会堆积大量未完成的数据库请求,耗尽连接池资源,同时可能丢失大量点击数据。
  • 浏览器API误用:navigator.userAgent是浏览器端专属API,Node.js环境下调用会直接抛出错误,导致请求失败。
  • 函数未执行:shortId.generate仅引用了函数,未调用执行,clickID实际是函数对象而非生成的唯一ID,会导致最终跳转链接无效。
  • 无索引的数据库查询:Links.findOne({oID: offerID})中oID字段未建立索引,高并发下大量查询会触发全表扫描,拖慢数据库响应,甚至导致数据库过载。
  • 冗余的URL解析:手动拼接URL再重新解析的操作完全多余,增加了不必要的CPU开销。

如果不修复这些问题,数千次并发点击时服务会频繁报错、丢失数据,甚至直接崩溃。

二、缩短重定向时间的优化方案

1. 修复基础逻辑错误

  • 替换用户代理获取方式:const userAgent = req.get('User-Agent')
  • 正确生成唯一ID:const clickID = shortId.generate()
  • 处理数据库保存操作:要么用await click.save()确保数据入库(会增加一点延迟),要么改为异步非阻塞执行(优先重定向,后台处理数据):
    click.save().catch(err => console.error('点击数据保存失败:', err))
    

2. 数据库层优化

  • 给Links集合的oID字段创建唯一索引,将查询效率从O(n)提升至O(1):
    db.Links.createIndex({oID: 1}, {unique: true})
    
  • 调整MongoDB连接池配置,根据并发量设置合理的maxPoolSize,避免连接耗尽。

3. 减少请求阻塞

将点击数据保存改为异步非阻塞执行,不等待数据库操作完成就返回重定向响应,用户感知的跳转延迟会大幅降低,同时通过错误捕获确保异常情况可追溯。

4. 简化参数获取逻辑

直接从req.query中提取参数,省去冗余的URL拼接与解析:

const affiliateId = req.query.a;
const offerID = req.query.o;

5. 缓存热门链接

使用Redis或内存缓存(如lru-cache)存储访问频率高的offer链接,避免每次请求都查询MongoDB。缓存失效时间可根据链接更新频率灵活设置,比如设置为1小时或更久。

6. 优化链接拼接方式

使用URLSearchParams处理链接参数,避免手动拼接的错误,同时确保参数编码正确:

const urlObj = new URL(link.affiliateLink);
urlObj.searchParams.set('clickID', clickID);
urlObj.searchParams.set('sub1', affiliateId);
const finalLink = urlObj.toString();

7. 服务器与网络优化

  • 启用HTTP/2或HTTP/3协议,提升并发请求的处理效率
  • 将服务部署在靠近目标用户的区域,降低网络延迟

内容的提问来源于stack exchange,提问作者Schola LMS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:50:19