互聯網後端基礎設施

使用Java後端技術的目的就是構建業務應用,爲用戶提供在線或者離線服務。因此,一個業務應用需要哪些技術、依賴哪些基礎設施就決定了需要掌握的後端技術有哪些。縱觀整個互聯網技術體系再結合公司的目前狀況,筆者認爲必不可少或者非常關鍵的後端基礎技術/設施如下圖所示:

640?wx_fmt=png

 

這裏的後端基礎設施主要指的是應用在線上穩定運行需要依賴的關鍵組件或者服務。開發或者搭建好以上的後端基礎設施,一般情況下是能夠支撐很長一段時間內的業務的。此外,對於一個完整的架構來說,還有很多應用感知不到的系統基礎服務,如負載均衡、自動化部署、系統安全等,並沒有包含在本章的描述範圍內。

1. 統一請求入口-API網關

在移動APP的開發過程中,通常後端提供的接口需要以下功能的支持:

  • 負載均衡

  • API訪問權限控制

  • 用戶鑑權

一般的做法,使用Nginx做負載均衡,然後在每個業務應用裏做API接口的訪問權限控制和用戶鑑權,更優化一點的方式則是把後兩者做成公共類庫供所有業務調用。但從總體上來看,這三種特性都屬於業務的公共需求,更可取的方式則是集成到一起作爲一個服務,既可以動態地修改權限控制和鑑權機制,也可以減少每個業務集成這些機制的成本。這種服務就是API網關,可以選擇自己實現。也可以使用開源軟件實現,如Kong和Netflix Zuul。API網關一般架構如下圖所示:

640?wx_fmt=png

但是以上方案的一個問題是由於所有API請求都要經過網關,它很容易成爲系統的性能瓶頸。因此,可以採取的方案是:去掉API網關,讓業務應用直接對接統一認證中心,在基礎框架層面保證每個API調用都需要先通過統一認證中心的認證,這裏可以採取緩存認證結果的方式避免對統一認證中心產生過大的請求壓力。

2. 業務應用和後端基礎框架

業務應用分爲:在線業務應用和內部業務應用。

  • 在線業務應用:直接面向互聯網用戶的應用、接口等,典型的特點就是:請求量大、高併發、對故障的容忍度低。

  • 內部業務應用:主要面向公司內部用戶的應用。比如,內部數據管理平臺、廣告投放平臺等。相比起在線業務應用,其特點: 數據保密性高、壓力小、併發量小、允許故障的發生。

 

業務應用基於後端的基礎框架開發,針對Java後端來說,應該有以下幾個框架:

  • MVC框架:統一開發流程、提高開發效率、屏蔽一些關鍵細節的Web/後端框架。典型的如SpringMVC、Jersey以及國人開發的JFinal以及阿里的WebX。

  • IOC框架:實現依賴注入/控制反轉的框架。Java中最爲流行的Spring框架的核心就是IOC功能。

  • ORM框架:能夠屏蔽底層數據庫細節,提供統一的數據訪問接口的數據庫操作框架,額外地能夠支持客戶端主從、分庫、分表等分佈式特性。MyBatis是目前最爲流行的ORM框架。此外,Spring ORM中提供的JdbcTemplate也很不錯。當然,對於分庫分表、主從分離這些需求,一般就需要自己實現,開源的則有阿里的TDDL、噹噹的sharding-jdbc(從datasource層面解決了分庫分表、讀寫分離的問題,對應用透明、零侵入)。此外,爲了在服務層面統一解決分庫分表、讀寫分離、主備切換、緩存、故障恢復等問題,很多公司都是有自己的數據庫中間件的,比如阿里的Cobar、360的Atlas(基於MySQL-Proxy)、網易的DDB等;開源的則有MyCat(基於Cobar)和Kingshard,其中Kingshard已經有一定的線上使用規模。MySQL官方也提供了MySQL Proxy, 可以使用lua腳本自定義主從、讀寫分離、分區這些邏輯,但其性能較差,目前使用較少。

  • 緩存框架:對Redis、Memcached這些緩存軟件操作的統一封裝,能夠支持客戶端分佈式方案、主從等。一般使用Spring的RedisTemplate即可,也可以使用Jedis做自己的封裝,支持客戶端分佈式方案、主從等。

  • JavaEE應用性能檢測框架:對於線上的JavaEE應用,需要有一個統一的框架集成到每一個業務中檢測每一個請求、方法調用、JDBC連接、Redis連接等的耗時、狀態等。Jwebap是一個可以使用的性能檢測工具,但由於其已經很多年沒有更新,有可能的話建議基於此項目做二次開發。

