公司一面试题
公司一面试题
AI相关
第一:面试题:在智能销售数据分析 Agent项目中,Agent 通过 ReAct循环自主编排调用路径,这个 ReAct循环它是怎么循环的,流程是什么样的?
ReAct核心是一个「思考 → 行动 → 观察 → 再思考」的迭代循环。每轮中,Agent 先由大模型进行 Thought 思考,基于当前已知信息推理下一步该做什么、调用哪个工具;接着执行 Action 行动,把决策转成一次具体工具调用,比如销售分析场景里的 SQL 查询、维度聚合、下钻分析;然后进入 Observation 观察,把工具返回的结果拼回上下文,作为下一轮推理的输入。一轮结束后,模型判断信息是否足以回答用户:不足就回到 Thought 进入下一轮,循环因此得名;充分就输出最终答案,终止条件通常是信息充分、或达到最大轮数上限。
第二:讲一讲你对RAG的理解
RAG 就是检索增强生成,核心是在大模型回答前先从外部知识库检索相关内容,作为上下文注入 Prompt,让模型基于事实生成回答,本质是用"外挂知识库"替代"参数记忆"。流程分两阶段:离线把文档分块、向量化存入向量库;在线把用户问题向量化后做相似度检索取 Top-K,拼进上下文交给 LLM 生成。这样解决了大模型幻觉、知识时效性和领域知识不足三大痛点,且回答可溯源到原文。
第三:可以讲一讲RAG的运行流程吗?
RAG(检索增强生成)的运行流程分为离线知识构建和在线检索生成两个阶段。离线阶段:首先将各类文档加载后进行文本切分,按固定长度或语义边界把长文档拆分成适当大小的文本块;然后用 Embedding 模型将每个文本块向量化,连同原始文本和元数据一起存入向量数据库,并构建近似最近邻索引(如 HNSW)。在线阶段:用户提问后,用同一个 Embedding 模型将问题向量化,在向量库中通过相似度计算召回 Top-K 个最相关的文本块;接着将检索到的内容拼接到提示词模板中作为上下文,最后交由大模型基于这些上下文生成回答。整个过程中,检索负责找到正确知识,生成负责用好知识,两阶段的质量共同决定最终效果,而切分策略、Embedding 模型选择、检索精度(可配合 Query 改写、混合检索、Rerank 重排等手段优化)是影响效果的核心环节。
第四:平时我们是怎么用AI去写代码的?
我平时用AI写代码,不是停留在代码补全,而是建立了一套文档驱动+任务分解+验收闭环的工作流。核心认知是 Context Engineering 比 Prompt 更重要——我用项目规则文件固化技术栈和规范,把大任务拆成带验收标准的原子任务,让AI自己去查调用链而不是硬塞上下文。工具上按场景分工:IDE类的Cursor/Trae做细节编辑,终端Agent类的Claude Code做跨文件重构。同时我对边界很清醒——AI会幻觉API、大型重构要小步快跑、生成的代码要重点查安全漏洞,核心架构决策我自己做,AI负责提效执行。
其他相关
第一:讲一讲你在项目里怎么用的分布式锁?
我们项目是集群部署是定时任务幂等。门户放飞模块有几个定时任务——放飞申请到期自动提交、批件过期状态更新、放飞超时三级提醒,都是每 2 到 5 分钟执行一次。集群下多个节点会同时触发,我用 Redisson 锁保证同一时刻只有一个节点执行,tryLock 参数是等待 1 秒、租约 5 分钟:1 秒拿不到就快速放弃不阻塞,5 分钟覆盖任务最长执行时长,finally 里 unlock。不同任务用不同锁 key 互不干扰。
选 Redisson 而不是 SETNX,主要是它封装了 watchdog 自动续期、可重入锁、Lua 脚本原子操作,开箱即用不用自己踩坑。
第二:讲一讲Redission分布式锁的运行原理
Redisson 分布式锁基于 Redis 实现,底层用 Hash 结构存储锁——key 是锁名,field 是 UUID:threadId 标识持有者,value 是重入计数,天然支持可重入。加锁和解锁各用一段 Lua 脚本执行,保证「判断、写入、设过期」多步操作的原子性,避免了 setnx+expire 分离带来的竞态死锁问题。最核心的是看门狗机制:当调用 tryLock() 不传 leaseTime 时,锁默认 30 秒过期,同时启动一个定时任务,每 lockWatchdogTimeout/3(默认 10 秒)执行一次续期,只要锁还归当前线程持有就把 TTL 重置回 30 秒,业务没跑完就一直续命;而客户端宕机后定时任务停止续期,锁会在最多 30 秒后自动过期释放,从而避免死锁。加锁失败的线程不会自旋忙等,而是订阅解锁频道挂起,持锁者解锁时通过 del 删锁并 publish 通知,唤醒等待者重新竞争——既防死锁又防空转。整个过程通过 Lua 脚本、看门狗、Pub/Sub 三者配合,实现了可重入、原子性、自动续期、自动释放四大特性。
第三:我看你这里写了通过@Async异步调用外部算法服务,你这里有指定自己的线程池吗?参数是怎么样的?设置这些参数的依据是什么?
面试官您好,这三个参数是我们项目组结合业务场景压测后确定的,我来介绍一下背后的逻辑。首先看业务,我们是低空航空政务系统,线程池主要跑两类任务——一类是 CompletableFuture 并行查询,一个接口最多并行查 8~10 个数据源;另一类是审批回调和 MQ 消费后的异步处理。这些任务都是 IO 密集型的,查数据库、查 Redis、调 Feign,线程大部分时间在 wait,CPU 不忙。
核心线程数 100:我们是从 20 开始往上压的,20、40、80、100、150……压测平峰 QPS 时,加到 100 以后接口平均 RT 基本不再下降了,说明瓶颈从线程数转移到了数据库和网络层,所以定在 100——再加线程就是浪费资源,上下文切换反而多了。
队列容量 2000:这个是两个考虑,第一防 OOM,默认 LinkedBlockingQueue 不设容量是无界的,必须限死;第二看波峰压测,早高峰航班集中上报的时候,QPS 大概是平峰的 5~10 倍,持续 1~2 秒的突发流量,2000 的队列刚好能兜住不拒绝,再大的话任务在队列里等太久超时率就上去了。
最大线程数 500:这个是极端兜底值,线程池的工作顺序是核心满了进队列,队列满了才开非核心线程,所以 500 平时根本用不到。我们做缓存雪崩模拟演练的时候(把 Redis 关了,所有请求直接打数据库),核心 + 队列扛不住,扩容到 500 刚好把拒绝率压到 0 以下,再往上加 CPU 上下文切换就太严重了,反而更慢,所以定在 500。
最后补一句,这套参数上线后我们还配了监控——队列积压过 1000 告警、活跃线程超 80% 告警、只要有拒绝立刻告警,有问题能及时发现调整。
第四:用explain去定位慢查询的时候主要看哪些参数?

