搜狗商業平臺Java技術實踐

Java自1995年問世以來,已歷經20多年歲月。20年來,IT技術風起云涌,Java始終以其可移植性、跨平臺性、生態系統完備性等特點成為最主流的開發語言之一。事實上,Java無處不在,已經滲入到大家的日常生活中,從你的每一次購物到每一筆支付,都有Java技術的身影,國內外的主流網站大部分都是由Java技術支撐。

搜狗商業平臺負責搜狗廣告業務,涵蓋搜索、網盟、無線、品牌等業務線,面向幾十萬廣告主和廣告代理商,提供十億級以上在線廣告管理及相關支持,提供近百億的在線報告。其中,基于Java的業務系統在70%以上。從底層緩存、會話、調度、通信交互,到提供給客戶的API接口,從數據庫訪問、離線大規模數據處理到實時計算,都依托于Java技術。在我們內部長期的實踐過程中,Java技術已經逐步自發地形成了一個生態系統。

Java生態圈非常龐大而豐富,我們在長期的實踐過程中,自主或基于Java開源組件進行二次開發和優化,構建了搜狗商業平臺完整的Java技術框架,如圖1所示。

圖1搜狗商業平臺Java技術棧

在基礎組件層,我們直接使用了一些業界著名的框架和類庫,比如IoC框架Spring、日志Log4J等;同時也基于一些框架進行了二次開發,比如基于Redis提供了分布式會話和分布式緩存,有效地解決單機內存及I/O瓶頸問題。在數據存儲層,我們數據存儲主要使用關系數據庫MySQL、文檔數據庫MongoDB、分布式存儲HDFS以及自行研發的DFS文件系統。在數據訪問層,基于MySQL數據庫和MongoDB數據庫,分別提供了一套分庫分表框架,使得其支持海量數據存儲,同時也分別提供了ORM框架,使得能夠很容易地完成數據庫中的數據到對象的映射。在數據計算層,離線計算方案主要使用了HadoopMapReduce框架,流式計算方案主要使用了Kafka和Storm。在接口交互層,提供了三種框架,分別支持Thrift、WebServices和HTTP/JSON三種交互方式。在基礎服務層,提供了認證、授權、配置、分布式任務調度、消息、圖片、短信和郵件等多種基礎服務。

下面分別介紹我們在數據庫分庫分表框架、分布式任務調度平臺和分布式RPC框架上的實踐。

數據庫分庫分表框架:Compass

互聯網領域針對大數據存儲,基于NoSQL的數據庫越來越多,然而,在一致性、事務性、可靠性等方面,特別是在較復雜的業務場景中,關系數據庫仍起著不可替代的作用。在關系數據庫領域,MySQL數據庫基本上主導了市場。然而,互聯網面臨著用戶多、數據量大等的挑戰,一組MySQL數據庫集群無法支撐如此大的PV及I/O,因此對單表的數據量以及每臺機器的數據分布需要做一定的預估。在我們的實踐中,對于單表的數據量有一些約束。一般說來,對于定長的記錄,單表數據量最好不超過800W,極限不超過1000W;對于不定長記錄,單表數據量最好不超過500W,極限不超過800W,否則在較復雜的業務場景中,可能會引起性能下降。

對于大規模數據的存儲和訪問,一般都采用分庫分表的方案解決。主流互聯網公司都提供了各自的解決方案,比如淘寶分布式數據層TDDL、百度Dbproxy等。我們也研發了數據庫分庫分表框架Compass,支持和滿足內部的一些需求。

一般來說,數據庫分布分表框架的設計有兩種方案:獨立中間件層方式和嵌入式應用框架方式。獨立中間件層方式采用獨立的部署,后端數據庫對應用程序是透明的,其擴容對應用的可用性不會有明顯的影響。嵌入式應用框架方式是獨立的類庫,應用需要顯式地配置后端的單個或者多個數據庫。獨立中間件層方式的開發和維護成本都較高,且多了一層網絡開銷;嵌入式應用框架方式數據庫配置較為復雜一些,但其開發維護成本低,并且對單元化架構的支持也不錯,因此Compass選用了嵌入式應用框架方式。

圖2分布分表框架Compass架構圖