一般來說,以上幾個框架即可以完成一個後端應用的雛形。

 

3. 緩存、數據庫、搜索引擎、消息隊列

緩存、數據庫、搜索引擎、消息隊列這四者都是應用依賴的後端基礎服務,他們的性能直接影響到了應用的整體性能,有時候你代碼寫的再好也許就是因爲這些服務導致應用性能無法提升上去。

  • 緩存:緩存通常被用來解決熱點數據的訪問問題,是提高數據查詢性能的強大武器。在高併發的後端應用中,將數據持久層的數據加載到緩存中,能夠隔離高併發請求與後端數據庫,避免數據庫被大量請求擊垮。目前常用的除了在內存中的本地緩存,比較普遍的集中緩存軟件有Memcached和Redis。其中Redis已經成爲最主流的緩存軟件。

  • 數據庫:數據庫可以說是後端應用最基本的基礎設施。基本上絕大多數業務數據都是持久化存儲在數據庫中的。主流的數據庫包括傳統的關係型數據庫(MySQL、PostgreSQL)以及最近幾年開始流行的NoSQL(MongoDB、HBase)。其中HBase是用於大數據領域的列數據庫,受限於其查詢性能,一般並不用來做業務數據庫。

  • 搜索引擎:搜索引擎是針對全文檢索以及數據各種維度查詢設計的軟件。目前用的比較多的開源軟件是Solr和Elasticsearch,都是基於Lucence來實現的,不同之處主要在於termIndex的存儲、分佈式架構的支持等。Elasticsearch由於對集羣的良好支持以及高性能的實現,已經逐漸成爲搜索引擎的主流開源方案。

  • 消息隊列:數據傳輸的一種方式就是通過消息隊列。目前用的比較普遍的消息隊列包括爲日誌設計的Kafka以及重事務的RabbitMQ等。在對消息丟失不是特別敏感且並不要求消息事務的場景下,選擇Kafka能夠獲得更高的性能;否則,RabbitMQ則是更好的選擇。此外,ZeroMQ則是一種實現消息隊列的網絡編程Pattern庫,位於Socket之上,MQ之下。

4. 文件存儲

不管是業務應用、依賴的後端服務還是其他的各種服務,最終還是要依賴於底層文件存儲的。通常來說,文件存儲需要滿足的特性有:可靠性、容災性、穩定性,即要保證存儲的數據不會輕易丟失,即使發生故障也能夠有回滾方案,也要保證高可用。在底層可以採用傳統的RAID作爲解決方案,再上一層,目前Hadoop的HDFS則是最爲普遍的分佈式文件存儲方案,當然還有NFS、Samba這種共享文件系統也提供了簡單的分佈式存儲的特性。

此外,如果文件存儲確實成爲了應用的瓶頸或者必須提高文件存儲的性能從而提升整個系統的性能時,那麼最爲直接和簡單的做法就是拋棄傳統機械硬盤,用SSD硬盤替代。像現在很多公司在解決業務性能問題的時候,最終的關鍵點往往就是SSD。這也是用錢換取時間和人力成本最直接和最有效的方式。在數據庫部分描述的SSDB就是對LevelDB封裝之後,利用SSD硬盤的特性的一種高性能KV數據庫。

