news 2026/4/16 14:13:28

Java实习模拟面试实录:微服务OJ系统架构、JWT安全机制与Redis排行榜深度解析(实在智能-Java开发-实习一面)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java实习模拟面试实录:微服务OJ系统架构、JWT安全机制与Redis排行榜深度解析(实在智能-Java开发-实习一面)

Java实习模拟面试实录:微服务OJ系统架构、JWT安全机制与Redis排行榜深度解析(实在智能-Java开发-实习一面)

关键词:Java实习面试 | 微服务OJ系统 | Docker沙箱安全 | JWT令牌管理 | Redis ZSet排行榜 | 线程池原理


引言

在准备Java后端开发实习岗位的过程中,模拟面试是查漏补缺、提升表达能力的重要环节。本文基于一次真实的“实在智能”公司Java开发实习生一面的完整问答记录,以结构化对话 + 专业解析的形式,还原面试官连环追问的逻辑,并结合专业知识给出高质量回答,帮助读者深入理解微服务、安全控制、缓存设计等核心知识点。


一、自我介绍

面试官提问

请先做个简单的自我介绍吧。

回答
您好!我是XX大学计算机专业的大三学生,目前主攻Java后端开发方向。在校期间参与过多个项目实践,其中最核心的是一个基于Spring Cloud Alibaba的微服务在线判题系统(OJ)。该项目支持多语言代码提交、Docker沙箱隔离执行、JWT鉴权、Redis实时排行榜等功能。我主要负责后端服务模块的设计与实现,包括判题服务、用户服务和排行榜模块。希望通过这次实习机会,进一步提升工程能力和对高并发、分布式系统的理解。


二、项目深挖:微服务OJ系统

Q1:介绍一下你的项目(微服务OJ系统)

回答
我们的OJ系统采用微服务架构,整体划分为以下几个核心服务:

  • 用户服务(user-service):处理注册、登录、JWT生成;
  • 题目服务(problem-service):管理题目信息、测试用例;
  • 判题服务(judge-service):核心模块,接收代码、调用Docker沙箱执行、比对输出;
  • 排行榜服务(ranking-service):基于Redis ZSet实现实时排名;
  • 网关服务(gateway):统一入口,路由与限流。

整个系统通过Nacos做服务注册发现,Sentinel做熔断降级,使用RabbitMQ解耦判题任务,保证高可用性。


Q2:Docker沙箱是每次提交代码都会创建新的吗?还是会复用?

回答
我们采用的是每次提交都创建新容器的策略。虽然启动容器有一定开销,但为了强隔离性安全性,必须确保每个用户的代码运行在完全独立的环境中,避免状态污染或恶意代码影响其他任务。

不过我们也做了优化:

  • 使用轻量级基础镜像(如Alpine);
  • 预拉取常用语言镜像(Java/Python/C++);
  • 设置容器超时自动销毁(5秒执行上限)。

这样在保证安全的前提下,尽量降低资源消耗。


Q3:判题逻辑是怎么样的?最后样例输出是直接读取Docker沙箱的输出吗?

回答
是的。判题流程如下:

  1. 用户提交完整代码(ACM模式,非力扣模板);
  2. 判题服务将代码、输入样例、时间/内存限制打包;
  3. 启动对应语言的Docker容器,挂载代码文件;
  4. 容器内执行编译 → 运行 → 重定向标准输出到指定文件;
  5. 容器退出后,宿主机读取输出文件内容;
  6. 与预期输出逐行比对(忽略末尾空格/换行差异);
  7. 返回判题结果(AC/WA/TLE/MLE等)。

注意:Docker内部不包含业务逻辑,只负责“黑盒执行”,所有判题规则都在宿主机服务中处理。


Q4:用户提交的代码里如果有恶意代码怎么办?

回答
这是安全设计的重点。我们从多个层面防御:

  1. 资源限制:通过Docker的--memory--cpusulimit限制内存、CPU、文件句柄等;
  2. 网络隔离:容器默认无网络(--network none),禁止外联;
  3. 文件系统只读:除代码挂载目录外,其余路径只读;
  4. 禁用危险系统调用:使用seccomp或AppArmor过滤syscall(如fork,execve等);
  5. 超时强制终止:超过5秒自动kill进程;
  6. 日志审计:记录所有提交行为,便于事后追溯。

即使用户写while(true)或尝试读取/etc/passwd,也会被系统拦截或超时终止。


Q5:项目支持多语言编程,是如何实现的?

回答
目前我们采用的是ACM竞赛模式,即用户提交完整可运行程序(而非函数片段)。因此,每种语言都有对应的执行脚本模板,例如:

  • Java:编译为.class,用java Main运行;
  • Python:直接python3 code.py
  • C++g++ -o a.out code.cpp && ./a.out

这些脚本预置在Docker镜像中。当用户选择语言后,判题服务会调用对应镜像,并传入用户代码。没有前端模板填充,因为不是力扣那种“补全函数”模式。

