博客 / 詳情

返回

我帶的外包兄弟放棄大廠轉正,薪資翻倍入職字節

大家好,我是老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任務,單獨建立一個“服務員”線程池,讓他們去等,別佔用我們寶貴的大廚資源

// 老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<。這,是第二個分水嶺

// 老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%),整個過程技驚四座。那一刻,再也沒有人把他當外包了。

@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實戰手冊

回覆“指導”獲取《大廠外包鍍金手冊

最後,如果覺得內容還行,也希望能點個贊、點個在看,讓更多需要它的兄弟看到。

我們一起,在技術的路上結伴“陪跑”。

user avatar dm2box 頭像 FatTiger4399 頭像 ticktank 頭像 prepared 頭像 deltaf 頭像 zilliz 頭像 goudantiezhuerzi 頭像 91cyz 頭像 wodingshangniliao 頭像 TwilightLemon 頭像 luoshenshen 頭像 dadegongjian 頭像
71 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.