面试常问:DNS,CDN,Cookie,Session和Token详解及实战避坑指南

Q1: 什么是DNS?

一、DNS 是什么?为什么需要它?

核心定义

DNS = 分布式数据库 + 查询协议 ,用于将人类可读的域名(如 www.example.com)转换为机器可识别的 IP 地址(如 93.184.216.34)。

类比理解

ini 复制代码
🌍 互联网 = 全球电话网络
📇 DNS    = 智能电话簿 + 接线员系统
👤 你     = 客户端(浏览器/后端服务)

你想联系 "阿里巴巴客服"(域名)
→ 查电话簿(本地缓存)
→ 问小区物业(本地DNS)
→ 物业问市电信局(根/顶级域名服务器)
→ 最终拿到号码:0571-85022088(IP地址)
→ 拨号建立连接

为什么不用 IP 直接访问?

问题 DNS 的解决方案
❌ IP 难记忆 ✅ 域名人类可读
❌ 服务器迁移需改所有客户端配置 ✅ 域名不变,只改 DNS 解析记录
❌ 无法做负载均衡 ✅ 一个域名可解析到多个 IP(轮询/地域调度)
❌ 单点故障 ✅ 快速切换 DNS 记录实现故障转移

二、DNS 的层次结构(树状分布式设计)

scss 复制代码
                        . (根域名,13组根服务器)
                        |
        +---------------+---------------+
        |               |               |
      .com            .org            .cn  (顶级域名 TLD)
        |               |               |
   +----+----+     +----+----+     +----+----+
   |         |     |         |     |         |
example  google  wikipedia  alibaba  baidu  (二级域名)
   |         |     |         |     |         |
 www  api  mail  www  docs  www  shop  (子域名/主机记录)

关键角色

角色 职责 示例
根域名服务器 管理顶级域名服务器地址 a.root-servers.net
TLD 服务器 管理某顶级域下的所有域名 .com 服务器知道 example.com 的 NS 记录
权威域名服务器 存储具体域名的解析记录 ns1.alibaba.com 存储 www.alibaba.com → IP
本地 DNS 服务器 为用户递归查询,提供缓存 运营商分配的 114.114.114.114

设计精髓:分层 + 缓存 + 分布式,避免单点瓶颈,查询效率极高。

三、DNS 解析完整流程(递归 + 迭代)

假设用户在浏览器访问 y.abc.com

Q2:什么是CDN?

CDN(Content Delivery Network,内容分发网络) 是构建高性能、高可用服务时不可或缺的"加速器"。

它不仅是前端静态资源的"快递站",更是后端架构中降低源站压力、提升全球访问速度、抵御流量攻击的关键基础设施。

核心定义

CDN = 分布式边缘节点网络 + 智能调度系统,通过将内容缓存到离用户最近的节点,实现"就近访问",降低延迟、减轻源站压力。

类比理解(快递系统)

scss 复制代码
🌍 传统模式(无CDN):
用户(上海) → 互联网 → 源站服务器(北京) → 返回内容
          ⏱️ 延迟高 + 源站带宽压力大

🚀 CDN模式:
用户(上海) → 边缘节点(上海机房) → 直接返回缓存内容
          ⏱️ 延迟低 + 源站零压力(缓存命中时)

📦 缓存未命中时:
边缘节点(上海) → 回源 → 源站(北京) → 缓存到上海节点 → 返回用户
          🔄 后续上海用户都从本地节点获取

为什么后端必须了解 CDN?

问题 CDN 的解决方案 后端收益
❌ 用户访问慢(跨地域/跨国) ✅ 边缘节点就近响应 提升用户体验,降低跳出率
❌ 源站带宽被打满(突发流量) ✅ 90%+ 请求被边缘节点拦截 节省带宽成本,避免服务雪崩
❌ 静态资源占用应用服务器资源 ✅ 静态/动态分离,CDN 托管静态文件 应用服务器专注业务逻辑
❌ DDoS/CC 攻击直接打到源站 ✅ CDN 作为"盾牌"吸收攻击流量 提升系统安全性

Q3:Cookie,Session和Token之间有什么区别?

Cookie、Session 和 Token 是解决 HTTP 无状态(Stateless) 问题的三种核心方案。

核心概念速览

机制 存储位置 本质 关键特点
Cookie 客户端 (浏览器) 一段文本数据 浏览器自动携带,有大小限制 (4KB),易被篡改
Session 服务端 (内存/Redis) 服务器端的会话记录 依赖 Cookie 传 SessionID,服务器有状态,单机友好
Token (如 JWT) 客户端 (浏览器/App) 自包含的加密字符串 服务端无状态,适合分布式/移动端,需防泄露