Compass系統架構如圖2所示?;∈菰床憧梢匝∮每吹氖菘飭映胤槳?,比如包括C3P0、Proxool、TomcatJDBC、DBCP等。在我們的實踐中主要使用C3P0。代理數據源層主要負責數據庫分庫分表的處理,包括分庫數據源、主從數據源、心跳監控和管理接口四大???。

分庫數據源和主從數據源都實現了Java中標準的javax.sql.DataSource接口,提供基于Spring注解的配置方式,對應用屏蔽底層數據源的差異,從而簡化應用配置及應用在不同數據源之間遷移(包括普通數據源遷移至主從數據源、主從數據源遷移至分庫數據源),降低數據庫擴容成本。由于采用標準的javax.sql.DataSource接口,在JDBC封裝層支持方面,我們目前可以兼容業界大部分的ORM框架,比如Hibernate、Mybatis、iBatis和JDBC等。同時由于采用對DataSource層進行分區路由,因此對于依賴javax.sql.DataSource接口的框架或應用均無影響。

分庫數據源中包含路由選擇器。路由選擇器可以通過自定義路由選擇策略選擇合適的底層數據源,并將獲取數據庫連接的請求代理到此底層數據源。路由選擇策略可通過多種方式實現:1.取模;2.分段;3.Hash;4.特殊路由策略等。在我們的實踐中主要是對客戶的物料進行管理,路由選擇策略是通過客戶ID取模實現,同時針對個別大客戶使用特殊路由策略的方式,從而保證表中數據的均衡性。

對于每次獲取數據庫連接的請求,主從數據源根據當前的事務屬性等上下文相關信息以及自身可用的底層數據庫連接池信息,返回底層數據源的連接。它主要包括主從選擇和代理連接。主從選擇可以支持讀寫分離、支持多從單主模式,并支持自定義反主從延時策略,更好地保證主從庫數據的一致性;在負載均衡方面,我們除了支持內置的隨機、權重、輪詢、響應時間等負載均衡策略外,還支持自定義擴展負載均衡策略。代理連接主要是提供了一系列的策略對SQL進行攔截,完成分表等功能。在SQL解析與替換方面,目前我們內置了供如MyBatis之類的ORM框架的SQL占位符替換基于SQL語法樹解析的SQL結構替換等方式,還支持自定義擴展解析和替換策略。在主從選擇擇中,反主從延時策略是解決主從延遲可選插件,它是通過將一段訪問時間內的讀請求路由到主庫上來完成的,目前可以基于常見的分布式緩存和內存方式提供反主從延遲標記的管理,并支持自定義擴展。

心跳監控主要對底層數據源的健康性進行監控。一般說來,底層數據源連接池都已經提供了心跳監控,例如C3P0能夠監控數據庫連接是否有效,檢查數據庫空閑連接以及數據庫是否有效,并提供了一系列的策略來處理上述問題;然而,主從數據源以及分庫數據源(特別的)需要對底層的數據源的數據庫連接以及數據庫是否可用進行監控,并在底層數據源不可用時提供策略進行處理(例如:對主從選擇策略中的參數進行調整)。因此,數據源代理層仍需對底層數據源進行監控,并根據底層數據源是否可用進行選庫或者負載均衡策略上的調整。同時心跳監控中也支持故障移除、故障恢復等功能,并能針對不同的數據庫類型進行自定義監控擴展,并支持一定的JMX監控接口監控數據庫連接池(C3P0/DBCP/Proxool等,支持自定義擴展),可以更好地監控其運行狀況。

管理接口主要提供訪問次數(讀寫)以及執行時間、數據庫連接數(活躍、空閑等狀態)的監控管理,并通過JMX、Thrift等手段暴露服務。

數據聚合層提供了數據聚合可選插件,目前支持繼承已實現聚合的JdbcTemplate進行全庫聚合和操作,并可采用多線程方式提高數據訪問效率。

元信息收集層主要提供了一系列的工具收集主從選擇的標識、反延時標識、路由選擇標識,提供給代理數據源層的路由選擇器和主從選擇器進行路由選擇和主從選擇。

