腾讯实习-个人总结自评

2025年8月6日 · 4122

数据等敏感内容已脱敏

实习总结自评

实习回顾

入职熟悉阶段

入职时还是 4 月中旬,腾讯是我实习的第一家大厂。来之前我就对这里满怀憧憬与向往,入职后发现一切果然不负所望:无论是公司的瑞雪文化,同事间的热情友好,还是 mentor 深厚的技术底蕴,都让我觉得这段实习经历十分值得。

刚入职时,mentor 就为我制定了一系列计划,包括熟悉研发平台、测试流程,以及我接下来需要重点参与的代码仓库。在整体计划的基础上,还明确了我需要学习的内容,并且为了让我更好地适应和熟悉工作,分配了相应的需求。这些任务对我来说并不算难,而且是循序渐进的过程。一开始,我为我们负责的功能新增了几个 e2e 测试;之后,又重构了服务中某个模块的单元测试;再后来,终于接触到服务本身的开发 —— 虽然只是解决了一个小 bug,但修复这个 bug 的过程让我积累了多项目协作的经验,也让我在工作中越来越得心应手。

较难需求过渡阶段

在完成几个小需求、熟悉了平台和研发流程后,我迎来了第一个真正具有挑战性的需求。

事情的起因是 mentor 有一项新工作需要启动,便将前期调研的任务分配给了我。不过这里的调研并不需要与用户沟通,我要做的是从不同数据库中提取所需数据,经过筛选、聚合、统计后,得出我们需要的结果。基于这份结果,我们才能评估新工作的可行性并进行收益分析。总的来说,这是一件充满乐趣的事,尤其在方案评审会上,当看到由我的代码生成的数据被投放到大屏幕上供大家分析讨论时,我内心充满了满足感。

值得一提的是,在这个需求中,我运用了 Go 的 cobra 框架、本地缓存技术,再结合多线程任务处理等优化手段,最终将需求成果转化为一款工具。其他人可以通过二次开发代码自定义规则,再借助命令行指令,就能便捷地接入其他数据库执行相关操作。在我完成需求后,这个工具进一步抽离了耦合逻辑,最终通过 MR 合并到了多个小组共用的工具库中。通过这件事,我切实感受到了为团队带来便利的成就感。

复杂需求阶段

随着对业务的熟悉,在完成几个基础需求后,我迎来了实习期间复杂度最高、耗时最长的任务。 恰逢学校考试季,一个月内我不得不频繁请假,导致这项实际开发周期仅两周的工作,最终贯穿了 5 次周报。尽管上下文频繁切换影响了部分效率,但凭借入职阶段积累的经验,我通过每日同步进度、编写日报等方式,稳步推进需求,最终达成预期目标。

需求背景与演进逻辑

该需求全称为 "磁盘限速与优先级支持声明式配置并提供运营监控手段",是对现有磁盘限速功能的迭代升级。其技术背景与我们基于 k8s 构建的自定义 CRD 密切相关:我们的 CRD 类似增强版 deployment,可通过自定义字段(如 minReplicas、writeIOPS 上限)与其他服务协作,动态生成符合配置的 pod。

原有功能实现存在明显短板:用户通过接口提交限速请求后,服务需先修改 CRD,再将任务记录存入数据库;后台通过 goroutine 定时轮询数据库,提取未完成任务进行处理。这种模式既引入了不必要的 DB 依赖,又让用户无法感知任务状态(如进行中、失败),且轮询全表的操作存在效率隐患。更关键的是,它与 k8s"声明式配置" 的设计理念相悖 —— 用户本应只需定义终态,无需关心执行过程。因此,重构的核心目标是:基于 k8s 的 Informer 监听机制实现配置式流程,移除 DB 依赖,同时补充监控能力。

技术方案设计

接手时需求仅明确目标,未提供具体方案。我在研读项目源码时发现了 k8s Informer 的事件监听能力,通过自学相关技术文档,设计了 Manager-Handler-Task 框架,实现了对原有流程的无侵入式重构(新增代码与其他模块完全解耦)。

我设计了 Manager-Handler-Task 的流程框架。Manager 负责功能生命周期管理与任务调度,通过 Informer 监听 CRD 的 update 事件触发任务创建;Handler 针对不同任务类型实现统一接口(handle/specEqual/isPodsNeedReconcile),确保扩展灵活性;Task 保存任务执行和 Manager 协调所需的字段数据等。