至於HDFS,如果要使用上面的數據,是需要通過Hadoop的。類似xx on Yarn的一些技術就是將非Hadoop技術跑在HDFS上的解決方案。

 

5. 統一認證中心

統一認證中心,主要是對APP用戶、內部用戶、APP等的認證服務,包括:

  • 用戶的註冊、登錄驗證、Token鑑權

  • 內部信息系統用戶的管理和登錄鑑權

  • APP的管理,包括APP的secret生成,APP信息的驗證(如驗證接口簽名)等。

之所以需要統一認證中心,就是爲了能夠集中對這些所有APP都會用到的信息進行管理,也給所有應用提供統一的認證服務。尤其是在有很多業務需要共享用戶數據的時候,構建一個統一認證中心是非常必要的。此外,通過統一認證中心構建移動APP的單點登錄也是水到渠成的事情:模仿Web的機制,將認證後的信息加密存儲到本地存儲中供多個APP使用。

 

6. 單點登錄系統

目前很多大的在線Web網站都是有單點登錄系統的,通俗的來說就是只需要一次用戶登錄,就能夠進入多個業務應用(權限可以不相同),非常方便用戶的操作。而在移動互聯網公司中,內部的各種管理、信息系統甚至外部應用同樣也需要單點登錄系統。

目前,比較成熟的、用的最多的單點登錄系統應該是耶魯大學開源的CAS, 可以基於https://github.com/apereo/cas/tree/master/cas-server-webapp來定製開發的。

基本上,單點登錄的原理都類似下圖所示:

640?wx_fmt=jpeg

7. 統一配置中心

在Java後端應用中,一種讀寫配置比較通用的方式就是將配置文件寫在Propeties、YAML、HCON等文件中,修改的時候只需要更新文件重新部署即可,可以做到不牽扯代碼層面改動的目的。統一配置中心,則是基於這種方式之上的統一對所有業務或者基礎後端服務的相關配置文件進行管理的統一服務, 具有以下特性:

  • 能夠在線動態修改配置文件並生效

  • 配置文件可以區分環境(開發、測試、生產等)

  • 在Java中可以通過註解、XML配置的方式引入相關配置

百度開源的Disconf和攜程的Apollo是可以在生產環境使用的方案,也可以根據自己的需求開發自己的配置中心,一般選擇Zookeeper作爲配置存儲。

 

8. 服務治理框架

對於外部API調用或者客戶端對後端API的訪問,可以使用HTTP協議或者RESTful(當然也可以直接通過最原始的socket來調用)。但對於內部服務間的調用,一般都是通過RPC機制來調用的。目前主流的RPC協議有:

  • RMI

  • Hessian

  • Thrift

  • Dubbo

這些RPC協議各有優劣點,需要針對業務需求做出最好的選擇。

這樣,當你的系統服務在逐漸增多,RPC調用鏈越來越複雜,很多情況下,需要不停的更新文檔來維護這些調用關係。一個對這些服務進行管理的框架可以大大減少因此帶來的繁瑣的人力工作。

傳統的ESB(企業服務總線)本質就是一個服務治理方案,但ESB作爲一種proxy的角色存在於Client和Server之間,所有請求都需要經過ESB,使得ESB很容易成爲性能瓶頸。因此,基於傳統的ESB,更好的一種設計如下圖所示:

640?wx_fmt=jpeg

如圖,以配置中心爲樞紐,調用關係只存在於Client和提供服務的Server之間,就避免了傳統ESB的性能瓶頸問題。對於這種設計,ESB應該支持的特性如下:

  • 服務提供方的註冊、管理

  • 服務消費者的註冊、管理

  • 服務的版本管理、負載均衡、流量控制、服務降級、資源隔離

  • 服務的容錯、熔斷