當然,Compass中間件在分布式數據庫事務(在事務管理方面,我們繼續沿用Spring事務管理機制,保證同庫事務性)、跨節點join問題上依然沒有很好的處理方法,在跨節點count/orderby/groupby等聚合問題上的實現也有待更優雅的支持。特別是針對全庫聚合或者查詢,其線程資源和內存資源占用都相對較高。這也是任何數據庫中間層解決方案都未能完全解決的事情,只能依賴于在業務上進行精巧的設計,盡量避免這些問題。

此外,Compass分庫分表框架也大大提升了易用性:


  • 最小代碼侵入:內置路由標識(Envidence)默認策略,不改變上層ORM框架實現;

  • 簡化配置:在配置中采用了大量的默認策略和機制,使得配置達到最簡單;

  • 最小接入成本:支持與目前現有的數據庫訪問框架并存,支持逐個數據庫集群灰度切換。目前,Compass中間件已經接入了所有業務線應用,無論是從功能還是性能,與業界數據庫中間件均保持統一水準,在易用性方面更是極大地簡化了數據源配置和降低代碼侵入,很好地支撐了目前10+億級的物料存儲和管理。


分布式任務調度平臺:凌云

隨著業務的發展,各開發團隊經常需要編寫大量定時任務來進行相關的業務處理,如導入導出數據、報表計算、匯總統計等。最常見的定時任務可通過Linux系統中的Crontab來在指定時間點觸發任務執行。然而,隨著任務量逐漸增多,基于Crontab的任務管理方式存在諸多弊端:


  1. 任務配置管理成本較高。每增加或修改一個任務,都需要修改Crontab,增加人力管理成本;

  2. 無法支持任務依賴。Crontab不支持任務間依賴;

  3. 手工配置出錯風險高。手動修改Crontab缺少正確性校驗機制,有一定出錯風險;

  4. 不支持任務可視化。Crontab任務只能通過Linux終端查看,沒有統一的管理界面查看任務詳情及歷史運行記錄;

  5. 存在單點風險。任務每次觸發后只能在一臺機器上執行,若機器故障,任務將無法執行;

  6. 監控不完善。Crontab任務失敗后,需要為任務單獨增加相應的監控。


為此,我們研發了搜狗分布式任務調度平臺:凌云,將各種類型的任務統一到該平臺進行配置和管理,并支持以下特性:


  • 將任務的管理、調度與執行解耦合;

  • 任務調度節點和任務執行節點可水平擴展,避免單點;

  • 各任務隔離執行,獨立平滑上線,互不影響;

  • 支持復雜任務依賴,一個任務可有多個前驅和多個后繼;

  • 任務失敗自動報警、任務超時自動報警。


圖3凌云分布式任務調度平臺

其架構如圖3所示。任務執行節點(TaskNode)是執行任務的服務器集合,這些服務器可劃分為多個域,域主要保證不同業務間的隔離性。每個任務都需要指定所屬的域,任務觸發后,將會分配給其所屬域中的一臺服務器執行。任務執行節點負責具體任務的執行,每個任務執行節點上部署著一個任務代理(基于Thrift的HTTP服務),用于與調度集群交互并啟動子進程執行具體任務。任務分為Java任務和Shell腳本任務(其中Hadoop任務屬于一種Shell腳本任務),兩者都是以子進程的形式由任務代理啟動。

任務代理與任務調度集群的交互主要包括接收任務分發請求、處理任務狀態輪詢請求、任務結束后回調任務調度集群等。任務代理通過獲取任務子進程的退出碼判斷任務是否正常結束,退出碼0表示正常完成任務,非0表示出現異常,任務代理會將退出碼返回給任務調度集群。

任務調度集群底層基于Quartz集群模式。Quartz是由Java編寫的強大的企業級任務調度框架,提供了非常好的伸縮性、高可用性及負載均衡機制。我們在Quartz的基礎上進行了擴展,支持任務的定時觸發、依賴執行、失敗重試及異常報警等。任務調度集群提供基于Thrift的HTTP服務,包括兩方面功能:1.對任務管理中心開放任務管理和調度的相關接口,管理員對任務的調度配置會更新到任務調度集群中;2.對任務代理開放任務狀態回調接口,任務在執行節點上運行完畢后,任務代理會通過此接口回調調度器告知其任務的運行結果。

任務的依賴執行可以非常方便地實現任務之間的前后順序銜接,尤其是對于存在跨組數據依賴的情形,通過配置任務之間的依賴關系,即可實現數據獲取的及時性和有效性。

