想起了自己畢竟是技術Leader,天天水管理也不是個事,所以還是聊下工程端的一些工作吧。工程的問題最終全部會體現在業務上,一個系統一直優化不好,因為每個系統都可能旁枝錯節:
管理側的解題思路前面很多文章已經介紹,今天主要介紹工程側的解決辦法。
這裡可以新增關注交流一下嘛……
Case:優化不好的系統
背景
研發研發團隊去年年初60人左右,由於業務急速增長,6月啟動招聘擴大研發團隊規模,至今團隊接近200人,新人佔比超過60%;
與此同時,需求井噴,產研團隊應接不暇,作為最終執行側的研發團隊暴露的問題尤為凸顯,常常成為被吐槽物件,業務壓力大,歷史包袱重成為團隊常態;
具體表現
工作臺是平臺重要的工具,從上線以來BUG不斷:
1、使用者量大後,進入工作臺空白/使用系統卡頓;
2、工作臺新訊息不置頂(有BUG);
3、工作臺使用者列表區頭像裂開;
4、以及難復現的各種各種偶發性問題等等…
為解決這個問題,小規模優化10多次;大型優化2次,結果依舊不理想。
抽象問題
這個簡單的Case體現了三個問題:
組織建設問題:
1)管理單點凸顯。上下鎖死,一米五九問題嚴重,關鍵人凋零,組織執行力跟不上……
2)質效問題。產品質量低下並且研發質量意識不足;專案流程混亂,文件基無沉澱;業務單點問題嚴重,整體業務意識偏低……
3)工程問題。歷史包袱過重,工程建設停留在兩年前;現有數量級一定會有效能問題,更不能滿足10倍增長;業務效率一定會跟不上……
去年剛到新公司就面臨這一棘手環境,除了業務方還經常有運維或者開發同學吐槽,問題大致下面幾點:
1)服務依賴複雜,部署管理難(如果涉及到大版本迭代釋出,經常都是通宵發版本,並且很難順利發成功);
2)新老邏輯交叉很難做技術迭代升級(技術負債太多,很難做好規範,翻新老邏輯困難)。技術語言不統一,一部分php一部分golang,涉及到緊急專案人員協調困難;
3)由於程式碼很少翻新,瞭解之前的歷史業務的同學比較少,新同學很難快速熟悉老業務,非常擔心業務熟悉的老同學離職,技術團隊的穩定性差;
基於上面的原因我們打算使用新的成熟的微服務框架,來重構公司所有的專案,解決以上問題,並且通過工程化和devops一些系統,讓整個技術團隊的工作輕鬆,不需要花太多時間在框架和環境上,更多時間放在業務上。
先說說什麼是微服務
微服務(Microservices)就是一些協同工作小而自治的服務。
2014年,Martin Fowler 與 James Lewis 共同提出了微服務的概念,定義了微服務是由以單一應用程式構成的小服務,自己擁有自己的行程與輕量化處理,服務依業務功能設計,以全自動的方式部署,與其他服務使用 HTTP API 通訊。同時服務會使用最小的規模的集中管理 (例如 Docker) 能力,服務可以用不同的程式語言與資料庫等元件實現 。「維基百科」
我們的目的也是將我們現在複雜混亂的額專案變的邊界清楚,並且每個專案做自己獨立的事情,系統與系統之間能夠方便快速呼叫,並且入手成本很低。
我們也在網上了解一些微服務框架最終使用,最終基於B站開源的 discovery(https://github.com/bilibili/discovery)、kratos (https://github.com/go-kratos/kratos)兩個專案進行我們服務的搭建,kratos是使用的1.x版本,選擇這個專案的原因是該專案微服務治理方面比較完善,有完整的監控大盤、鏈路追蹤、限流、統一配置、告警 以及一些常用的中介軟體,我們也是使用的大倉的模式來組織程式碼,能夠極大的提高開發效率。
簡單的腳手架
1、首先我們需要一個快速建立工程的腳手架,如下圖,直接通過medcreate就會在golang對應的目錄中建立一個完整的新工程,我們整體工程分了3類 服務類、BFF閘道器類、Job定時任務類
工程建立之後,在開發中,我們使用的grpc來進行介面,參考kratos也知道我們也是基於proto檔案來定義http介面和grpc介面,所以我們開發一個工程中使用的工具medgen包含以下功能
1)、定義proto檔案之後,可以根據命令生成對應的grpc或者http的一些golang的模版形式的初始化程式碼,直接寫上邏輯程式碼就可以正常執行
2)、我們使用的文件有多種,我們可以直接根據命令生成swagger、markdown、yapi等,並且直接上傳到對應的伺服器上,非常方便。
3)、還能生成一些redis、db操作的一些模版程式碼供參考。
4)、也可以生成grpc的client程式碼,等等。
有了以上的工具,單個專案開發就會變的比較簡單,並且大家統一工具,一些生成的程式碼都是可以整個工程快速變更的,並且非常方便。
服務發現
這部分需要參考discovery,我們也是直接使用discovery來作為註冊中心進行服務發現,並且部署了3個節點(現在discovery多個節點資料同步會有小問題,需要修改程式碼)
配置中心
kratos提供了統一的配置,我們使用的攜程的apollo作為配置中心,kratos也是支援,但是唯一不好的事apollo不支援toml結構的配置,我們之前的所有服務都是使用的toml,我們最終使用了apollo txt的private的namespace 存放toml格式的配置,勉強可以用。我們也可以根據不同環境來配置apollo支援我們後面所說到的泳道(有多個開發或者測試環境,每個環境的配置管理)。
測試環境除錯
我們使用kratos的環境區分也是用的染色的方式來進行區分的,一般來說我們的服務可能有幾百個,不會本地全部啟動,我們本地可能會連結到不同的測試環境中進行測試,所以提供了grpcDebug通過json編碼呼叫grpc的服務,如果需要測試環境能夠呼叫到我們本機的服務,需要測試環境和公司的網路互通,我們現在辦公網路事互通的,不同環境的除錯是非常方便的。
大倉如果出現程式碼洩漏是非常不安全的,所以我們比較重要的專案也做成了單獨的私有倉庫,只是支援快速的方便呼叫,使用方式和上面所說的一樣。
釋出系統
接踵而至的是團隊越來越大,服務越來越多,僅僅靠運維團隊是不行的,是不是要把服務的維護“成本”分攤到不同的單元化開發小組分而治之,這樣每個小組並不需要承擔太多的維護成本,而且能夠減少運維的時間成本,讓整個複雜的事情變的短小可控。
於是我們準備搭建一套系統來解決以上提到的問題,並且能夠支援業務和團隊的持續擴張。
下面就用一些例子來說一下我們現在做成的系統能解決的問題
例子1:
開發:新來了一個需求,左顧右盼,這是一個新的業務線,我們需要新建一個新的微服務,還要為該服務新建一套測試環境、預發環境、線上環境。
之前運維:需求提過來我在各個環境的jenkins建立對應的專案,20分鐘給你弄好。
開發:來吧,我們這個需求比較大,我們需要有10個新的應用需要建立30套環境。
如果你有一個系統
現在運維:你有10個系統,你們自己去我們的系統上建立環境就可以了,資源自己配置,我給你稽核
建立多個環境,並且每個環境1個節點
這樣原本需要運維解決多次建立不同環境的事項分擔到多個研發,不會阻塞到某一個同學身上,這個事情變的更順了。
場景2:
研發1: 我有使用者服務的需求緊急我需要一個除錯環境。
研發2: 我和樓上一樣,我也有個緊急需求更改了使用者服務需要一個除錯環境。
研發3: 同上
一個服務需要並行開發並行測試,來看我們怎麼支援這種場景我們可以讓開發同學隨意建立自己的環境(但我們測試的k8s叢集資源是有限的),並且環境裡包含你需要更改的服務,依賴的專案無更改流量排程都是呼叫的QA基準環境,相當於虛擬了人手一個除錯環境,想怎麼改就怎麼改,每個人環境都是隔離的不會專案影響,滿足正常迭代。
場景3:
研發: 我要發線上,我需要先滾動一臺上線,看下監控,看下這次上線的業務日誌是否正常,正常了再灰度線上全量,或者流量大的時候,我需要一臺一臺灰度,避免流量不均勻。
場景4:
研發:突然我的使用者服務好像流量漲了之前的資源不滿足了,我需要擴資源或者今天晚上有一波活動使用者量會觸達200個W的人,我需要擴資源擴到10臺,每一臺4C8G,需要緊急擴容,我們可以直接更改每個服務的例項數,每個例項CPU核數和記憶體,直接灰度重啟生效,可能就2-3分鐘就弄完了。
場景5:
研發:我們需要設定環境變數區分環境,當然也是可以在我們系統中進行配置的。
經歷大概1年的時間以上很多問題都得到了友好的解決,關於發版本的這個事情上,基本上都是研發團隊自己能解決的事情,並且單元化之後,每個團隊負責的服務都不是太多,只要服務拆分的合理整體複雜度得到有效控制,再也不見當初研發團隊發版本的吐槽了。
拋開語言層面不說,整體的建設方向大概是這樣,只是看如何建設的符合大家的大環境。