阿里開源的Dubbo則對以上做了很好的實現,也是目前很多公司都在使用的方案;噹噹網的擴展項目Dubbox則在Dubbo之上加入了一些新特性。目前,Dubbo已經被阿里貢獻給Apache,處於incubating狀態。在運維監控方面,Dubbo本身提供了簡單的管理控制檯dubbo-admin和監控中心dubbo-monitor-simple。Github上的dubboclub/dubbokeeper則是在其之上開發的更爲強大的集管理與監控於一身的服務管理以及監控系統。

此外,Netflix的Eureka也提供了服務註冊發現的功能,其配合Ribbon可以實現服務的客戶端軟負載均衡,支持多種靈活的動態路由和負載均衡策略。

 

9. 統一調度中心

在很多業務中,定時調度是一個非常普遍的場景,比如定時去抓取數據、定時刷新訂單的狀態等。通常的做法就是針對各自的業務依賴Linux的Cron機制或者Java中的Quartz。統一調度中心則是對所有的調度任務進行管理,這樣能夠統一對調度集羣進行調優、擴展、任務管理等。Azkaban和Yahoo的Oozie是Hadoop的流式工作管理引擎,也可以作爲統一調度中心來使用。當然,你也可以使用Cron或者Quartz來實現自己的統一調度中心。

  • 根據Cron表達式調度任務

  • 動態修改、停止、刪除任務

  • 支持任務分片執行

  • 支持任務工作流:比如一個任務完成之後再執行下一個任務

  • 任務支持腳本、代碼、url等多種形式

  • 任務執行的日誌記錄、故障報警

對於Java的Quartz這裏需要說明一下:這個Quartz需要和Spring Quartz區分,後者是Spring對Quartz框架的簡單實現也是目前使用的最多的一種調度方式。但其並沒有做高可用集羣的支持。而Quartz雖然有集羣的支持,但是配置起來非常複雜。現在很多方案都是使用Zookeeper來實現Spring Quartz的分佈式集羣。

此外,噹噹網開源的elastic-job則在基礎的分佈式調度之上又加入了彈性資源利用等更爲強大的功能。

10. 統一日誌服務

日誌是開發過程必不可少的東西。打印日誌的時機、技巧是很能體現出工程師編碼水平的。畢竟,日誌是線上服務能夠定位、排查異常最爲直接的信息。

通常的,將日誌分散在各個業務中非常不方便對問題的管理和排查。統一日誌服務則使用單獨的日誌服務器記錄日誌,各個業務通過統一的日誌框架將日誌輸出到日誌服務器上。

可以通過實現Log4j或者Logback的Appender來實現統一日誌框架,然後通過RPC調用將日誌打印到日誌服務器上。

 

11. 數據基礎設施

數據是最近幾年非常火的一個領域。從《精益數據分析》到《增長黑客》,都是在強調數據的非凡作用。很多公司也都在通過數據推動產品設計、市場運營、研發等。這裏需要說明的一點是,只有當你的數據規模真的到了單機無法處理的規模才應該上大數據相關技術,千萬不要爲了大數據而大數據。很多情況下使用單機程序+MySQL就能解決的問題非得上Hadoop即浪費時間又浪費人力。

這裏需要補充一點的是,對於很多公司,尤其是離線業務並沒有那麼密集的公司,在很多情況下大數據集羣的資源是被浪費的。因此誕了 xx on Yarn 一系列技術讓非Hadoop系的技術可以利用大數據集羣的資源,能夠大大提高資源的利用率,如Docker on Yarn。

數據高速公路

接着上面講的統一日誌服務,其輸出的日誌最終是變成數據到數據高速公路上供後續的數據處理程序消費的。這中間的過程包括日誌的收集和傳輸。

  • 收集:統一日誌服務將日誌打印在日誌服務上之後,需要日誌收集機制將其集中起來。目前,常見的日誌收集方案有:Scribe、Chukwa、Kakfa和Flume。對比如下圖所示:

640?wx_fmt=png

    此外,Logstash也是一個可以選擇的日誌收集方案,不同於以上的是,它更傾向於數據的預處理,且配置簡單、清晰,經常以ELK(Elasticsearch + Logstash + Kibana)的架構用於運維場景中。

  • 傳輸:通過消息隊列將數據傳輸到數據處理服務中。對於日誌來說,通常選擇Kafka這個消息隊列即可。

此外,這裏還有一個關鍵的技術就是數據庫和數據倉庫間的數據同步問題,即將需要分析的數據從數據庫中同步到諸如Hive這種數據倉庫時使用的方案。可以使用Apache Sqoop進行基於時間戳的數據同步,此外,阿里開源的Canal實現了基於binlog增量同步,更加適合通用的同步場景,但是基於Canal還是需要做不少的業務開發工作。

離線數據分析

離線數據分析是可以有延遲的,一般針對的是非實時需求的數據分析工作,產生的也是延遲一天的報表。目前最常用的離線數據分析技術除了Hadoop還有Spark。相比Hadoop,Spark性能上有很大優勢,當然對硬件資源要求也高。其中,Hadoop中的Yarn作爲資源管理調度組件除了服務於MR還可以用於Spark(Spark on Yarn),Mesos則是另一種資源管理調度系統。

對於Hadoop,傳統的MR編寫很複雜,也不利於維護,可以選擇使用Hive來用SQL替代編寫MR。而對於Spark,也有類似Hive的Spark SQL。

此外,對於離線數據分析,還有一個很關鍵的就是數據傾斜問題。所謂數據傾斜指的是region數據分佈不均,造成有的結點負載很低,而有些卻負載很高,從而影響整體的性能。處理好數據傾斜問題對於數據處理是很關鍵的。

實時數據分析

相對於離線數據分析,實時數據分析也叫在線數據分析,針對的是對數據有實時要求的業務場景,如廣告結算、訂單結算等。目前,比較成熟的實時技術有Storm和Spark Streaming。相比起Storm,Spark Streaming其實本質上還是基於批量計算的。如果是對延遲很敏感的場景,還是應該使用Storm。除了這兩者,Flink則是最近很火的一個分佈式實時計算框架,其支持Exactly Once的語義,在大數據量下具有高吞吐低延遲的優勢,並且能夠很好的支持狀態管理和窗口統計,但其文檔、API管理平臺等都還需要完善。

實時數據處理一般情況下都是基於增量處理的,相對於離線來說並非可靠的,一旦出現故障(如集羣崩潰)或者數據處理失敗,是很難對數據恢復或者修復異常數據的。因此結合離線+實時是目前最普遍採用的數據處理方案。Lambda架構就是一個結合離線和實時數據處理的架構方案。

此外,實時數據分析中還有一個很常見的場景:多維數據實時分析,即能夠組合任意維度進行數據展示和分析。目前有兩種解決此問題的方案:ROLAP和MOLAP。

  • ROLAP:使用關係型數據庫或者擴展的關係型數據庫來管理數據倉庫數據,以Hive、Spark SQL、Presto爲代表。

  • MOLAP:基於數據立方體的多位存儲引擎,用空間換時間,把所有的分析情況都物化爲物理表或者視圖。以Druid、Pinot和Kylin爲代表,不同於ROLAP(Hive、Spark SQL), 其原生的支持多維的數據查詢。

如上一小節所述,ROLAP的方案大多數情況下用於離線數據分析,滿足不了實時的需求,因此MOLAP是多維數據實時分析的常用方案。對於其中常用的三個框架,對比如下:

. 使用場景 語言 協議 特點
Druid 實時處理分析 Java JSON 實時聚合
Pinot 實時處理分析 Java JSON 實時聚合
Kylin OLAP分析引擎 Java JDBC/OLAP 預處理、cache

其中,Druid相對比較輕量級,用的人較多,比較成熟。

數據即席分析