用戶可在任務管理中心維護任務之間的依賴關系,當任務的所有前驅任務執行完畢后,會自動觸發該任務的執行。假設有如圖4的任務依賴關系,任務C有兩個前驅,分別是任務A和B,任務D的前驅任務是任務B,任務E、F的前驅任務是任務C。則沿時間軸方向,任務B先執行完畢,會自動觸發其后繼任務D開始執行;當任務A執行完畢后,會自動觸發任務C開始執行;任務C執行完畢后,會自動觸發E和F執行。

圖4任務依賴關系

由于分離了任務調度與執行,調度器需要知道任務狀態,并在必要的時候觸發重試或者報警。我們采用了任務結果回調和任務狀態輪詢兩種方式。正常情況下,任務執行完畢后,任務代理根據任務子進程的退出狀態碼確定任務是否執行成功,然后將任務執行情況通過回調的方式返回給調度集群。但考慮到可能存在任務成功完成但任務代理回調失敗的情況,我們增加了調度器對任務狀態的輪詢策略,即對于運行中的任務,調度器輪詢處理節點該任務的狀態,以確保任務成功與否能及時反饋給調度器。通過輪詢,對于耗時超出預期執行時間的任務,調度器會發出任務超時報警。

任務管理中心是一個對任務可視化管理平臺,用戶可登錄此系統查看并管理自己的任務。具體包括任務管理、觸發器管理、參數管理、依賴管理,任務配置項包括任務的基本屬性、執行時間的觸發器、任務的參數等。也可以直接在管理中心立即啟動執行指定任務。系統按角色劃分權限,不同角色的用戶擁有不同的權限。此外,任務管理中心采用分布式會話,可以進行集群部署,提高了容災能力。

目前,搜狗分布式任務調度平臺承載著絕大多數任務調度工作。通過將任務的管理、調度與執行解耦合,減少了三者之間的互相侵入;通過提供豐富的任務配置屬性和任務可視化展現,極大提高了任務管理效率;通過提供任務遠程調度、任務隔離執行、任務平滑上線、任務多依賴等特性,很好地支撐了各產品線業務的發展。

分布式RPC框架:Polaris

在長期的業務發展過程中,對于系統間的交互,我們使用了Socket、RMI、Hessian、JSON等技術,針對每種技術,都需要維護一套相應的故障轉移、故障恢復、追蹤框架,對于商業平臺多條業務線的大量系統交互來說,經常面臨著硬件故障問題,此種交互方式引起的維護成本及故障遷移成本都是巨大的。另外,多種不同的接口技術也面臨著接口兼容性的問題,例如對于RMI來說,我們就遇到了Spring從2.5.6升級到3.1.0所帶來的RMI接口不兼容導致的接口調用錯誤問題。最后,我們內部也有一些跨語言的調用需求,比如用C++查詢廣告物料信息、Python腳本做統計,這些都會涉及到接口調用,而使用不能跨語言的技術(例如RMI和Hessian)成本會非常高。因此,我們需要統一內部系統接口交互方式,并降低接口的管理和維護成本。

在實踐過程中,我們比較了WebService、ProtocolBuffer、HTTP/JSON、Dubbo以及Thrift等技術。其中,WebService基于XML,兼容性良好,但其序列化/反序列化性能較差;ProtocolBuffer和HTTP/JSON無服務接口/地址描述;Dubbo的框架過于龐大;Thrift在接口定義文檔、數據類型支持、跨語言等方面存在優勢,然而對服務地址和服務管理方面支持力度不夠,并且存在類型侵入問題。在分析比較之后,我們選定了Thrift,并在此基礎上開發了服務注冊中心,解決服務地址和服務管理方面的問題。對于類型侵入問題,從描述語言來看,長遠來看它生成的POJO代碼應該可以像WebService一樣,消除類型侵入(例如,Facebook提供了開源的Swift框架,已經朝這個方向邁進了一步)。我們目前是提供了一系列的方法和轉換類,自主進行類型轉換適配工作。

我們基于Thrift構建的分布式RPC框架Polaris如圖5所示。

 

圖 5 分布式RPC框架Polaris 