第五:索引失效的场景?

第六:用rabbitmq消息队列的时候,怎么保证消息不会丢失?
三个层面保障。第一,生产端开启Confirm模式,发送消息后等待Broker确认ack,未确认的重发。第二,消费端手动ack,消费成功才确认,失败则消息重新入队。第三,审批结果同时持久化到数据库,即使极端情况下消息丢失,也可以人工补偿或通过查询恢复。
第七:服务器CPU满了,我们会怎么去分析?
服务器 CPU 飙高的排查核心是"从外到内三步下钻"。第一步用 top/uptime 看系统整体负载和 CPU 占比,先区分是用户态(%us,业务代码在烧 CPU)、内核态(%sy,系统调用或上下文切换)还是 IO 等待(%wa,其实是磁盘瓶颈方向不同别搞错)。第二步用 top -Hp <PID> 下钻到线程级,拿到 CPU 最高的那个线程 TID——这一步是关键,很多人只停在进程级就卡住了。第三步把 TID 用 printf "%x\n" 转成十六进制,再用 jstack <PID> | grep nid=0x.. 抓出该线程的调用栈,建议连抓三次对比找出真正热点。看到栈后分两条路:业务代码问题(死循环、正则回溯、序列化密集计算等)直接定位方法;如果是大量线程卡在 GC Thread,就用 jstat -gc 看 Full GC 频率,并用 jmap -histo 看对象占用,排查内存泄漏——Java 应用 CPU 飙高一大半是频繁 Full GC 导致的。线上优先用 Arthas 的 thread -n 3 一步到位,复杂热点用 async-profiler 采火焰图。一句话:top 看负载 → top -Hp 定位线程 → printf %x + jstack 抓栈定位代码 → jstat 排除 GC。
第八:我们怎么通过分析GC日志定位到具体是哪一行代码出了问题?
抓栈定位代码 → jstat 排除 GC**。
第八:我们怎么通过分析GC日志定位到具体是哪一行代码出了问题?
GC 日志本身不能直接定位到代码行,它的作用是识别问题模式。首先分析 GC 日志判断属于哪类问题:如果频繁 Full GC 且老年代回收后仍然满,说明可能是内存泄漏,这时用 jmap 导出堆转储,通过 MAT 分析 Dominator Tree 找到占用内存最大的对象,再沿 Path to GC Roots 追溯引用链,定位到持有该对象的类和方法;如果是 Young GC 间隔极短说明对象分配速率过高,用 JFR 或 async-profiler 生成分配火焰图,直接看哪个方法分配最多;如果是 GC 停顿过长,用 jstack 多次抓取线程栈,结合日志中的大对象分配信息排查。最后把对象类名和引用链映射回代码,审查具体的创建逻辑,就能定位到出问题的代码行。总结就是:GC 日志定问题类型,堆转储和分配采样定对象,引用链和线程栈定代码位置。
在Linux查找一个进程,例如Tomcat,应该用什么命令?
ps -ef | grep tomcat
更多推荐



所有评论(0)