離線和實時數據分析產生的一些報表是給數據分析師、產品經理參考使用的,但是很多情況下,線上的程序並不能滿足這些需求方的需求。這時候就需要需求方自己對數據倉庫進行查詢統計。針對這些需求方,SQL上手容易、易描述等特點決定了其可能是一個最爲合適的方式。因此提供一個SQL的即席查詢工具能夠大大提高數據分析師、產品經理的工作效率。Presto、Impala、Hive都是這種工具。如果想進一步提供給需求方更加直觀的ui操作界面,可以搭建內部的Hue。

640?wx_fmt=jpeg

12. 故障監控

對於面向用戶的線上服務,發生故障是一件很嚴重的事情。因此,做好線上服務的故障檢測告警是一件非常重要的事情。可以將故障監控分爲以下兩個層面的監控:

  • 系統監控:主要指對主機的帶寬、CPU、內存、硬盤、IO等硬件資源的監控。可以使用Nagios、Cacti等開源軟件進行監控。目前,市面上也有很多第三方服務能夠提供對於主機資源的監控,如監控寶等。對於分佈式服務集羣(如Hadoop、Storm、Kafka、Flume等集羣)的監控則可以使用Ganglia。此外,小米開源的OpenFalcon也很不錯,涵蓋了系統監控、JVM監控、應用監控等,也支持自定義的監控機制。

  • 業務監控:是在主機資源層面以上的監控,比如APP的PV、UV數據異常、交易失敗等。需要業務中加入相關的監控代碼,比如在異常拋出的地方,加一段日誌記錄。

監控還有一個關鍵的步驟就是告警。告警的方式有很多種:郵件、IM、短信等。考慮到故障的重要性不同、告警的合理性、便於定位問題等因素,有以下建議:

  • 告警日誌要記錄發生故障的機器ID,尤其是在集羣服務中,如果沒有記錄機器ID,那麼對於後續的問題定位會很困難。

  • 要對告警做聚合,不要每一個故障都單獨進行告警,這樣會對工程師造成極大的困擾。

  • 要對告警做等級劃分,不能對所有告警都做同樣的優先級處理。

  • 使用微信做爲告警軟件,能夠在節省短信成本的情況下,保證告警的到達率。

故障告警之後,那麼最最關鍵的就是應對了。對於創業公司來說,24小時待命是必備的素質,當遇到告警的時候,需要儘快對故障做出反應,找到問題所在,並能在可控時間內解決問題。對於故障問題的排查,基本上都是依賴於日誌的。只要日誌打的合理,一般情況下是能夠很快定位到問題所在的,但是如果是分佈式服務,並且日誌數據量特別大的情況下,如何定位日誌就成爲了難題。這裏有幾個方案:

  • 建立ELK(Elasticsearch + Logstash + Kibana)日誌集中分析平臺,便於快速搜索、定位日誌。搭配Yelp開源的Elastalert可以實現告警功能。

  • 建立分佈式請求追蹤系統(也可以叫全鏈路監測系統),對於分佈式系統尤是微服務架構,能夠極大的方便在海量調用中快速定位並收集單個異常請求信息,也能快速定位一條請求鏈路的性能瓶頸。唯品會的Mercury、阿里的鷹眼、新浪的WatchMan、Twitter開源的Zipkin基本都是基於Google的Dapper論文而來,大衆點評的實時應用監控平臺CAT則在支持分佈式請求追蹤(代碼侵入式)的基礎上加入了細粒度的調用性能數據統計。此外,Apache正在孵化中的HTrace則是針對大的分佈式系統諸如HDFS文件系統、HBase存儲引擎而設計的分佈式追蹤方案。而如果你的微服務實現使用了Spring Cloud,那麼Spring Cloud Sleuth則是最佳的分佈式跟蹤方案。還需要提到的是,Apache孵化中的SkyWalking是基於分佈式追蹤的一個完備的APM(應用性能監測)系統,其最大的一個特點就是基於Java agent + instrument api,對業務代碼無任何侵入,Pinpoint則是類似的另一個已經用於生產環境的APM系統。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章