💡 一句话总结

  • Cookie 是"存储机制"(存在哪?存在浏览器)。
  • Session 是"会话管理"(数据存在服务器,靠 Cookie 传 ID)。
  • Token 是"认证凭证"(数据存在客户端,服务端只验签名)。

详细工作流程对比

这是最经典的方案,适合单体应用。

ini 复制代码
👤 用户                 🌐 浏览器                🏢 服务端 (Session 存储)
 |                       |                          |
 | 1. 输入账号密码        |                          |
 | --------------------->|                          |
 |                       | 2. POST /login           |
 |                       | -----------------------> |
 |                       |                          | 3. 验证通过
 |                       |                          | 4. 创建 Session 数据
 |                       |                          |    (userId=1001, role=admin)
 |                       |                          | 5. 生成 SessionID=xyz123
 |                       |                          | 6. 存储 Session 到 Redis/内存
 |                       |                          |    Key: xyz123, Value: {...}
 |                       | 7. 响应 Set-Cookie:      |
 |                       |    JSESSIONID=xyz123     |
 |                       | <----------------------- |
 | 8. 浏览器保存 Cookie   |                          |
 |                       |                          |
 | 9. 访问 /profile      |                           |
 | --------------------->|                          |
 |                       | 10. 请求自动携带 Cookie  |
 |                       |     JSESSIONID=xyz123    |
 |                       | -----------------------> |
 |                       |                          | 11. 根据 ID 查 Session 数据
 |                       |                          | 12. 返回用户信息
 |                       | <----------------------- |
 | 13. 显示页面          |                          |
  • 优点:安全(敏感数据在服务端),实现简单。
  • 缺点 :服务器有状态,集群部署需解决 Session 共享 (如 Redis 集中存储)或 会话保持(Nginx ip_hash)。

2️⃣ Token 模式(如 JWT,现代 API/微服务)

这是前后端分离、移动端、微服务的主流方案。

lua 复制代码
👤 用户                 🌐 客户端                🏢 服务端 (无状态)
 |                       |                          |
 | 1. 输入账号密码        |                          |
 | --------------------->|                          |
 |                       | 2. POST /login           |
 |                       | -----------------------> |
 |                       |                          | 3. 验证通过
 |                       |                          | 4. 生成 Token (JWT)
 |                       |                          |    Header.Payload.Signature
 |                       |                          |    (包含 userId, exp, 签名)
 |                       | 5. 响应 { token: "..." } |
 |                       | <----------------------- |
 | 6. 客户端保存 Token    |                          | (不存储 Session)
 |    (LocalStorage/内存) |                          |
 |                       |                          |
 | 7. 访问 /api/profile  |                          |
 | --------------------->|                          |
 |                       | 8. 请求头携带            |
 |                       |    Authorization: Bearer |
 |                       |    <token>               |
 |                       | -----------------------> |
 |                       |                          | 9. 解析 Token
 |                       |                          | 10. 验证签名 + 有效期
 |                       |                          | 11. 提取 userId 处理业务
 |                       |                          | (无需查数据库/Redis)
 |                       | 12. 返回数据             |
 |                       | <----------------------- |
 | 13. 显示数据          |                          |
  • 优点:服务端无状态,易扩展,支持跨域,适合移动端。
  • 缺点 :Token 一旦签发,难以撤销(除非引入黑名单);Payload 不能存敏感信息(因为只是 Base64 编码,可被解码)。

常见面试坑点 & 解决方案

1. Token 被窃取了怎么办?

  • 问题:XSS 攻击拿到 Token,可冒充用户。

  • 解决

    1. HTTPS 强制加密传输。
    2. Token 存 内存 (JS 变量) 而非 LocalStorage。
    3. 短有效期 (如 15 分钟) + Refresh Token 轮换。
    4. 关键操作(支付/改密)要求二次验证

2. 分布式 Session 怎么实现?

  • 问题:用户请求打到服务器 A,Session 在 A;下次请求打到 B,B 没有 Session。

  • 解决

    1. Session 复制:A 同步给 B(流量大,不推荐)。
    2. 会话保持 :Nginx 配置 ip_hash,同一 IP 始终打到同一台(扩容/故障不友好)。
    3. Session 集中存储 (推荐):所有服务器读写 Redis Cluster

3. 如何做到 Token 的"注销"功能?

  • 问题:JWT 无状态,签发后服务端无法主动失效。

  • 解决

    1. 短效 Token:让它快点过期。
    2. 黑名单机制:用户注销时,将 Token ID (jti) 加入 Redis 黑名单,设置剩余过期时间为 TTL。网关/中间件验签时查黑名单。
    3. 版本号 :用户表加 token_version 字段,Token 里也带版本号,不一致则失效(需查库,牺牲部分无状态优势)。
  • 背景:防止 CSRF 攻击。

    • Strict:完全禁止第三方 Cookie(最安全,但影响体验)。
    • Lax:允许顶级导航请求携带(默认值,平衡安全与体验)。
    • None:允许所有第三方 Cookie(必须配合 Secure,用于跨站场景)。

