无奈八则
长相失败, 化妆无奈。 皮黑耐晒, 口音奇怪。 腿粗缺钙, 不会做菜。 如果被爱, 纯属意外。
长相失败, 化妆无奈。 皮黑耐晒, 口音奇怪。 腿粗缺钙, 不会做菜。 如果被爱, 纯属意外。
📥下载MSCZ格式曲谱 📥下载PDF格式曲谱
个人简历 · 在线预览 新窗口打开 ↗
你理解这段代码吗? do { oldseed = seed.get(); newseed = (oldseed * ...) & mask; } while (!seed.compareAndSet(oldseed, newseed)); // ← CAS 第〇层:先搞懂"变量"在多线程里的危险 假设有一个变量 seed = 100,两个线程同时想改它: 线程A:读到 seed=100 → 算出新值 200 → 写回 seed=200 线程B:读到 seed=100 → 算出新值 300 → 写回 seed=300 问题来了——两个人都读到了 100,各算各的,最后谁写得晚谁赢。A 的结果被 B 覆盖了,A 白干了,而且程序根本不知道出错了。 这就是经典的 线程安全问题。 第一层:解决办法有两条路 路线一:悲观锁(synchronized) → "我先把门锁上,别人别进来" → 安全但慢(别人要排队) 路线二:乐观锁(CAS) → "门不锁,但我写之前验一下,被人改了我就重来" → 快但可能要重试 你这段代码走的就是 路线二。 第二层:什么是 CAS? CAS = Compare And Set(比较并设置),三个参数: CAS(内存地址, 我期望的旧值, 我想写入的新值) 它做的事用大白话说: “我记得这个值是 42,如果现在还是 42,就帮我改成 77。如果不是 42 了,说明有人动过了,啥也别干,告诉我失败了。” ...
假设配偶是外国人,女方。 女方境外人员住宿登记表 到当地派出所领取 女方护照主页复印件 (如果有)女方护照内上次居留许可复印件 男方邀请函(移民管理局照相馆可提供) 男方户口本复印件 双方结婚证 南方身份证复印件 女方印刷出来的小照片(移民管理局照相馆可提供) 提交所有内容到当地出入境移民管理局
缓存三兄弟 缓存穿透 是什么:大量请求查询数据库不存在的数据。缓存没有,持续击打数据库 防范方法: 缓存空值 数据库查不到也往缓存放一个空标记(TTL短,2分钟,该TTL过期了才能进行再次数据库查询) 下一次同样的id来了直接被挡住 优点:有效拦截大量穿透请求 缺点: 恶意攻击造成大量不同的不存在的key,缓存堆满无效数据,浪费内存 延迟了数据一致性,新数据必须等缓存过期 布隆过滤器(推荐) 启动时把所有合法id放入布隆过滤器; 布隆过滤器不给进就真的没有; 优点: 没有高内存占用风险 没有数据一致性风险 缺点: 有极小误判率 增删要维护。数据更新时,要同步更新布隆过滤器 接口层限流和校验 API网关或Controller层做拦截 参数校验、限流降级 互斥锁重建 互斥锁主要解决缓存击穿(热点key过期),但是在缓存空对象场景下,如果有大量并发请求一个不存在的key,可以使用锁 每次访问让一个线程去查DB,其他线程等待 大厂的实践 网关层 校验参数格式,IP限流(挡掉脚本攻击) 过滤器层 布隆过滤器 缓存层 缓存击穿 是什么:某个被疯狂访问的热点key,因为TTL一到,失效的一瞬间海量并发请求同时miss,同时到DB重建同一个key 防范方法: 互斥锁 只让第1个miss的线程去查DB 其他线程等一下再读缓存 高一致性:线程傻傻等待 低一致性:先给旧数据,下一次来查就是新的 逻辑过期 key永不物理过期,把过期时间存在value里面 如果发现逻辑上过期了,异步开个线程重建 当前请求先返回旧值 互斥锁的实现 如何搭建出正确的锁? v1:SETNX key 1 抢锁,DEL key 释放 SETNX=“不存在才设置成功”,天然互斥。但问题:抢到锁的线程崩了、DEL 没执行 → 锁永远不释放 → 死锁。 v2:给锁加过期间 崩了也能自动过期。但关键:必须用一条原子命令 SET key value NX EX 30。 陷阱:别写成 SETNX + 再 EXPIRE 两条——如果刚 SETNX 成功、还没 EXPIRE 就崩了,又变回 v1 的死锁。“抢锁"和"设过期"必须一步做完。 ...
基础知识 TCP 三次握手 客户端 - 服务器 三次握手目的:客户端的收发没问题,服务器的收发也没问题。 第一次握手:客户端发 SYN(同步请求) 客户端:我啥也不知道,我发个 SYN 消息出去,看看有没有人接收到。 如果没人回复,我再发几次(超时重传)。 这个时刻,客户端知道的事实是: 我发出去了,但不知道有没有人收到 ❌ 我能不能收消息?不知道 ❌ 对方存不存在?不知道 ❌ 第二次握手:服务器回 SYN+ACK(同步+确认) 服务器收到了客户端的 SYN。 服务器回复 SYN+ACK:“我收到你的消息了,我也发一条试试,看看你能不能收到。” 这个时刻,服务器知道的事实是: 客户端发消息是没有问题的 ✅(因为我收到了) 服务器收消息是没有问题的 ✅(因为我收到了) 服务器不知道服务器发消息有没有问题 ❌(我发出去了,但不知道对方收到没) 服务器不知道客户端收消息有没有问题 ❌(我发出去了,但不知道对方收到没) 服务器需要发送一条 SYN+ACK,等对方回复 ACK 来确认“我能发、对方能收” 当客户端收到 SYN+ACK 后,客户端可以确定以下事实: 我发消息是没有问题的 ✅(我发的 SYN 被收到了) 我收消息也是没有问题的 ✅(我收到了对方的回复) 服务器收消息是没有问题的 ✅(对方收到了我的 SYN) 服务器发消息也是没有问题的 ✅(我收到了对方的 SYN+ACK) ✅ 客户端这边已经确认全双工通信没问题了! 但是服务器他还有顾虑(不知道自己能不能发、不知道我能不能收),我再发个 ACK 给他吧 第三次握手:客户端发 ACK(确认) 客户端收到 SYN+ACK 后,回复一个 ACK:“我收到你的 SYN+ACK 了,我这边收发都没问题,你也可以放心了。” 当服务器收到这个 ACK 后,服务器可以确定以下事实: ...
正常 JWT 请求流程 sequenceDiagram participant User as 用户 participant Frontend as 前端(浏览器/App) participant Auth as 认证服务器 participant Backend as 后端API服务器 Note over User,Backend: 1. 登录阶段 User->>Frontend: 输入用户名/密码 Frontend->>Auth: POST /login (凭证) Auth->>Auth: 验证凭证 Auth-->>Frontend: 返回 access_token + refresh_token Frontend->>Frontend: 存储token(内存/localStorage) Frontend-->>User: 登录成功 Note over User,Backend: 2. 正常请求阶段 User->>Frontend: 请求受保护资源 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: 验证access_token签名和过期时间 Backend-->>Frontend: 返回请求的资源 Frontend-->>User: 展示数据 Note over User,Backend: 3. Access Token过期 User->>Frontend: 继续请求 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token(已过期) Backend-->>Frontend: 401 Unauthorized (token过期) Frontend->>Frontend: 检测到401,触发刷新逻辑 Note over Frontend,Auth: 4. 刷新Token阶段 Frontend->>Auth: POST /refreshrefresh_token Auth->>Auth: 验证refresh_token Auth-->>Frontend: 返回新的 access_token(可选的新refresh_token) Frontend->>Frontend: 更新存储的access_token Frontend->>Backend: 重试原请求(新access_token) Backend-->>Frontend: 返回请求的资源 Frontend-->>User: 展示数据 为什么不能只靠JWT refresh token 发出去后后端不保存,会变成 不可控的长期通行证 无法主动踢人下线 无法注销单点设备 无法判断 token 是否被盗用(攻击者拿到了 refresh token 可以一直刷新 access token) 无法实现会话管理 使用 refresh tokens 表后的流程图 sequenceDiagram participant User as 用户 participant Frontend as 前端 participant Auth as 认证服务器 participant DB as 数据库(refresh_tokens表) participant Backend as 后端API服务器 Note over User,DB: 1. 登录阶段(签发token + 入库) User->>Frontend: 输入用户名/密码 Frontend->>Auth: POST /login Auth->>Auth: 验证凭证 Auth->>DB: 生成唯一refresh_token_idINSERT INTO refresh_tokens(user_id, token_hash, expires_at, device_info, ip_address, revoked) DB-->>Auth: 插入成功 Auth->>Auth: 生成access_token + refresh_token(refresh_token包含id引用) Auth-->>Frontend: 返回access_token + refresh_token Frontend->>Frontend: 存储token Frontend-->>User: 登录成功 Note over User,Backend: 2. 正常请求(与之前相同) User->>Frontend: 请求资源 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: 验证access_token Backend-->>Frontend: 返回资源 Note over Frontend,DB: 3. Access Token过期 → 刷新 Frontend->>Backend: GET /api/resource (access_token过期) Backend-->>Frontend: 401 Unauthorized Frontend->>Auth: POST /refreshrefresh_token Note over Auth,DB: 4. 刷新验证(多步校验) Auth->>Auth: 解析refresh_token,提取token_id Auth->>DB: SELECT * FROM refresh_tokensWHERE id = token_id DB-->>Auth: 返回记录 Auth->>Auth: 校验清单: Note over Auth: ✅ token_hash是否匹配✅ 是否过期 (expires_at > now())✅ 是否被撤销 (revoked = false)✅ 用户是否仍有效✅ 设备信息是否一致(可选) alt 校验全部通过 Auth->>DB: UPDATE refresh_tokensSET last_used_at = now(), last_used_ip = current_ipWHERE id = token_id Auth->>Auth: 生成新access_token(可选:延长refresh_token有效期) Auth-->>Frontend: 返回新access_token Frontend->>Frontend: 更新access_token Frontend->>Backend: 重试原请求(新token) Backend-->>Frontend: 返回资源 else 校验失败 Auth-->>Frontend: 401/403 (刷新失败) Frontend->>Frontend: 清除所有token Frontend->>User: 跳转登录页 end Note over User,DB: 5. 主动登出 User->>Frontend: 点击登出 Frontend->>Auth: POST /logoutrefresh_token Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE id = token_id Auth-->>Frontend: 登出成功 Frontend->>Frontend: 清除本地token Frontend-->>User: 已登出 Note over User,DB: 6. 安全场景:密码修改 User->>Frontend: 修改密码 Frontend->>Auth: POST /change-password Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE user_id = current_user_id Note over DB: 撤销该用户所有refresh_token(强制所有设备重新登录) Auth-->>Frontend: 密码修改成功 Frontend->>Frontend: 清除本地token Frontend-->>User: 请重新登录
数据来源:Spring Cloud Alibaba 官方 Wiki SpringBoot 3.3.4 之后 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.1.0.0 2025.1.0 4.0.0 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.0.0.0 2025.0.0 3.5.0 组件版本关系 每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示: Spring Cloud Alibaba Version Sentinel Version Nacos Version RocketMQ Version SchedulerX Version Seata Version 2025.1.0.0 1.8.9 3.1.1 5.3.1 1.13.3 2.5.0 2025.0.0.0 1.8.9 3.0.3 5.3.1 1.13.1 2.5.0 依赖引入 <dependencyManagement> <dependencies> <!-- Spring Boot 版本统一管理 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.5.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring Cloud 官方版本管理 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2025.0.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring Cloud Alibaba 阿里生态统一版本 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2025.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> SpringBoot 3.3.4 及以前 📌 新版本(Calendar Versioning,推荐使用) Spring Cloud Alibaba Spring Cloud Spring Boot 2023.0.3.2 2023.0.3 3.3.4 2023.0.3.0 2023.0.3 3.3.4 2023.0.1.0 2023.0.1 3.2.4 2023.0.0.0-RC1 2023.0.0 3.2.0 2022.0.0.0 2022.0.0 3.0.2 2022.0.0.0-RC2 2022.0.0-RC2 3.0.2 2022.0.0.0-RC1 2022.0.0-RC1 3.0.0 2021.0.6.2 2021.0.9 2.7.18 2021.0.6.0 2021.0.9 2.7.18 2021.0.5.0 2021.0.5 2.6.13 2021.0.4.0 2021.0.4 2.6.11 2021.0.1.0 2021.0.1 2.6.3 2021.1 2020.0.1 2.4.2 📌 旧版本(RELEASE 命名) Spring Cloud Alibaba Spring Cloud Spring Boot 2.2.10.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.9.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.8.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.7.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.6.RELEASE Hoxton.SR9 2.3.2.RELEASE 2.2.1.RELEASE Hoxton.SR3 2.2.5.RELEASE 2.2.0.RELEASE Hoxton.RELEASE 2.2.X.RELEASE 2.1.4.RELEASE Greenwich.SR6 2.1.13.RELEASE 2.1.2.RELEASE Greenwich 2.1.X.RELEASE 2.0.4.RELEASE ⛔ Finchley 2.0.X.RELEASE 1.5.1.RELEASE ⛔ Edgware 1.5.X.RELEASE ⛔ 表示已停止维护 ...
技术栈:Spring Boot 3 · Spring Cloud Alibaba · OpenFeign · JWT · Gateway · Nacos 如何使用这份文档 面试讲项目,最忌讳从代码细节讲起。正确顺序是: 先讲它解决什么问题 → 再讲整体架构 → 然后按请求流程串一遍 → 最后应对深挖。 本文档按这个顺序组织。带 🎤 标记的引用框,是可以基本照着说的话术。 一、一句话概述(开场用) 🎤 我做了一套基于 Spring Cloud Alibaba 的微服务认证系统。它把「认证」这件事拆成三个角色:auth 服务负责签发令牌、网关负责统一校验令牌、各业务服务通过请求头拿到用户身份。整体用 JWT 做无状态认证,服务之间用 OpenFeign 通信,靠 Nacos 做服务发现。 关键词锚点(面试官会顺着这些追问,要准备好):无状态 JWT、网关统一鉴权、OpenFeign 远程调用、Nacos 服务发现、BCrypt 密码加密、职责分离。 二、它解决什么问题(讲动机) 背景:系统是微服务架构,有多个独立服务(auth、user-service、archive-service 等)。如果每个服务各自做一遍登录校验,会有两个问题: 重复:每个服务都写一遍鉴权逻辑,改规则要改很多处。 有状态难扩展:传统 session 存在单台服务器内存里,多实例之间不共享,扩容困难。 解决思路:「网关统一安检 + JWT 无状态令牌」。所有请求先经过网关校验令牌,业务服务不再重复鉴权;令牌本身自包含用户信息,验证只需用密钥本地验签,不依赖服务端存储。 🎤 类比机场:网关是安检口,严格查一次护照(验签);过了安检给你贴个写着身份的手环(请求头里的用户 id);后面登机口、免税店(各业务服务)只看手环,不再查护照。验签只做一次,业务服务零负担。 三、整体架构(讲骨架) 模块划分:项目是 Maven 多模块微服务,核心模块及职责如下。 模块 类型 职责 gateway 网关 所有请求入口;统一校验 JWT;按路由转发到后端服务 auth 认证服务 登录、注册;验密码;签发 JWT。自己不连数据库 user-service 业务服务 管理用户数据(tb_user 表的增删改查) archive-service 业务服务 档案业务;从请求头读取当前用户身份 api 契约模块 存放各服务的 Feign 接口声明 + 配套 DTO(被各服务依赖) common 基建底座 统一返回 Result、全局配置、ThreadLocal 用户上下文等 一个关键设计——auth 与 user-service 分离:auth 只管「认证动作」(验密码、发令牌),不碰数据库;它要用户数据时,通过 OpenFeign 远程调用 user-service 去查。user-service 只管「用户数据」,不掺和登录逻辑。 ...