我带的外包兄弟放弃大厂转正,薪资翻倍入职字节

大家好,我是老A

国庆节的时候,收到一位粉丝的私信求助。一来一回聊了半天,我发现了一个很多技术兄弟的通病------我们称之为「收藏夹式努力 ​」。水文看不上,只想让大佬推荐技术宝典,一旦拿到手,焦虑感削弱,宝典就在收藏夹里吃灰,下了班照样峡谷开黑。当你想督促他深入研究时,他又会用「他是大佬,我不是,我做不到 」来给自己设限,最终陷入「持续焦虑,持续躺平」的恶性循环。

这种惰性,是人之常情。但人和人之间的差距,就在于如何对抗它。这让我想起了我去年带过的一个外包兄弟,小汪。坦白说,他刚来的时候,也和这位粉丝一样,技术普通,满脸焦虑,总觉得自己不行

但他最终,靠自己的努力,挣脱了这个循环。他没有转正,却在一年后,薪资翻倍进了字节。

今天,我就把小汪的这段真实经历,以及我当时给他设计的那份「镀金计划」,毫无保留地分享出来。希望能为所有困在原地的兄弟,提供一条走得通的路。

第一幕:一个困在围城的年轻人

小汪是2023年6月份进组的,主要跟我做CRM的售卖系统,给我的第一印象是这小伙子阳光开朗,踏实肯干,不懒惰,很勤劳,基本每天都是第一个到公司(当然不是说第一个到公司就好,主要是从这点看出他很勤劳)。

小汪的技术基础还行,大概半个多月就熟悉了公司的技术基础设施和基础业务,之后就开始跟着我做项目。

他的成长速度真的很快,每天都会追着我问各种业务问题,应用问题还有代码问题,每次CR也都主动找我交流,能看的出来,他是真的很想进步,所以我也是倾尽所有的去教他带他。前半年,他工作的热情高涨,每天都像个小太阳一样,正能量满满,积极乐观的工作态度感染着周围的同学。

但是半年后,明显感觉到这个小太阳能量不足了,脸上的笑容也越来越少,察觉到这个变化,我赶紧跟他进行了一次one one交流,让我终于知道了原因所在。

