在技术栈中构建快速的 IP 国家识别能力
一份面向工程落地的指南:如何在 Web 应用中加入国家识别、如何缓存,以及如何避免它拖慢关键链路。
# 在技术栈中构建快速的 IP 国家识别能力
国家识别不应该成为请求链路上的负担。理想情况下,它只会带来个位数毫秒级的额外耗时。下面是一些让它始终保持轻量、稳定的做法。
先正确获取客户端 IP
如果你的服务部署在 proxy 或 CDN 之后,连接上的 socket 地址通常是你自己的边缘节点,而不是真实用户。应读取基础设施实际写入的请求头,并且只信任来自自有网络的这类头部:
- Cloudflare:
CF-Connecting-IP - 大多数负载均衡器:
X-Forwarded-For中最左侧的非可信条目 - 直连:socket peer address
不要不加判断地解析 X-Forwarded-For。客户端完全可以在里面随意添加内容,盲目信任会留下伪造来源 IP 的安全缺口。
每个会话查一次,而不是每个请求都查
在创建 session 时完成解析,把国家信息和分类结果写入 session 或签名 cookie,后续直接复用即可。只有当 IP 发生变化时再重新解析。这样可以把成千上万次查询压缩成一次。
使用合理的 TTL 做缓存
同一个 /24 网段的地理位置通常在数小时内都比较稳定。以 IP 为 key,设置一小时左右的内存缓存,可以消除大部分重复流量。失败或无结果也建议缓存,只是 TTL 设短一些,避免外部服务短暂异常时引发查询风暴。
不要让页面渲染阻塞在它上面
为查询设置几百毫秒的硬超时,并准备明确的兜底逻辑:
ts const geo = await Promise.race([ lookup(ip), timeout(300).then(() => null), ]); const country = geo?.country ?? defaultCountry;
页面展示了不完全匹配的货币,顶多是一次小小的体验偏差;页面完全打不开,则可能直接损失收入。
能在边缘做,就尽量在边缘做
如果你的应用运行在 edge runtime 上,查询会发生在更靠近用户的位置,新增延迟通常可以忽略不计。可以在边缘侧完成解析,把结果挂到请求上下文中,让业务应用像读取普通数据一样使用。
保留决策结果,丢弃原始数据
建议存储业务真正关心的结果,例如展示了哪种货币、命中了哪条规则,而不是保存完整的原始地理位置记录。这样成本更低,也更容易向隐私审核人员解释;更重要的是,后续真正会被查询和使用的,往往也只是这些决策结果。