✅ 补充说明:若未来支持力扣模式,可在前端提供函数模板,后端拼接成完整程序再执行。


三、JWT安全机制深度探讨

Q6:介绍一下JWT

回答
JWT(JSON Web Token)是一种无状态的认证令牌,由三部分组成:

  • Header:算法(如HS256)和类型(JWT);
  • Payload(Claims):用户信息(如user_id、role)、过期时间(exp)等;
  • Signature:用密钥对前两部分签名,防止篡改。

优点:

  • 服务端无需存储session,适合分布式系统;
  • 可跨域传递;
  • 自包含用户信息,减少DB查询。

缺点:

  • 无法主动失效(除非引入黑名单);
  • payload明文(需避免敏感信息)。

Q7:客户端A和B同时登录同一用户,B修改了用户信息,两个JWT会冲突吗?如何解决?

回答
这是一个经典的令牌同步问题。传统JWT确实存在这个问题——因为它是无状态的,服务端无法感知用户信息是否变更。

解决方案
可以在JWT的claims中加入一个“版本号”字段,比如user_version。每次用户关键信息(如密码、权限)变更时,更新数据库中的version字段。

验证JWT时,不仅校验签名和过期时间,还要比对当前数据库中的user_version是否与token中一致。如果不一致,说明用户信息已变更,要求重新登录或刷新token。

📌 面试官提示正是这个思路:通过claims携带校验标记,实现逻辑上的“令牌失效”


四、浏览器Cookie机制澄清

Q8:浏览器中的Cookie是在什么时候触发携带、保存的?

回答(修正版):
Cookie的保存和携带是浏览器自动完成的,无需手动写JS代码(与localStorage不同)。

  • 保存:当服务器响应头包含Set-Cookie: token=xxx; Path=/; HttpOnly时,浏览器自动存储;
  • 携带:后续向相同域名+Path的请求,浏览器会自动在请求头加上Cookie: token=xxx

❗ 我最初误答成localStorage,这是错误的。LocalStorage需要手动setItem/getItem,而Cookie是HTTP协议层的自动行为。


Q9:同一浏览器中不同网站的Cookie会冲突吗?

回答
不会。Cookie的隔离基于域名(Domain)和路径(Path)

  • a.com的 Cookie 不会被b.com访问;
  • 即使是子域,如api.a.comwww.a.com,也需显式设置Domain=.a.com才能共享;
  • 浏览器通过同源策略严格隔离不同站点的Cookie。

这是Web安全的基础机制之一。


五、Redis排行榜设计详解

Q10:说说Redis一些常见命令

回答
常用命令包括:

  • 字符串:SET/GET/INCR
  • 哈希:HSET/HGET/HGETALL
  • 列表:LPUSH/RPOP/LRANGE
  • 集合:SADD/SMEMBERS/SINTER
  • 有序集合(ZSet)ZADD/ZRANK/ZREVRANGE/ZSCORE

Q11:ZSet的原理是什么?

回答
Redis的ZSet底层由两种结构实现:

  • ziplist:元素少、成员短时,用压缩列表;
  • skiplist + hash table:元素多时,用跳跃表(skiplist)维护排序哈希表维护成员到分数的映射,实现O(logN)的插入、删除、排名查询。

跳跃表是一种概率型数据结构,通过多层索引加速查找,类似“链表的二分查找”。


Q12:为什么排行榜不用List/Set/Hash,而用ZSet?

回答

  • List:无法按分数排序,只能按插入顺序;
  • Set:无序,不支持排名;
  • Hash:可存分数,但无法高效获取Top N(需全表扫描);
  • ZSet:天然支持按分数排序 + 快速范围查询 + 实时排名,完美匹配排行榜场景。

Q13:日排行榜、周排行榜如何实现?

回答
我们采用多Key策略

  • 日榜:ranking:day:20260127
  • 周榜:ranking:week:2026-W04
  • 总榜:ranking:total

每天凌晨通过定时任务(原计划用XXL-JOB,但因Bug未上线)将当日得分聚合到周榜、总榜。也可用Redis的EXPIRE自动过期日榜数据。

⚠️ 当前因任务模块出Bug,暂时由手动脚本处理,后续会修复。


Q14:排行榜数据有持久化到数据库吗?

回答
核心数据会持久化。Redis作为缓存层提供高性能读写,但为防数据丢失:

  • 用户每次得分变更时,异步写入MySQL的user_score_log表;
  • 每日凌晨将Redis中的最终排名快照存入daily_ranking表;
  • 系统重启时可从DB重建Redis ZSet。

做到缓存+持久化双保险


六、微服务架构与多线程

Q15:项目整体划分为了哪些服务?

回答
如前所述,共5个微服务:

  1. user-service(用户)
  2. problem-service(题目)
  3. judge-service(判题)
  4. ranking-service(排行榜)
  5. gateway(网关)

通过Feign调用,Nacos注册中心,配置中心统一管理。