除了流程框架的设置之外,在设想实际操作时,我还遇到了两个难题;1:Task 如何去重,2:如何保证任务只被执行一次。这里我们先来说第二个难题的由来和解题思路。

如何保证任务只被执行一次

在具体实现阶段,我重点考虑了分布式环境下的任务执行唯一性问题。由于服务采用无状态设计,正式环境部署了数十个节点,若不对任务执行权限加以控制,极有可能出现多个节点同时处理同一任务的情况。针对这一问题,我最初构思了两套解决方案:

第一种思路是从 CRD 设计层面入手,在 Task 字段中新增 isAcquired (任务是否被获取)字段,通过标记状态避免重复执行。但分析后发现其存在明显缺陷:若持有任务的节点执行失败或意外宕机,任务会因 isAcquired 标记为 “已获取” 而陷入停滞。即便补充 acquiredTime(获取时间)字段,通过与节点本地时间对比判断超时(超时执行超时强制重新获取),仍会衍生新问题:一是若节点宕机后用户一直未更新 CRD,那就没有该 CRD 的更新事件产生,其他节点也就无法通过监听事件感知到停滞任务;二是跨节点本地时间存在偏差,需引入第三方时间同步服务,这显然会增加系统复杂度。

经过权衡,我决定采用 “分区 master 节点独占 + 定时对账” 的组合方案,在保证最终一致性的前提下控制实现成本:

  1. 权限隔离:指定每个分区的 master 节点为唯一任务执行节点,直接避免分布式节点的资源竞争情况。
  2. 对帐补偿:为解决极端场景下的任务停滞(如 master 节点宕机),设计定时对账机制 —— 每 3 小时触发一次全量 CRD 检查。借助 Informer 的本地缓存特性,遍历操作效率极高:测试环境中扫描 10000 个 CRD 仅耗时 142 毫秒,按正式环境数据量推算全程不超过 5 秒,且 3 小时的执行间隔不会对系统资源造成额外负担。

如何去重

在分布式任务处理流程中,去重是保障系统一致性的关键环节 —— 尤其在结合 “分区主节点 + 定时对账” 机制后,需应对用户重复请求、对账扫描触发重复任务等场景,因此高效准确的去重逻辑直接影响最终执行结果与资源利用率。

实际业务中存在三类典型重复场景,需要针对性的设计处理规则:

  • 场景一:用户短时间内发送两次参数不同的请求 —— 需识别参数差异并以最新请求为准;
  • 场景二:用户发送两次参数完全相同的请求 —— 需避免重复执行,直接标记为成功以节省资源;
  • 场景三:用户单次请求后,定时对账扫描再次触发任务添加 —— 需识别任务同源性,避免重复处理。

本质上,去重的核心目标是确保任务执行结果与用户最新配置一致,同时兼顾执行效率。

为了实现这一目标,我先后评估了三种技术方案,而且什么是先后呢?因为有一些东西我确实是逐渐发掘起来的,这个目标的每一种解决方案都是我实际写代码体验过,评估过的。

  1. **基于时间戳(createAt):**计划在 CRD 的任务列表中新增 CreateAt 字段记录任务创建时间,通过时间先后判断请求顺序。但 k8s 推荐的 meta.Time 类型默认序列化到秒级,精度无法满足高并发场景(同一秒内的请求无法区分);若自定义微秒级时间戳,又与 k8s 的 API 设计规范冲突,不够优雅。
  2. **基于 ResourceVersion:**该字段天然具有唯一性,最初被我视为理想选择。但查阅 k8s 官方文档后发现,其明确禁止将 ResourceVersion 解析为 int64 类型 —— 且社区讨论显示,未来可能将其替换为非数字格式,同时该字段不保证严格递增,存在逻辑漏洞。无奈只好另寻他路。
  3. 基于 Generation 字段:在反复查阅 CRD 定义时,我发现了 k8s core.Metadata.Generation 字段:它是 int64 类型,支持数值比较,且会随 Spec 配置的每一次更新自动递增,完美匹配 “通过版本区分请求先后” 的需求。

最终我基于 Generation 的特性设计了分层去重逻辑:

  • 跨 CRD 维度:通过 metadata.Name(CRD 实例唯一标识)区分,不同 Name 的 CRD 任务互不干扰;
  • 同 CRD 维度:先比对 taskType 对应的 Spec 配置,若内容完全一致则判定为重复任务,直接跳过;若配置不同,则比较 Generation 值,仅保留数值更大(即更新)的任务。

