使用Akka、Kafka和ElasticSearch等構建分析引擎

在這篇文章里,我將和大家分享一下我用Scala、Akka、Play、Kafka和ElasticSearch等構建大型分布式、容錯、可擴展的分析引擎的經驗。

我的分析引擎主要是用于文本分析的。輸入有結構化的、非結構化的和半結構化的數據,我們會用 分析引擎 對數據進行大量處理。如下圖所示為第一代架構,分析引擎可以用REST客戶端或Web客戶端(引擎內置)訪問。

簡單描述一下用到的技術:

  • Play框架 做REST服務器和WEB應用。Play是個基于輕量級、無狀態和WEB友好的MVC框架。
  • Akka集群 作處理引擎。Akka是個工具集,用于在JVM上簡化編寫高并發、分布式、和有彈性的消息驅動應用。
  • ClusterClient 用于與Akka集群通信。它運行在REST服務器上,將任務發給Akka集群。使用ClusterClient是一個非常錯誤的決定,因為它并不會維持與Akka集群的長連接,因而會經常報連接錯誤,而且重新建立連接時還要把那個Client所在的JVM也一起重啟。
  • ElasticSearch 用作查詢引擎和數據存儲,包括原始數據和分析結果。
  • Kibana 用作可視化平臺。Kibana是有彈性的分析和可視化平臺。
  • Akka Actor 用作ElasticSearch的數據導入導出服務。它的表現非常好,服務從來沒出過故障。
  • S3 用作集中化文件存儲。
  • Elastic Load Balance 用作節點之間的負載均衡。
  • MySQL 用于元數據存儲。

我們從Akka 2.2.x版開始用起,也碰到了一些嚴重問題,主要表現為:

  • ClusterClient與Akka集群之間連接斷開 :在負載大CPU使用率高時,ClusterClient常常莫名其妙的與Akka集群斷開連接。因為它是個第三方庫,所以我們只好把JVM重啟來讓它繼續工作,有的時候還要半夜爬起來處理問題。
  • 資源利用率 :我們發現REST服務器上CPU使用率只有2-5%,這樣太浪費資源了,Amazon EC2服務器可不便宜。
  • 延遲問題 :REST服務器運行在不同的服務器上。這樣就造成了延遲問題,因為對于每一條Client發過來的請求,它都要把請求反序列化,再序列化然后才能發到Akka集群。從Akka集群發來的響應消息也是一樣,要先反序列化再序列化,然后才能發給請求方。這樣的序列化和反序列化過程常常導致超時問題。而且,我們只是把Play用作REST后臺而不是完整的WEB框架,我承認這是我們的設計問題。

為了解決這些問題我們設計了 第二代架構 ,主要變化有:

  • 去掉Akka ClusterClient。
  • Spray 替換掉Play架構,因為把Play用作REST服務不是個正確的決定。Spray是個輕量級HTTP服務器。
  • 為了減少端到端的延遲,我們把REST服務運行在Akka集群節點所在的JVM上,而不是單獨的節點上。

新架構是這樣的:

太棒了,這樣的系統工作得非常好。生活又變得非常美好,團隊也得到了很多表揚。

三個月后,來了個要增加Datasift做為數據源的新需求,提供流數據和歷史數據。這個需求好滿足,只要增加一個新服務,從 Datasift 中拉取數據并發送到分析集群上即可。

 

增加新服務很簡單,但卻導致了新問題:

  • 上述架構本質上來說是個推送模型,每當有大量的流或歷史數據被推送過來時,集群就會處理不過來。
  • 我們決定把集群由4個節點擴展為8個節點。這樣峰值情況下還可以,但正常情況下大多數節點都處于非常空閑的狀態。我們用的是Amazon EC2 4x.Large節點,非常貴,所以就引發出了 基礎設施的費用問題
  • 我們決定使用Amazon的自動擴容服務。在集群上負載增加時它的確是自動擴容了,可是負載降下來時它卻沒有縮容。Amazon自動擴容服務對我們的業務情況處理得不夠好。
  • 另一個問題是Akka集群的內部節點通信在CPU使用率超過90%時常常出問題,原因可能是因為我們經驗不夠不會配Akka集群,也有可能是Akka集群那時候不象現在這么成熟。
  • 如果有節點崩潰的話,那整個處理過程就會停止。

當我們在努力為這個問題找解決方案時,又收到需求要再增加一種數據源!

在經過很多次頭腦風暴之后,我們明白了現有架構的問題,于是做出了一個簡單、可擴展和容錯的 第三代架構

在這個新架構里,我們去掉了Akka集群,重寫了分析引擎。它完全是基于Akka Actor的,REST服務也是運行在相同的JVM上。REST服務只是簡單的從客戶端接收請求,做認證和鑒權,然后創建一條待處理消息發送到Kafka隊列中去。分析引擎的每個節點都會從Kafka隊列中拉取數據,處理完畢再拉取下一批。這樣它就永遠不會忙不過來。

受益于Kafka的內部機制,不管哪個節點死掉了,Kafka都會自動的把要處理的消息發送到另一個正常節點上,所以不會有任何消息丟失。

在這個架構下我們就不必繼續租用以前的Amazon EC2 4X large服務器了,只要用Amazon EC2 2X large就可以支持任何負載,節省了很多錢。(此處應有掌聲。:) )

這完全是個基于 拉取模式 的架構。所有的請求和浪涌 都通過Kafka集群處理。它永遠不會忙不過來,因為所有操作都是基于拉取模式的。整個系統部署在 26臺EC2節點 上,已經快兩年了,生產系統一次故障都沒出過。

我們也用Kafka保存了各種服務日志來分析性能、安全和用戶行為。Kafka生產者會把日志發送到Kafka服務器中。因為我們已經有了ElasticSearch的導入導出服務,我們可以仍然用它們來推送ElasticSearch的日志。我們也可以輕松地用Kibana將用戶行為可視化。

結論

  • Akka Actors非常適合于打造高并發、分布式、有彈性的應用程序。
  • Spray非常適合作輕量級HTTP服務器。現在它已改名為 Akka-HTTP
  • Play框架 非常適合于構建高并發、可擴展的WEB應用,它底層是Akka。
  • ElasticSearch 是個非常好的搜索引擎,它底層是Lucene,可以提供全文檢索功能。盡管我們也把它當成數據存儲來用,但數據持久化并不是它的強項(比如與Cassandra相比)。
  • Kafka非常適合于流處理和日志匯聚。它的架構設計就已經支持可擴展、分布式、容錯等功能。

請耐心等待我改進第四版架構之后再更新這篇文章吧……快樂編程,不斷創新!

 

來自:http://www.infoq.com/cn/articles/use-akka-kafka--build-analysis-engine

 

 本文由用戶 mwly8182 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!