Q16:项目用到多线程了吗?

回答
业务逻辑中未显式使用多线程,但在某些工具类中了解过TransmittableThreadLocal(TTL)。

TTL用于解决线程池中ThreadLocal变量传递问题,比如在异步任务中传递用户上下文(如traceId、userId)。普通ThreadLocal在线程复用时会丢失上下文,而TTL通过装饰Runnable/Callable实现父子线程间的数据透传。


Q17:了解线程池吗?说一下核心参数

回答
ThreadPoolExecutor的核心参数有:

  • corePoolSize:核心线程数,即使空闲也不会被回收;
  • maximumPoolSize:最大线程数;
  • keepAliveTime:非核心线程空闲超时时间;
  • workQueue:阻塞队列(如ArrayBlockingQueue、LinkedBlockingQueue);
  • threadFactory:线程工厂;
  • handler:拒绝策略(如AbortPolicy、CallerRunsPolicy)。

Q18:核心线程和非核心线程的区别?

回答

  • 核心线程:常驻线程,即使空闲也不销毁(除非allowCoreThreadTimeOut=true);
  • 非核心线程:临时线程,空闲超过keepAliveTime会被回收。

Q19:非核心线程是在阻塞队列满之后才创建的吗?

回答
是的。线程池的执行策略是:

  1. 若当前线程数 < corePoolSize → 创建核心线程
  2. 否则,尝试将任务放入workQueue
  3. 若队列已满,且当前线程数 < maximumPoolSize → 创建非核心线程
  4. 若线程数已达上限 → 触发拒绝策略

所以,非核心线程只在队列满之后才会创建


结语

这次模拟面试覆盖了微服务架构、容器安全、认证授权、缓存设计、并发编程等多个维度,既有广度也有深度。尤其在JWT令牌同步、Redis ZSet选型、线程池机制等细节上,暴露出知识盲区,也明确了后续学习方向。

💡建议:实习面试不仅考编码,更看重系统设计思维问题解决逻辑。平时多思考“为什么用这个技术?有没有更好的方案?”,才能在连环追问中游刃有余。


欢迎关注我的CSDN主页,后续将持续更新Java后端面试实战系列!
如有疑问,欢迎评论区交流~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 10:01:16

3个月,从“小白”到网络安全入门:这份清单太狠了

3 个月&#xff0c;从 “小白” 到网络安全入门&#xff1a;这份清单太狠了 别再羡慕 “黑客大神” 的技术了 —— 入门网络安全&#xff0c;真的只需要3 个月的系统学习。 最近看到一份 “逼自己坚持 3 个月” 的网络安全学习清单&#xff0c;直接把 “从 0 到能上手” 的路…

作者头像 李华
网站建设 2026/4/16 12:28:53

springboot二手物品置换平台vue

目录系统架构设计核心功能模块技术实现要点系统特色功能安全与性能优化开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统架构设计 SpringBoot作为后端框架提供RESTful API&#xff0c;Vue.js作为前端框架构建用户界面。数据…

作者头像 李华
网站建设 2026/4/16 12:25:48

收藏这份大模型全景图,从技术到应用一次学透

本文全面分析了AI大模型的定义、分类、发展历程及产业链结构。大模型分为通用、行业和垂直三类&#xff0c;产业链涵盖基础层&#xff08;算力、数据&#xff09;、模型层和应用层。全球竞争激烈&#xff0c;市场前景广阔&#xff0c;预计2028年中国市场规模达211亿元。未来竞争…

作者头像 李华
网站建设 2026/4/16 13:00:47

一天一个Python库:python-dateutil - 强大的日期时间解析与计算工具

python-dateutil - 强大的日期时间解析与计算工具 一、什么是python-dateutil&#xff1f; python-dateutil 是一个用于扩展标准库 datetime 模块的 Python 库。 它可以帮助你&#xff1a; 灵活地解析各种格式的日期时间字符串。进行复杂的日期时间计算&#xff0c;例如计算…

作者头像 李华
网站建设 2026/4/16 13:01:11

Deepoc具身模型开发板:智能采摘机器人的技术突破与产业实践

在智慧农业快速发展的背景下&#xff0c;传统农业采摘环节面临劳动力短缺、作业效率低、采摘质量不稳定等现实挑战。Deepoc具身模型开发板通过创新的技术架构和产业化路径&#xff0c;为智能采摘机器人提供了核心驱动力&#xff0c;实现了从传统人工采摘向智能化精准作业的重要…

作者头像 李华
网站建设 2026/4/16 13:02:50

VSCode 附加进程调试完整指南

目录 概述附加调试 vs 启动调试配置说明使用方法常见场景调试技巧故障排除 概述 附加进程调试&#xff08;Attach Debugging&#xff09;是一种强大的调试技术&#xff0c;允许调试器附加到已经运行的进程上&#xff0c;而不需要从调试器启动程序。这在以下场景特别有用&…

作者头像 李华