此外,为配合去重机制,我还设计了任务取消功能:在自定义 Task 结构中嵌入 stopChan,当检测到更高 Generation 的新任务时,可通过关闭通道立即终止旧任务执行,避免资源浪费。这一机制与去重逻辑形成闭环,进一步提升了系统的响应效率。

在方案落地后,我通过单元测试,编写脚本重复请求,脏代码注入等方式测试功能的完备性。你也可以通过查看企微文档来简单的了解我的测试内容(仅腾讯员工可查看):diskLimit 功能验证

功能补充

为确保核心流程的稳定性与可运维性,我在方案中补充了多项支撑功能,形成完整的任务处理体系:

  1. **退避重试与告警机制:**针对任务执行失败的场景,设计了指数退避重试策略(失败间隔随次数递增),避免无效重试消耗资源;当重试次数达到上限时,系统会自动触发告警并推送至我的企业微信,确保异常情况能被及时处理。
  2. **柔性限流设计:**除基础 QPS 限制外,通过生产 - 消费队列实现任务解耦:生产者负责接收任务并加入队列,消费者按配置的并发数(可通过配置文件动态调整)处理任务,既避免了瞬时流量冲击,又能灵活适配不同节点的资源承载力。
  3. **全链路可观测性:**构建了完善的监控指标体系,包括任务执行时长、队列积压量、并发执行数等核心 metric;同时在任务创建、执行、终止等关键节点嵌入结构化日志,结合监控数据可快速定位异常根因,大幅降低排查成本。
  4. **灵活的运营配置:**将重试次数、限流阈值等重要参数纳入配置文件管理,无需修改代码即可通过重启服务生效,满足运营过程中的动态调优需求;针对特殊分区(如资源受限或承担核心业务的节点),支持通过配置手动关闭任务处理功能,实现差异化运营。
  5. **高可用保障:**实现两大稳定性机制:一是优雅退出,通过监听主进程 context,在收到终止信号时会先完成当前任务再退出,避免数据不一致;二是动态启停,任务模块不随进程启动默认激活,而是依赖 master 节点选举结果 —— 仅当节点成为分区 master 时自动启动,否则自动关闭,减少非主节点的资源占用。

此外,实习期间我还参与了另一项大型需求的开发,该任务虽技术难度适中,但涉及到相对较大的资源量,我还对其进行了资源统计和资源消耗预估。不过此处就一笔带过。

实习所得

在这里首先好好感谢团队里的每一个人。实习这段时间,我遇到的问题五花八门,几乎涵盖了大家各自擅长的领域,但每次我去请教,得到的都是特别耐心的回复。这不仅帮我解决了问题,更重要的是,让我那种怕把事情搞砸的焦虑少了很多。 然后必须单独谢谢我的 mentor。每次我带着一堆问题去找他,他都会特别细致地给我讲,但又不会直接把答案甩给我,总是一点点引导我自己想明白。这样一来,我对问题本身的思考就多了,理解也更深入,确实学到了不少东西,再次感谢。

除了技术上的进步和认识这么多大佬,还有一点特别想写在实习所得里的,就是公司的瑞雪文化。记得入职第一天就拿到了一本《瑞雪之书》,而且第一天我什么权限都没开,内网网站基本都进不去,就在工位上翻了半天。一开始只觉得挺有意思,觉得公司特意推广这种向善的文化,跟我的想法挺合得来。

直到后来真的遇到了很多温暖的人和事:热心帮我解决问题的大佬,在楼梯口特意按住门等我的同事,打饭时总给我多盛点的阿姨,耐心解答问题的 8000、8008 同学,还有每次去拿快递都满脸微笑的邮件中心小哥。这时候才明白,瑞雪真不是嘴上说说的,公司和这里的每个人,都在实实在在让这个地方变得更好。

这段实习不止让我在技术上往前迈了一大步,更让我明白,一个好的工作环境,一群温暖的人,对成长有多重要。

未来展望

我始终以勤勉自勉,对技术抱有持续的热忱与探索欲。很荣幸在实习期间结识了众多志同道合的伙伴,共同在项目中攻坚破局。虽因个人规划未能选择留在组里发起转正申请,心中满是遗憾 —— 从下定决心到告知 mentor 的每一刻,都伴随着对团队的不舍与歉疚。好在 mentor 的宽慰让我学会以更开阔的视角看待前路,这份理解与支持也成为我前行的动力。

未来具体会走向哪里,现在的我确实说不准,就像眼前蒙着一层薄雾。不过希望自己会坚定初心,怀揣着世界的善意踏实的走下去。