小汪表示他觉得自己就是个二等公民,作为外包,他感受到了诸多不便,再努力都没用。

  • 不便一:各种权限申请搞疯掉

    小到一篇文档、一个钉钉名片、一个项目环境吧器,大到一个代码库、应用、开关、配置他通通都要经过4层以上的审批,给他的工作带来了极大的不便,过程中也倍受冷眼,比如跟某些大厂骄子申请权限,已读不回,钉了也不回的例子太多,其中的心酸只有他自己能懂。

  • 不便二:外包身份让他无法接触到核心

    虽然我带着他做项目,能教的都在教他,业务也都给他讲的明明白白,但是从不会让他接触到项目最核心的技术部分,也不会把核心开发部分交给他做(这个我要喊一句冤枉,不是不交给小汪做,是不能,我们有严格的要求核心研发必须正式员工来做,毕竟背锅也是我们自己来,所以自己做也比较放心,但是每次的CR我都会叫上小汪,让他知道这个需求的核心部分是如何实现的)。

  • 不便三:所有的需求都不会让他独立完成,都需要我出技术方案,他去执行

    小汪觉得这样很不利于他的成长,就像离不开鸡妈妈的小鸡(这里批评一下,这个比喻太不恰当了,我不是鸡妈妈😂)。后面这里我改为了他出方案,我来把关评审。

  • 不便四:所有的核心技术分享都接触不到

    小汪说他想成长,但是每次部门的核心技术分享都不会邀请他,他也不知道有哪些技术分享,这让他更加难受,想成长却没有门(这个我后面反思了,因为我们的技术分享基本都在晚上8点以后,外包同学基本6点多就下班了,所以之前我一直没好意思留下小汪,毕竟让人加班等到8点不太优雅,那次one one谈话后我每次分享都会提前告诉他

最后小汪终于道出了压在心底的话:他拼命工作、拼命学习,就是为了撕掉"二等公民"的标签,成为一个真正的"自己人"。但他抬头四顾,满眼都是绝望:"A哥,我来了一年多了,一个转正的都没见过。这条路,真的走得通吗?"

第二幕:"B面"点化------"你的目标,从一开始就错了"

听了他的话,我沉默了足足有半分钟。我不是在想怎么安慰他,我是在想,这盆冷水,到底该怎么泼下去,才不至于浇灭他眼里最后的光。

他说的这些,我何尝不知呢?别说他只来了一年多,我在公司6年了,也没见到一个外包转正的。外包转正,这本身就是一个悖论,可能性十不足一。

所以我直接告诉他了外包转正的三个"残酷真相"

  1. "HC(Headcount)隔离墙":首先外包在哪个公司都算是一种技术资源,哪里需要去哪里。其招聘成本和正式员工不在一个等级,一个部门每年的正式员工HC是很珍贵的,基本一年1-2个,所以老板和HR都想把这个名额给到一个尽可能优秀的人。那么老板如何判断一个候选人是否优秀?第一就要看学历和工作经历,基本95%的外包同学都倒在这一关了。而一个外包HC就宽松多了,老板向部门申请预算也会容易的多,所以体现在面试上也容易很多。这就是为什么外包在老板这关就很难转正的原因。
  2. "招聘标准双轨制" :坦诚地说,社招一个P6的门槛,和外包转正一个P6的门槛,是完全不同的。我们社招的时候招一个P6的标准:985/211、有大厂经历、能独立完成中型项目、对自己做过的项目完全掌握这就行了。但是如果是外包转正一个P6:那你得有极其耀眼的项目经历或者做出过什么大贡献,比如挽回了1000万资损这种。但是这两个条件对于外包同学来说,难于上青天。。。这本身就是不公平的,却是赤裸裸的现实。
  3. "价值归属的原罪":外包同学是不会自己负责一块独立的业务的,所以他在项目里做的所有业绩,在汇报时天然会归功于他的直属正式员工Leader。

最后,我看着他的眼睛,一字一句地跟他说:"小汪,记住,从今天起,别再把转正当成你唯一的目标了。那是一条官方留给你,但几乎锁死的路。你的真正出路,是把在这里的每一天,都当成一场偷师学艺。你的目标,不是留下,而是镀金后,去一片更广阔的天空!"

第三幕:镀金!从CRUD Boy到"准架构师"的技术蜕变

1. 镀金第一步:"偷"文档,找到"战场"

老A点化 :我告诉小汪,你要学会"偷师",去lark上把我们CRM系统 所有的故障复盘文档 ,全都找出来读一遍。再去看架构组的周会纪要 ,看看那些P8、P9们,到底在为什么问题而头疼 。同时多交好一些正式员工,作为资源人脉,一旦有HC可以做内推。

发现"战场": 小汪花了一周的下班时间,真的找到了一个有价值的痛点------一个半年前的P3故障 复盘文档。这个故障始于CRM系统一个用于"同步客户签约状态 "的核心接口,由于需要依次调用 "会员中心"、"订购中心"、"风控中心"、"合同中心"四个下游服务,这几个系统都是有20年以上的历史的老系统,整个链路过长,在大促高并发下,TP99延迟飙升到5秒以上,导致整个签约流程的体验很差,经常出现签约异常情况。这个问题,因为"历史悠久、无人敢动",至今只是做了限流(令牌桶),也提出了渐进式优化的方案,但是苦于业务排期压力,一直没有排上日程。

老A点评 :"镀金 "的第一心法,找到那个所有人都知道痛,但没人敢治的"病灶 "。这,就是你的战场

2. 镀金第二步:"偷"代码,找到"武器"

小汪找到了"战场",但却不知道该怎么解决。他能想到的,还是优化SQL、加缓存这些常规操作。

老A点化 :我直接把公司内另一个核心交易网关 的代码读权限,给他临时申请了一天。然后告诉他:"别看那些修修补补的代码。去看看我们最新一代的交易应用代码,看看他们是如何编排和调度多个下游微服务的。偷师他们的设计思想。"

"偷"到"圣经" :小汪在这份新代码里,第一次看到了一个完全不同的世界------基于CompletableFutureThreadPoolExecutor构建的、优雅的异步化、非阻塞的编排方案。他这才明白,高手们早就不用同步调用链这种办法了。

3. 镀金第三步:从"看懂"到"精通"的灵魂拷问

小汪看了一天的交易代码,然后兴奋地跑来找我,说他准备用CompletableFuture.allOf()来并行化那三个RPC调用。但他还没说完,我就提出了三个"B面"灵魂拷问,直接把他问住了:

第一问:你打算用什么线程池来跑这些异步任务?

小汪脱口而出:"就用CompletableFuture默认的就行吧?"

我告诉他,这就是新手和老兵的第一个分水岭 。默认的ForkJoinPool.commonPool(),就像一个顶级餐厅里那几个最牛的、做菜最快的大厨,它是为计算密集型任务设计的。

而你的RPC调用,是IO密集型任务,就像是去等一份永远不知道何时能送达的外卖。如果你让大厨去等外卖,整个厨房很快就会瘫痪。

正确的做法,是为这些IO任务,单独建立一个"服务员"线程池,让他们去等,别占用我们宝贵的大厨资源

java 复制代码
// 老A的B面架构第一课:为IO密集型任务自定义线程池
private final ThreadPoolExecutor syncExecutor = new ThreadPoolExecutor(
    20, // 核心线程数,根据QPS和下游延迟估算
    200, // 最大线程数,应对突发流量
    60L, TimeUnit.SECONDS, // 空闲线程存活时间
    new LinkedBlockingQueue<>(1000) // 队列大小,防止OOM
);

第二问:三个RPC调用,真的可以完全并行吗?

我让他把旧代码贴出来,又问了他第二个问题:"你仔细看,这三个RPC调用,真的可以完全并行吗?" 小汪看着旧代码里那句orderClient.getLastOrder(info.getOrderId()),沉默了。

他这才发现,获取"订单信息",依赖于先获取"会员信息"的结果

我告诉他,allOf是万马奔腾,适用于没有依赖关系 的并行任务。而这种需要"第一棒跑完,第二棒才能接力"的场景,你需要的是thenCompose<。这,是第二个分水岭

java 复制代码
// 老A的B面架构第二课:用thenCompose处理依赖性的异步任务
CompletableFuture<UserInfo> futureInfo = CompletableFuture.supplyAsync(...);
CompletableFuture<OrderInfo> futureOrder = futureInfo.thenCompose(info -> 
    CompletableFuture.supplyAsync(() -> orderClient.getLastOrder(info.getOrderId()), syncExecutor)
);

第三问:你准备用 thenAccept还是 thenAcceptAsync来更新数据库?

最后,我问了他第三个问题:"当所有结果都计算完,你准备用thenAccept还是thenAcceptAsync来更新数据库?" 小汪一脸茫然。

我给他讲了一个真实的"B面"血泪史:曾经一个团队,因为在回调里使用了同步的thenAccept,而回调方法里又有一个微小的锁竞争,导致在高并发下,整个异步线程池被"反向"阻塞,引发了P2故障。

这,是第三个分水岭 ------ 永远要假设你的回调逻辑也可能阻塞,用thenAcceptAsync把它也扔进线程池里去执行,做到"绝对隔离"。

4. 终极镀金:用"A面"武器,重构"B面"屎山

在我问出这三个问题,并把自定义线程池ThenCompose这两个武器的核心代码画给他看之后,小汪说他要回去思考下。

我知道,他已经悟了,聪明的小汪~

又过了大概一周后,小汪发来了一个重构方案评审会邀,在会上他向我展示了他利用下班和周末的时间,写出的下面这份堪称"教科书级"的重构方案。

他不仅完美地应用了我们讨论的所有技术点,甚至还举一反三,在方案里加入了极其专业的超时控制(orTimeout)基于指数退避的重试机制、以及完善的异常处理

他不再是简单地模仿,而是真正理解了系统痛点背后的"B面"权衡。

我很惊讶于小汪的执行力,可以这么快就给出这样比较完整的方案。我对整体的重构方案进行了严格的技术把关和评估,最终评审通过,决定采用小A的这套方案 ,并通知小A配合测试同学给出压测方案和报告。 团队双周技术分享会上,小汪主讲了这个重构方案,并给出了详尽的压测报告(P99延迟从5秒降到150ms,接口吞吐量提升300%),整个过程技惊四座。那一刻,再也没有人把他当外包了。

java 复制代码
@Service
public class UserSyncServiceV2 {
    // 老A的B面架构第一课:为IO密集型任务自定义"服务员"线程池
    private final ThreadPoolExecutor syncExecutor = new ThreadPoolExecutor(
            20, 
            200, 
            60L,
            TimeUnit.SECONDS, 
            new LinkedBlockingQueue<>(1000)
    );
    
    // ... 注入各个Client ...
    
    public CompletableFuture<Boolean> syncStatusAsync(Long customerId) {
        // 1. 并行获取无依赖的用户信息和风控结果
        CompletableFuture<UserInfo> futureInfo = CompletableFuture.supplyAsync(
                () -> userClient.getUserInfo(customerId), 
                syncExecutor
        );
        
        CompletableFuture<RiskResult> futureRisk = CompletableFuture.supplyAsync(
                () -> riskClient.checkRisk(customerId), 
                syncExecutor
        );
        
        // 2. 老A的B面架构第二课:用thenCompose处理依赖性的异步任务(订单依赖用户信息)
        CompletableFuture<OrderInfo> futureOrder = futureInfo.thenCompose(info -> {
            if (info == null || info.getOrderId() == null) {
                // 如果前序结果为空,优雅地返回一个空的Future
                return CompletableFuture.completedFuture(null);
            }
            return CompletableFuture.supplyAsync(
                    () -> orderClient.getLastOrder(info.getOrderId()), 
                    syncExecutor
            );
        });
        
        // 3. 老A的B面架构第三课,组合所有结果,并用thenApplyAsync进行最终的数据库操作
        return CompletableFuture.allOf(futureOrder, futureRisk)
                .thenApplyAsync(v -> {
                    // ...从各个Future中join()结果,并进行组合...
                    // ...验证数据完整性...
                    
                    // 更新数据库
                    updateDatabase(syncResult);
                    
                    log.info("用户状态同步成功, customerId: {}", customerId);
                    return true;
                }, syncExecutor)
                .exceptionally(e -> {
                    log.error("异步同步失败, customerId: {}", customerId, e);
                    return false;
                });
    }
    
    // ... updateDatabase()等私有方法 ...
}

老A说:从毕业作品到"生产级"的最后三公里

兄弟们,小汪的这份代码,已经是一个极其优秀的技术验证原型。但要把它真正投入生产,我们还需要打磨三个"B面"细节:

线程池的哨兵: 必须为这个线程池配置合理的拒绝策略,并接入相关监控平台(如Sunfire)进行监控,防止在高并发下被打爆。

异步安全保障: exceptionally里的简单日志还不够。生产级代码需要集成Resilience4j这样的熔断器和重试框架,防止下游服务的抖动引发雪崩。

数据的安全锁: 异步化后,如何保证数据一致性?我们需要引入Saga或TCC等分布式事务方案,来确保整个流程的原子性。

这最后三公里,才能区分出你是高级工程师 还是架构师

第四幕:一年之后------"他放弃了转正的想法,选择了字节"

就这样,小汪按照我的镀金计划不断的"偷师取经,稳步成长",我能明显感觉到他在技术、视野和自信心上发生了脱胎换骨的变化。今年年初,我们的一个正式HC恰好空出,老板也确实在考虑他。但与此同时,通过之前积攒来的人脉,他也拿到了一个字节的面试机会。结果也在我的意料之中,他顺利通过了面试,薪资直接翻倍。他最终礼貌地"放弃"了在内部等待那个不确定的转正机会,飞到了另一片天空。

感言

我至今都记得小汪拿到Offer后请我吃饭时说的话:"A哥,谢谢你,没有你就没有我的今天。谢谢你让我找到成长的最优路径,谢谢你掏心窝子对我说的那些话,谢谢你对我的倾囊相授,谢谢你让我明白成长的意义所在,谢谢你让我知道我可以,我能行!"

老A说:其实一个人的价值,不应该由别人给你打上的身份标签来定义。我们可能无法选择起点,但可以通过正确的战略和努力,选择自己的终点。

老A时间

感谢各位兄弟的阅读。

我是老A,一个只想跟你说点B面真话的师兄。如果这篇文章让你有了一点点启发,那就是对我最大的肯定。

为了感谢大家的支持,我把这两年在一线大厂面试和带团队中,沉淀下来的所有上不了台面的私房笔记,整理成了一份《程序员B面生存手册》。

里面没有市面上千篇一律的八股文,只有一些极其管用的"潜规则"和"避坑指南",希望能帮你少走一些弯路。

关注我的同名公众号【大厂码农老A 】,在后台回复"B面",就能免费获取。

回复"简历 "获取《简历优化手册

回复"arthas "获取史上最全的《大厂arthas实战手册

回复"指导 "获取《大厂外包镀金手册

最后,如果觉得内容还行,也希望能点个赞、点个在看,让更多需要它的兄弟看到。

我们一起,在技术的路上结伴"陪跑"。

相关推荐
哈里谢顿18 小时前
1000台裸金属并发创建中的重难点问题分析
面试
哈里谢顿18 小时前
20260303面试总结(全栈)
面试
橙序员小站19 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
怒放吧德德20 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆21 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
开心就好20251 天前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
悟空码字1 天前
告别“屎山代码”:AI 代码整洁器让老项目重获新生
后端·aigc·ai编程
小码哥_常1 天前
大厂不宠@Transactional,背后藏着啥秘密?
后端
奋斗小强1 天前
内存危机突围战:从原理辨析到线上实战,彻底搞懂 OOM 与内存泄漏
后端
over6971 天前
从 LLM 到全栈 Agent:MCP 协议 × RAG 技术如何重构 AI 的“做事能力”
面试·llm·mcp