我們對Polaris的服務端和客戶端都進行了增強。在服務器端,我們提供了標準的HTTP服務器,能夠很輕易地將一個Thrift服務發布到一個URL上。同時,也集成了標準的認證和授權框架,有效地保證了業務的安全性;另外,我們在運維監控方面做了很多增強,能夠監控每個方法的執行時間以及執行參數,這樣的話可以面向整個商業平臺,建立標準的監控統計架構。因為我們提供的服務是基于HTTP的,因此部分統計是可以直接沿用線上已有的監控統計軟件,也有效減少了重新構建監控框架的成本。

在客戶端,主要添加了失敗重試、提供了類RPC的調用方式,并且提供了一種抽象的機制簡化了測試成本。通過Spring的依賴注入,可以支持在僅調整配置,不改變客戶端代碼的情況下進行本地調用和遠程HTTP調用的切換。使用本地調用時可以更快地進行單元測試,在完成單元測試之后,可以直接通過調整配置切換成遠程HTTP調用,在此過程中無需任何代碼的調整。此方案還對接口遷移,比如從RMI接口遷移至Thrift接口提供了很大的幫助。一般情況下,大型復雜依賴系統內部接口間的依賴關系都會特別復雜,在進行接口梳理和遷移時成本和風險都非常高,特別是在系統的服務化改造過程中需要將內部接口提升為API接口的時候。在這種情況下,可以通過引入一個Thrift???,將此??橐覽滌諦枰嶸狝PI接口的???,而其他??樵蚪鲆覽滌詿薚hrift???。在此調整過程中,可以隨著業務版本的開發同步進行,而且可以重用大部分單元測試稍作調整即可使用,這樣的話能夠將成本和風險都降至最低。

事實上,Thrift有標準的定義語言,能夠對服務接口、異常、接口參數和返回值進行描述,同時支持Set、Map之類的數據結構。然而,它沒有描述服務地址以及服務依賴關系等。因此,我們也構建了服務中心Aura,它的概念架構圖6所示。

 

圖6 服務中心Aura概念架構圖 

圖6中的通信框架服務端和通信框架客戶端已經在前面介紹了。服務中心的主要功能是對Thrift接口描述語言文件進行管理,管理其發布/訂閱關系。實際上,它定義了一種團隊間互相協作的方法,此協作遵循面向服務體系結構。在開發實踐中,我們不鼓勵依賴通過接口描述語言直接生成的代碼,鼓勵依賴于接口描述語言生成代碼,這樣能夠保證耦合性,減少代碼升級所帶來的成本。另外,通過管理服務的所有者和服務的訂閱者,能夠迅速地了解到服務間的依賴關系以及服務演化時所帶來的相關影響。

在商業平臺內部有多個業務系統使用分布式RPC框架Polaris,包括資金、計費、客戶、財務、合同、物料、報告等,也覆蓋了Java、C++、Python等語言,目前已經完成大部分接口的遷移,利用服務中心Aura,構建了完善的服務發布、發現和使用的流程,也針對其安全性、易用性和可維護性做了很多工作,因為有了一致的技術集,連怎么去使用都有了最佳實踐,遷移后的服務接口顯著減少了重復開發成本,有效地提升了溝通效率,降低了風險。

總結

在長期的實踐中,我們一直基于Java技術,致力于解決分布式、高并發、大數據量、強一致性等帶來的各種技術難題及挑戰。同時,我們也致力于基礎組件和框架的統一化,構建和持續優化基礎架構、基礎服務,保證高可靠、高性能、高可擴展性、低成本的快速支撐各項新業務,保證業務的高速發展。在此過程中,Java及其生態系統有效地進行了支撐,成為了搜狗商業平臺Java生態系統的基石,顯著降低了開發和維護成本,提高了可維護性和系統健壯性。

來源:CSDN

上一篇: 2016最流行的Java EE服務器

下一篇: 為何 Java EE 是更好的選擇

分享到: 更多
11选5计划软件 十一 皇冠彩票网一现金投注 打麻将的规则介绍 pk10计划软件秒速版 分分彩平刷一天 天津时时彩开奖结果 判断长龙 时时彩平台排名 全天北京pk10冠军计划 元游棋牌手机斗地主 内蒙古时时综合走势图 可以提现看牌抢庄拼十 有天津时时的平台 多赢快3计划 360票新时时 三码二肖