人人車業務平臺從最初典型的LNMP單機單服務部署架構,發展到現在分佈式服務化架構,五百多臺虛擬機部署,一路走來,踩過很多坑,也遇到過很多挑戰,特別是對於基於雲服務進行業務開發的場景,以及從零開始服務化與SOA之路更是很有心得,但願經過這次分享全面回顧人人車業務平臺技術架構發展之路,重點分享以下內容:mysql
- 創業初期技術架構選型思考,那些年咱們趟過的坑,雲服務與三方服務使用心得;
- O2O型互聯網創業公司,重線下團隊技術型公司,技術架構優化之路,分享咱們人人車是如何作服務拆分、如何作服務化、如何作SOA、如何作DB慢SQL優化等;
- 人人車HTTP服務管理框架介紹相關使用經驗分享;
- 人人車業務平臺技術架構規劃;
人人車是由一幫百度兄弟們,於 2014年4月成立,做爲二手車C2C模式獨創者,以及典型的O2O二手車互聯網電商企業, 創業兩年多,目前業務範圍已經覆蓋全國數十個城市了,今年年末將覆蓋到過百城市。sql
咱們業務平臺負責所有核心業務系統研發工做,包括:CRM系統、發佈系統、編輯系統、評估系統、銷售系統,金融支付等業務系統,承擔人人車全部線下業務團隊收車、賣車等核心環節技術支持!數據庫
好了,接下來,就進入到今天的第一個話題,分享下咱們創業初期的技術架構和技術選型思考。json
創業初期技術架構選型思考
爲了快速開發迭代,初期人人車業務平臺全部服務所有基於LNMP進行搭建,從前到後一套系統,2臺雲主機機器,很是簡單清晰,V 0.1版本架構以下圖所示:後端
從上圖能夠看出創業初期咱們的V0.1版本的技術架構很是簡單,主要基於一下幾點考慮:api
- 研發資源的限制,咱們必須集中精力作最重要的事情,業務需求知足是第一位的;
- 產品快速迭代的須要,創業初期整個技術團隊技術能力成熟度不高,所以咱們更是傾向簡單、清晰、研發熟練度高的技術框架;
- 初期業務規模較小,技術架構需求較低,簡單框架徹底能夠知足業務需求,適合業務需求的架構就是好架構;
- 輕量級LNMP框架,選擇足夠簡單靈活的PHP CI框架, 雲MySQL RDS服務,簡單易上手,運維部署成本很是低,大大節省了咱們運維成本,以及開發人員的學習成本;
爲了可以快速搭建服務把創業項目搞上線,咱們以前一直堅持的幾個原則也跟你們分享下:緩存
- 大量使用雲服務,包括:虛擬機、DB、MQ中間件、Redis等基礎服務,大大下降了這些技術能力要求高的基礎主件、存儲服務、消息中間件等服務的部署運維代價;其實就是:花錢買服務,花錢買時間,花錢買研發能力;
- 大量使用第三方收費服務,以代價換時間,例如:Teambition服務、BDP報表服務、ODPS數據管理、圖片存儲服務、語音通話服務等等;
- 權衡自研系統與三方採購系統代價,對於非核心業務系統,若是能經過採購知足需求,就快速採購服務,應用到一線業務中去,例如:HR系統、OA系統、培訓系統、雲報銷系統、工做流引擎等等;
- 擁抱開源,GitHub是個金礦,值得每一位創業者去挖掘,去發現本身的需求,其實不少同行已經作了咱們要作的基礎研發事情;
- O2O創業項目,線下業務系統是第一位的,全部資源」all in」 去提高線下團隊工做效率,優化線下業務系統流程,提高線索轉化漏斗,提升轉化率;
- 低頻冷門電商業務,口碑推廣,營銷推廣,廣告投放,SEM等都是須要精細運營的,是流量運營最重要的幾個關鍵點;
雖然咱們堅持了上面提到的不少原則,不經意間咱們仍是踩了不少坑,例如:安全
- 雲服務不靠譜,出問題形成雪崩,致使整個站點不可用。這塊個人經驗是不能把整個站點的生死寄託在別人手中,必定要多給本身留個B計劃,容災方案無論是公司發展到哪一步都須要的;雲服務做爲基礎服務在作架構部署時,必定要多考慮幾家互爲容災備份;
- 第三方服務在使用時,必定要與本身業務服務解耦,能簡單封裝一個proxy代理層那就最好了,避免直接嵌套第三方SDK到業務代碼中,這樣就至關於跟第三方捆綁在一條船上了,友誼的小船說翻就翻啊;
- 核心系統容災,核心系統在選擇第三方服務時,必定要多挑選幾個合做夥伴,系統架構上,最好能支持容災切換,在一個第三方服務出問題時,可以快速進行切換,避免將核心系統生死權掌握到第三方服務上去。例如咱們人人車是一個重電銷型公司,呼叫中心就是咱們的核心,這套系統以前咱們設計初期就僅僅只支持一家供應商,致使後面只要合做夥伴出問題,咱們就跟着掛了,很是很是的被動;真是不怕神同樣的對手,就怕豬同樣的隊友啊!
- 重視DB設計,這個問題,可能在初期你們以爲MySQL DB數據庫表能夠隨便設計,表的字段個數,字段類型都影響不大,其實初期嚴格把關DB設計,後期就會少填不少坑,咱們曾經有個大json_data字段,歷史緣由設計不友好,致使咱們花了2年時間才把這個字段拆掉,真的是很是痛苦的經歷;
人人車業務平臺技術架構優化之路
隨着咱們業務不斷髮展,線下團隊出現了爆炸性的增加,銷售、評估師、客服人員等都增加不止一個量級,咱們的車輛數、訂單量、客服量等都是飛速增加,同時因爲前期主要關注產品需求,而對技術架構的優化工做相對滯後,致使這個階段咱們業務系統問題不斷,這使得咱們陷入了很是被動的局面。架構
這種背景下,咱們意識到必需要緩一緩業務需求開發了,不能再一直堆代碼了,咱們須要進行重構須要梳理咱們以前的系統架構,所以這纔有了咱們全面梳理人人車業務系統架構與系統重構這項工做,但願重點從技術架構合理性上去梳理現有系統!
回頭你們能夠反觀當時這個階段咱們的技術架構,我叫它爲V0.2版本架構,以下圖所示:
相對於1年前的V0.1版技術架構,此時整個業務端架構,作了部分系統拆分,可是這種拆分僅僅是代碼層面的複製,從新建立出了不少業務模塊,而真正的底層DB、數據庫表、緩存等都仍是未進行拆分的;
因爲全部業務都使用一個業務DB庫,所以DB成了整個業務的單點與雷區,隨時可能被引爆,同時因爲業務複雜度的不斷增大,DB慢查詢也不斷涌現,DB鏈接數、CPU、IOPS等核心資源都出現了競爭與爭搶,只要一個業務系統出問題,則全部服務都將受影響,出現雪崩效應,正是因爲這些問題使得咱們業務進展愈來愈艱難!
在啓動服務架構優化項目以前,咱們首先從以下兩個方面進行梳理,全面診斷咱們系統架構存在的問題:
一、流程規範與運維部署問題梳理:
- 所有服務部署在2臺雲主機,高度耦合,相互影響,資源競爭;
- 發佈方式原始,svn check、scp覆蓋;
- 回滾流程與工具缺失,遇到問題回滾不方便、回滾不徹底;
- 上線流程不規範,無通報相關機制、無回滾預案;
- 上線後迴歸驗證方法不全面,不易肯定功能是否完整;
二、服務耦合與服務拆分梳理:
- 全部項目copy自car_publish這個項目,大量冗餘代碼,框架使用不純淨;
- 通用庫、工具、類未能複用,未提取部署到統一路徑獨立部署維護;
- API分層邏輯不嚴格,跨層、躍層調用現象明顯,業務調用出口不統一,不便於後續維護;
- 項目耦合太緊密,未按功能進行服務化拆分,服務調用關係混亂,難以管理;
- Cache層缺失,缺乏核心邏輯緩存加速,系統有時響應緩慢;
- DB數據庫耦合嚴重,未按業務獨立拆分,部分字段設計不合理包含大JSON、長字段、慢查詢;
- 日誌打印不規範,關鍵路徑日誌缺失,日誌文件切分與清理機制缺乏
- 接口級別監控缺乏,超時、流量變化等業務級別監控缺乏;
爲了解決上面分析的問題,咱們從以下幾個方面重點跟進,對人人車業務平臺進行有史一來最大的一次優化重構,涉及到:服務拆分、運維部署流程優化、服務監控、DB拆分、慢SQL 優化、同步轉異步等事項。
一、服務拆分
從上面分析能夠看出,現有系統最大問題,就是各模塊之間耦合過高,模塊之間依賴過重,所以咱們首先啓動的項目,就是服務拆分,從服務部署上物理拆分開,避免一個模塊出問題形成整個業務系統雪崩。
服務拆分的核心原則以下:
- 各模塊Git代碼層面獨立管理與維護
- 線上獨立SLB、獨立部署、獨立運維
- DB層面數據隔離,獨立從庫
- 通用功能抽取到API層
- 核心業務邏輯增長cache層
經過以上的拆分工做,咱們的服務部署架構變成以下圖所示,各個模塊獨立部署,經過SLB進行負載均衡,從物理部署上將服務拆分開來。
二、DB慢查詢優化,咱們從以下幾個方面着手:
第一,天天經過SQL工具分析出top 5慢查詢,要求研發同窗必須完成優化,將慢查詢優化做爲例行事項,天天去review,到後期咱們規範化慢SQL排查流程,從以下幾個維度分析周級別慢SQL:執行耗時、掃描行數、返回行數等條件,綜合分析出高優先級SQL提交給研發同窗參考優化;
第二,DB讀寫分離,全部讀請求切換到從庫,同時各個服務按優先級使用不一樣從庫,這樣主庫只剩下更新操做,基本能夠杜絕大部分慢SQL,經過慢SQL天天分析報告能夠清楚看到須要重點優化的問題SQL;
第三,對於DB輪詢操做相關業務邏輯優化,調整輪詢爲通知機制,下降程序輪詢給DB帶來的壓力,經過更新通知機制保證數據實時通知到業務方,再經過 API查詢詳細數據,減小各業務模塊對主庫的直接SQL查詢;
第四,增強SQL審覈,全部上線SQL,都必須經過SQL審覈才能夠到線上DB執行,以前因爲業務迭代過快,線上DB運維與權限把控不夠,致使研發同窗直接線上操做DB, 各類慢SQL層出不窮;
第五,增強DB表設計review ,全部對線上數據庫DDL相關操做,都必須經過線上DB schema審覈纔可執行;對於DB設計咱們一樣概括出統一的 mysql DB設計規範,全部線上設計都必須知足規範纔可執行!
人人車DB Schema規範以下:
- 全部數據庫的DDL操做所有收回,由OP統一管理;
- 每張表/視圖要有註釋(comment),格式爲 模塊|用途|負責人|建立日期 ,例如:貸款|記錄貸款用戶身份證號碼|張三|2016-03-25;
- 每一個字段要有註釋(comment),格式爲 用途|負責人|建立日期 , 例如:記錄用戶性別@1:男@0:女@2:未知|李四|2016-03-25;
- 每張表三個必加字段,id (自動增加), create_time , update_time 用做存儲主鍵,記錄建立時間,記錄更新時間 , 這三個字段由OP維護,RD無需處理;
- 有邏輯刪除需求的表,可選增長delete_flag字段(int類型,默認值爲0),用來標識字段是否被邏輯刪除;
- 收回RD的delete權限,全部數據不能作物理刪除(邏輯上刪除的需求能夠經過flag標籤的方式來處理);
- 字段來源須要說明,來自哪張表的那個字段,例如:記錄車輛ID,#取自cp_used_car.car_id|李四|2016-03-25;
- 若是字段爲枚舉類型,或普通數據類型當作枚舉使用,須要列舉枚舉範圍並說明每一個枚舉值的含義,例如:記錄用戶性別,#系統根據用戶身份證號碼判斷@1:男@0:女@2:未知|李四|2016-03-25 ( | 用來分割不一樣項目 , # 用來標識數據來源 ,@ 用來分割多個枚舉 ,: 用來分割枚舉名稱和值 , 正常的描述中不要包含 | # @ :)
三、DB拆分:
因爲前期業務相對簡單,全部業務數據所有集中存放在一個DB裏面,這樣致使重要數據與普通日誌數據都混在一個庫中,各業務模塊數據也所有落在一個庫中,致使業務主庫壓力過大,隨時可能由於一條SQL致使的DB問題,將整我的人車業務平臺都給拖垮,所以DB拆分對於咱們來講,也迫在眉睫。
咱們執行DB拆分的核心原則以下:
- 各實體分庫分表設計
- DB主從拆分
- 數據加密杜絕明文存儲
- 表與DB設計:必須遵循人人車DB設計規範與schema設計規範
- 索引設計:合理使用索引,杜絕濫用索引
爲了可以更好的兼容以前的系統,作到平滑遷移,減小對業務系統的影響,在作DB拆分時,咱們首先對業務系統進行實體拆分,再抽取API,對於業務方只須要將以前SQL查詢方式遷移到API調用便可。
基於人人車業務實際場景,咱們將以前的DB庫拆分爲以下實體:
- Json_data 數據拆分 (解決DB 中json_data字段內容過大形成性能問題而拆分)
- Car 實體抽取
- User 實體抽取
- Order 實體抽取
- Clue 實體抽取
對於咱們最核心的car車輛實體拆分,基本是將以前主庫中一個核心表與json_data所有從新拆開設計的,由原來的一張表擴展到以下圖所示的實體設計:
人人車服務化與SOA架構
1、服務化與SOA架構:
在咱們作完服務部署架構拆分後,服務化與SOA架構規劃其實已經排上了日程,咱們作服務化與SOA架構主要出於如下考慮:
一、業務平臺視角
- 多樣的需求直達 (業務端各種系統需求的知足)
- 一致的用戶體驗 (用戶使用與行爲習慣的延續,減小培訓成本)
- 快速迭代 (各子系統、業務線只關注自有特性開發、專人專事,避免「重複造輪子」)
- 資源的最有效利用 (便於人力資源、軟硬件資源的高效共用與複用)
- 系統穩定性與服務質量的提高
- 問題避免與定位、解決速度的提高
二、公司全局視角
- SOA與服務化架構的探索
- 公司級服務化框架的試點與應用
- 技術積累與沉澱的須要,研發人員技能提高的必由之路
- 打造高效O2O線上、線下平臺的基石
- 提高研發效率、下降研發成本的利劍
人人車服務化架構設計的核心指標以下表所示:
對於人人車來講,服務化架構是必行之路,前期的高度耦合的技術架構,已經在很大程度上制約整個公司業務的發展,對於產品需求,響應速度愈來愈慢,需求堆積愈來愈多,業務抱怨也愈來愈大!
所以咱們對現有技術團隊作了簡單的組織架構調整,單獨抽取精幹力量,搭建專門負責服務化的基礎架構團隊,開始啓動人人車服務化架構之路,咱們主要從以下幾個方面着手開展工做的:
- 現有系統功能劃分與子系統梳理;
- DB層拆分:各子系統DB獨立,解耦下降依賴;
- 全部子系統、應用間的交互都要經過服務的方式來進行,不容許其餘方式如:讀庫、同步腳步、搭建私服、跨層調用等;
- 全部子系統、應用,都以服務的方式將其數據與功能開放出來,經過API的形式提供訪問;
- 服務的實現方式,初期以現有的HTTP協議爲準,後續擴展到RPC、自定義協議等;
經過上面這一系列的優化重構,人人車業務平臺技術架構終於站到了 V1.0版本,以下圖所示:
從上圖咱們能夠看到,咱們的V1.0版本系統架構,基本達到以下效果:
- 服務已經徹底拆分開,模塊化與組件化也初步創建;
- 產出多個基礎服務如:基於zookeeper的通用配置管理服務、通用反做弊服務、通用驗證碼服務等;
- 產出一批執行規範:通用錯誤碼規範、通用日誌管理規範、MySQL規範、PHP編碼規範等;
- 對於一些通用庫與通用配置,也完成拆分,單獨經過Git項目進行管理,建立comm libs, comm configs等多個通用配置與代碼庫。
能夠說這一階段,是咱們人人車業務研發團隊最艱難的階段,一樣也是你們收穫最大的階段,從零開始,咱們全程見證了本身的服務,從開始的混亂不堪,逐步變成規範與穩定,每一步拆分,每個優化,其實都凝聚着全部業務平臺研發同窗的無限心血!
經過服務化相關項目的推動,咱們在項目研發過程當中,發現以前的研發流程與研發思路也須要進行調整與轉變,主要表如今以下幾點:
轉變須要解決的主要問題
- 從簡單「堆代碼」實現業務需求,到模塊化開發「堆積木」知足需求;
- 從簡單代碼copy,到模塊服務化與基礎庫沉澱,便於後續各種系統快速開發;
轉變的關鍵點
- 通用流程業務的抽象;
- 核心流程的拆分與解耦 (服務、子系統、模塊級別拆分);
- 服務的可定製 -> SAAS;
- 服務的可插拔 -> SOA;
2、人人車HTTP微服務管理框架:
在作服務化過程當中,咱們基於實體拆分,抽取了多個實體API服務,爲了可以統一管理這些HTTP API,咱們提取了統一的服務接入層,對咱們全部http-api進行管理,經過統一的微服務管理框架,實現以下核心功能:
- 統一的API接入層:全部業務實體拆分後對應API所有接入到服務管理框架,實現對外接口統一,對內統一管理;
- 統一的權限管理與鑑權:能夠實現多種API訪問的權限管理,如:jwt、OAuth 2.0、IP白名單機制等等;
- 統一的API分析與管理:經過WEB上實現服務註冊,簡單配置下,便可實現服務路由、API分析、流量控制、服務容災、failover等通用功能;
- 統一的API監控與統計:統一實行qps統計、日誌、監控、openfalcon打通上報數據等功能;
- 採用Nginx+lua的模式,功能模塊採用lua可靈活擴展,基於Nginx實現達到高性能與高可靠,在最上層實現功能需求,減小對業務的侵入與性能的損耗;
人人車微服務管理框架,架構圖以下:
人人車業務平臺微服務管理框架,基於開源OpenResty框架進行搭建,經過Lua腳本進行功能擴展,實現個性化需求,全部 HTTP請求調用所有經過微服務管理框架,由框架進行路由、鑑權等功能;
因爲微服務管理的請求都是無狀態的HTTP請求,所以在微服務框架層面能夠靈活的擴展,避免單點問題。對於一些核心業務,咱們甚至能夠靈活的從物理層面獨立部署微服務管理框架,從而隔離各個核心模塊之間的相互影響。
3、人人車V2.0版本架構:
雖然人人車業務平臺V1.0的架構,階段性的知足了快速發展的業務需求,可是從技術架構角度看,仍是存在諸多問題的,例如:
- 跨層調用大量存在;
- API化不夠完全;
- DB拆分仍不完整;
- HTTP服務缺少統一管理,缺乏統一的服務治理框架;
- 對於HTTP服務全部模塊鑑權、安全、監控等都有大量重複工做。
所以,在2016年上半年咱們花了大概小半年的時間,經過進行上面提到的的SOA與服務化,HTTP api統一接入層的加入, 微服務管理框架的加入等一系列工做,終於將人人車業務平臺技術架構再次往前推動一步到V2.0版架構,V2.0架構圖以下所示:
人人車業務平臺技術架構規劃
對於下一步人人車業務平臺技術架構的走向,整體規劃以下圖所示:
歸納的講,咱們將重點關注服務穩定性、異地容災、數據存儲隔離、基礎服務組件化、通用業務模塊化、持續集成、運維與安全協同等方面,重點跟進以下幾點:
- 基礎支撐項目服務化與組件化:重點跟進呼叫平臺化、派單服務化、CRM平臺化、配置服務化、反做弊通用服務、驗證碼服務化等基礎業務支撐項目;
- 基礎運維與安全:協同OP一塊兒構建更加方便靈活的運維安全體系,對整我的人車業務平臺全部服務進行安全護航;
- 持續集成支撐:協同QA團隊一塊兒打造從Git提交代碼開始的自動化流程,包括:自動化測試,自動化發佈,自動化迴歸驗證等核心指標;
- 前端架構分離與服務化:協同FE團隊一塊兒打造服務化的前端架構,完全作到先後端分離,真正實現先後端數據隔離,進一步打造人人車本身的前端開發組件和框架;
- 數據存儲隔離:協同DBA團隊一塊兒構建人人車業務系統數據訪問層,對於底層DB真正作到業務隔離與上層透明,加強DB數據安全性;
- 異地容災支撐系統:基於各家雲服務提供商,構建人人車自有資源定位層,實行各雲服務商之間災備,同時經過自建proxy服務方式,實現自建服務與雲服務之間的災備功能;
- 服務質量評價體系創建:基於現有的業務系統,構建統一的服務質量評價體系,可以實現各服務缺陷管理、穩定性度量、穩定性評價指標統一監控等功能;