太极 Java开发 二面
#JAVA##JAVA面经##JAVA内推#
1. JWT 无状态架构下,如何实现分布式会话的强制下线、拉黑功能?
回答思路
- 核心锚定:JWT本身无状态、无法主动撤销,需通过「外部存储+前置校验」突破无状态限制,核心逻辑是「黑名单/状态表拦截 + 短有效期兜底」;
- 分层拆解实现方案:
- 核心方案:JWT黑名单/状态表
- 存储层:Redis(高性能、支持过期)存储需强制下线的JWT token或用户ID,设置过期时间与JWT有效期一致;
- 校验流程:网关/接口层接收请求后,先校验JWT签名有效性,再查询Redis是否存在该token/用户ID,存在则拒绝请求(强制下线/拉黑);
- 触发逻辑:用户登出/被拉黑时,将token/用户ID写入Redis;
- 兜底方案:缩短JWT有效期
- JWT有效期设为15-30分钟,配合刷新token机制(refresh token),即使黑名单失效,短有效期也能快速终止非法会话;
- 进阶优化
- 按用户维度拉黑:存储用户ID而非token,避免token过多;
- 分布式缓存:Redis集群保证高可用,避免单点故障;
- 核心结论:通过Redis维护JWT/用户黑名单,网关层前置校验,配合短有效期,解决JWT无状态下的强制下线/拉黑问题。
标准答案
JWT无状态架构下实现强制下线/拉黑的核心方案:① 基于Redis构建JWT黑名单:用户登出/被拉黑时,将其JWT token(或用户ID)写入Redis(过期时间与JWT一致);② 网关/接口层前置校验:先验证JWT签名,再查询Redis是否存在该token/用户ID,存在则拒绝请求;③ 兜底优化:将JWT有效期缩短至15-30分钟,配合refresh token机制,即使黑名单失效,也能快速终止非法会话。核心是通过外部存储突破JWT无状态限制,实现主动拦截。
2. JWT 存在哪些安全风险,如何在分布式网关层做防护?
回答思路
- 核心锚定:JWT风险聚焦「签名/传输/有效期/载荷泄露」,网关层防护需覆盖「校验+限流+加密+监控」;
- 分层拆解风险与防护:
JWT安全风险 网关层防护方案 签名算法被篡改(如none算法) 网关强制指定签名算法(如HS256/RS256),拒绝none算法,校验签名有效性; token传输泄露(HTTP) 网关强制HTTPS,禁止HTTP访问,防止token被抓包; token过期时间过长 网关校验token有效期,拒绝过期token,且限制JWT有效期≤30分钟; 载荷明文泄露(如用户敏感信息) 网关禁止JWT载荷存储敏感信息(如密码),仅存用户ID等非敏感字段; token重放攻击 网关维护近期token黑名单(Redis),结合nonce随机数+时间戳,拒绝重复请求; 暴力破解签名密钥 网关对异常请求限流(如1分钟内同一IP请求>100次),监控密钥破解风险; - 核心结论:网关层从「签名校验、传输加密、有效期控制、防重放、限流」多维度防护,覆盖JWT全链路风险。
标准答案
JWT核心安全风险及网关层防护:① 签名风险:网关强制指定签名算法(如RS256),拒绝none算法,严格校验签名;② 传输风险:网关强制HTTPS,禁止HTTP暴露token;③ 重放攻击:网关结合nonce随机数+时间戳,维护近期token黑名单(Redis);④ 有效期风险:网关校验token过期时间,限制JWT有效期≤30分钟;⑤ 载荷泄露:网关禁止JWT存储敏感信息,仅保留用户ID等非敏感字段;⑥ 暴力破解:网关对异常IP/用户限流,监控密钥破解行为。
3. Docker 沙箱在高并发判题场景下,如何避免资源争抢与容器反复创建?
回答思路
- 核心锚定:高并发判题痛点是「容器创建销毁开销大+资源抢占」,解决方案围绕「容器池化+资源隔离+任务调度」;
- 分层拆解方案:
- 容器池化(核心)
- 预创建固定数量的Docker容器池(如100个),判题任务直接复用空闲容器,避免反复创建销毁;
- 容器状态管理:通过Redis/ZooKeeper维护容器「空闲/运行/异常」状态,任务调度器只分配空闲容器;
- 资源隔离与限制
- 为每个容器设置CPU/内存配额(如--cpus=0.5 --memory=512M),防止单个判题任务占满资源;
- 容器网络隔离:使用独立网络命名空间,禁止容器间通信;
- 任务调度优化
- 按任务类型(如Java/Python判题)分组容器池,避免不同类型任务争抢资源;
- 限流削峰:通过MQ缓冲高并发任务,避免容器池过载;
- 异常处理
- 容器执行异常(如死循环)时,强制销毁并重新创建,补充到容器池;
- 监控容器资源使用率,动态扩容/缩容容器池;
- 核心结论:容器池化复用避免反复创建,资源配额隔离防止争抢,任务调度削峰保证稳定性。
标准答案
高并发判题场景下Docker沙箱优化方案:① 容器池化:预创建固定数量的容器池,判题任务复用空闲容器,避免反复创建销毁;② 资源隔离:为每个容器设置CPU/内存配额(如--cpus=0.5 --memory=512M),防止单任务抢占资源;③ 任务调度:按语言类型分组容器池,通过MQ缓冲高并发任务,削峰填谷;④ 异常处理:容器异常时自动销毁重建,监控资源使用率动态扩缩容容器池。核心是「池化复用+资源隔离」,兼顾性能与稳定性。
4. 代码沙箱如何防止恶意代码攻击(如死循环、占满内存、文件读写)?
回答思路
- 核心锚定:代码沙箱防护核心是「资源限制+操作拦截+环境隔离」,从「执行、资源、文件、网络」多维度管控;
- 分层拆解防护措施:
- 执行限制(防死循环)
- 设置CPU时间限制(如1秒),超过则强制终止进程;
- 检测进程执行指令数,超过阈值则kill;
- 资源限制(防内存/CPU占满)
- 内存限制:通过cgroup/ulimit限制进程最大内存(如256M),超限制则终止;
- CPU限制:绑定CPU核心,设置CPU使用率上限(如50%);
- 文件系统限制(防读写)
- 只读挂载:沙箱内文件系统设为只读,禁止写入;
- 临时目录:仅允许写入指定临时目录,执行完立即清理;
- 系统调用拦截:通过seccomp拦截文件读写、进程创建等危险系统调用;
- 网络限制(防网络攻击)
- 禁用网络:沙箱容器/进程禁止联网,拦截socket相关系统调用;
- 环境隔离
- 独立进程/容器:每个判题任务运行在独立进程/容器,互不影响;
- 权限降级:以非root用户运行沙箱进程,降低攻击危害;
- 核心结论:通过时间/内存/CPU资源限制、系统调用拦截、环境隔离,全面阻断恶意代码的危险行为。
标准答案
代码沙箱防恶意代码攻击的核心措施:① 执行限制:设置CPU时间上限(如1秒),超过则终止进程,防止死循环;② 资源限制:通过cgroup限制进程最大内存(如256M)、CPU使用率(如50%),避免资源耗尽;③ 文件限制:沙箱文件系统只读,仅开放临时目录,通过seccomp拦截文件读写系统调用;④ 网络限制:禁用沙箱网络,拦截socket相关调用;⑤ 环境隔离:独立进程/容器运行,非root权限执行,防止攻击扩散。
5. HashMap 在 JDK 8 下为什么要引入红黑树,树化与退化的条件是什么?
回答思路
- 核心锚定:引入红黑树是为解决「链表过长导致查询性能下降」,树化/退化平衡查询与插入性能;
- 分层拆解:
- 引入红黑树的原因
- JDK 7中HashMap链表过长时,查询时间复杂度从O(1)退化为O(n);
- 红黑树查询时间复杂度为O(logn),大幅提升长链表的查询性能;
- 树化条件(两个条件同时满足)
- 链表长度 ≥ 8;
- 数组容量 ≥ 64;
- 补充:若数组容量<64,先扩容而非树化;
- 退化条件(满足其一)
- 红黑树节点数 ≤ 6;
- HashMap扩容时,重新哈希后红黑树拆分,可能退化为链表;
- 核心结论:红黑树优化长链表查询性能,树化/退化条件平衡查询与插入效率,避免过度树化增加开销。
标准答案
JDK 8 HashMap引入红黑树的核心原因:解决链表过长导致的查询性能退化(链表查询O(n)→红黑树O(logn))。树化条件:① 链表长度≥8;② 数组容量≥64(容量<64时优先扩容)。退化条件:① 红黑树节点数≤6;② HashMap扩容重新哈希后,红黑树拆分退化为链表。
6. 线程池在任务堆积、队列满、拒绝策略触发时的底层执行流程是什么?
回答思路
- 核心锚定:线程池执行流程遵循「核心线程→队列→非核心线程→拒绝策略」,需拆解每一步的触发条件和执行逻辑;
- 分层拆解执行流程:
补充细节:graph TD A[提交任务] --> B{核心线程数是否满?}; B -- 否 --> C[创建核心线程执行任务]; B -- 是 --> D{任务队列是否满?}; D -- 否 --> E[任务入队等待]; D -- 是 --> F{线程数是否达最大线程数?}; F -- 否 --> G[创建非核心线程执行任务]; F -- 是 --> H[触发拒绝策略];
- 核心线程默认不销毁(allowCoreThreadTimeOut=false),非核心线程空闲超时(keepAliveTime)后销毁;
- 拒绝策略默认AbortPolicy(抛异常),可选CallerRunsPolicy(调用者执行)、DiscardOldestPolicy(丢弃最老任务)、Disca
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏
查看18道真题和解析