Q4: 讲一下JWT Token?

JWT 是什么?

核心定义

JWT (RFC 7519) 是一种开放标准,用于在双方之间安全地传输信息作为 JSON 对象 。 核心特点:自包含 (Self-contained)无状态 (Stateless)

类比理解

scss 复制代码
🪪 Session 机制 = 小区门禁卡
• 卡上只有一个编号 (SessionID)
• 保安 (服务器) 需要查登记表 (Redis/Database) 才知道你是谁
• 缺点:每个保安室都要有同样的登记表 (集群共享麻烦)

🛂 JWT 机制 = 护照
• 护照上直接印着你的信息 (姓名、国籍、有效期) + 政府公章 (签名)
• 海关 (服务器) 只需验证公章真伪,无需查数据库
• 优点:任何海关都能验,无需联网查表
• 缺点:护照丢了很难作废 (撤销困难)

二、JWT 结构详解(核心!)

JWT 是一个长字符串,由 . 分隔成三部分:Header.Payload.Signature

复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1️⃣ Header (头部)

描述 JWT 的元数据,主要是算法类型

json 复制代码
{
  "alg": "HS256",  // 签名算法:HMAC SHA256
  "typ": "JWT"     // 令牌类型
}

⚠️ 注意 :Header 只是 Base64 编码,任何人可解码查看,不要放敏感信息。

2️⃣ Payload (负载)

存放实际数据,称为 Claims (声明)

json 复制代码
{
  "sub": "1234567890",      // 主题 (通常是用户 ID)
  "name": "John Doe",       // 用户名称
  "role": "admin",          // 用户角色
  "iat": 1516239022,        // 签发时间 (Issued At)
  "exp": 1516242622         // 过期时间 (Expiration Time) ⚠️ 关键字段
}

⚠️ 严重警告

  1. Payload 只是 Base64 编码不是加密!任何人都能解码看到内容。
  2. 严禁存放密码、手机号、银行卡号等敏感信息。
  3. 尽量精简,因为 JWT 会随每次请求发送,过大会浪费带宽。

3️⃣ Signature (签名)

防止篡改的核心。服务器用密钥 (Secret) 对 Header + Payload 进行签名。

scss 复制代码
// 伪代码
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key  // 只有服务器知道
)

作用 :客户端修改了 Payload(如把 role: user 改成 role: admin),签名就会失效,服务器验证时会拒绝。

常见面试坑点 & 排查思路

1. JWT 如何做到单点登录 (SSO)?

  • 方案:认证中心统一签发 JWT,各个子系统共享公钥(RS256 算法)验签。
  • 流程:用户登录认证中心 → 获取 JWT → 访问子系统 A → A 验签通过 → 访问子系统 B → B 验签通过。

2. Token 太大影响性能怎么办?

  • 原因:Payload 放了太多数据。

  • 解决

    1. Payload 只放 userIdrole,其他信息查库/缓存。
    2. 开启 HTTP 压缩 (Gzip/Brotli)。
    3. 考虑改用 Session(如果带宽是瓶颈)。

3. 如何排查「Token 验证失败」问题?

  1. 检查时间同步 :服务器时间不一致会导致 exp 验证失败(NTP 同步)。
  2. 检查密钥 :签发和验证的 secret 是否一致。
  3. 检查算法:签发用 HS256,验证是否误配为 RS256。
  4. 检查格式 :Header 是否带了 Bearer 前缀,是否有空格。
  5. 查看日志 :JWT 库通常会抛出具体异常(TokenExpiredError, JsonWebTokenError)。

相关推荐
Memory_荒年1 小时前
TiDB 单机部署与监控完整指南
运维·数据库·后端
张元清1 小时前
React Hooks 性能优化:如何避免不必要的重新渲染
前端·javascript·面试
犯困的饭团2 小时前
3_【自动化引擎Ansible Runner】深入功能模块 - 不止于 Playbook
后端
写Cpp的小黑黑2 小时前
WHEP 拉流技术详解(基于一个 html/js demo)
后端
GetcharZp2 小时前
告别 Selenium!这款 Go 语言神器,让网页自动化与爬虫快到飞起!
后端
天下无贼2 小时前
【Python】2026版——FastAPI 框架快速搭建后端服务
后端·python·aigc
橙序员小站2 小时前
当所有人都在做 Agent,我想聊聊被遗忘的基础设施
后端·开源·aigc
小蚂蚁i2 小时前
LangChain 完全学习手册:看完就能上手
后端·python·ai编程
Memory_荒年2 小时前
TiDB:当 MySQL 遇上分布式,生了个“超级混血儿”
java·数据库·后端