非死book如何使用Haskell處理垃圾郵件

jopen 9年前發布 | 8K 次閱讀 Haskell

 

非死book使用一個名為Sigma的系統打擊垃圾郵件、惡意軟件及其它惡意行為。該系統的任務是主動發現這些行為,并自動刪除檢測到的不良內容,避免它們在用戶的動態消息中顯示。最近,他們完成了為期兩年的Sigma重新設計工作,用 Haskell 取代了僅在非死book內部使用的 FXL語言 。現在,基于Haskell的Sigma系統已經應用于生產環境,每秒為100多萬請求提供服務。對于像Sigma這樣的大型生產系統而言,Haskell不是一個常用的選項。Simon Marlow是一名非死book軟件工程師,同時也是Haskell社區的領軍人物。近日,他 撰文 解釋了他們做出這種選擇的原因,并分享了經驗。

Sigma是一個規則引擎,就是說它運行一組規則,非死book稱之為策略。Sigma會用那些規則評估非死book上的每次交互,以便識別和阻止惡意交互,防止它們影響非死book用戶。策略是持續部署的,任何時候,代碼庫中的源代碼都是Sigma中運行的代碼。這樣,它們可以對新出現的惡意行為作出快速響應。同時,這也要求他們用于編寫策略的語言是安全的。

起初,他們使用自己設計的FXL語言編寫策略,但隨著擴展性需求和復雜性的增加,FXL不再是理想的選擇。它缺少一些抽象機制,比如用戶定義類型和模塊,而且它的實現是以一個解釋器為基礎,速度不夠快。因此,他們希望選用一種現有的語言。下面是他們重點考慮的幾個因素:

  1. 純函數式強類型語言 :確保策略不會在無意間相互交互,可以單獨測試,并且不會導致Sigma系統崩潰;強類型有助于在策略部署到生產環境之前減少許多Bug;
  2. 自動批處理和并發獲取數據 :策略通常需要從非死book的其它系統獲取數據,為了提高效率,他們希望系統默認使用并發,即隱式并發;
  3. 在幾分鐘內將修改后的代碼推送到生產環境 ,即他們可以快速部署或更新策略;
  4. 性能 :FXL性能較差,他們需要使用C++開發一些對性能要求較高的功能,增加了變更發布時間;
  5. 支持交互式開發 :開發人員可以交互地試驗和測試策略代碼并立即看到結果。

Haskell非常適合:它是強類型的純函數式語言,有成熟的優化編譯器和交互式環境(GHCi),并且有他們需要的抽象機制。此外,它還有豐富的庫和活躍的開發者社區。因此,上述列表中還有兩項特性有待處理:

  • 自動批處理和并發 :在Haskell中,現有所有的并發抽象都是顯式的,就是說需要用戶自己指出什么應該并發。但他們希望有一個編程模型,使系統在可以并發的時候自動并發。為此,他們開發了Haxl框架。它可以使多個數據獲取操作自動批處理和并發執行。感興趣的讀者可以閱讀他們先前發表的 博文論文 以及查看其 GitHub頁面 。此外,他們還在GHC中實現了 Applicative do-notation
  • 已編譯代碼的熱切換 :他們希望任何提交到策略庫的新代碼盡快在每臺機器的Sigma fleet上運行。他們希望動態地在運行中的Sigma進程中更新已編譯的規則。修改正在運行的程序代碼非常困難,但他們的情況相對簡單:向Sigma發起的請求很短暫,所以他們不需要將一個正在運行的請求切換到新代碼,而是等待現有的請求結束,然后用新代碼為新請求提供服務。目前,他們使用GHC內置的運行時鏈接器加載和卸載代碼,而卸載舊版本代碼還要 用到垃圾收集器

Haskell位于Sigma中兩個C++層之間。上面一層是C++ thrift服務器。其實,這里也可以用Haskell作為thrift服務器,但C++ thrift服務器更成熟,性能更好,功能更豐富,并且可以與下面的Haskell層無縫集成,因為他們可以從C++調用Haskell。最底層是與外圍服務交互的C++客戶端代碼。他們使用Haskell的外部函數接口(FFI)將C++客戶端封裝成一個Haxl數據源,那樣,他們就可以從 Haskell使用它。

他們對Sigma所服務的25種常見類型的請求進行了測試。結果表明,對于特定的請求,Haskell的性能是FXL的3倍。Haskell的吞吐量整體上比FXL高20%到30%。為了,他們做了大量艱苦的工作,優化Haskell代碼,確定和解決性能瓶頸,其中包括 修改GHC的堆管理方式修復Haskell JSON解析框架aeson的一個性能缺陷 等。

此外,Simon還介紹了其它幾項重要的工作,包括:

  • 資源限制 :為了確保單個請求不因占用過多資源而導致其它請求的響應速度降低,他們在GHC中實現了 資源分配限制 ,設定一個線程在被動終止之前可以獲得的內存上限。
  • 交互式開發 :為了實現交互式開發,他們需要將GHCi環境與他們的整個技術棧集成,包括從命令行向其它后臺服務發送請求。為此,他們必須讓構建系統將代碼的所有 C++依賴都鏈接到一個GHCi可以加載的共享目錄。此外,他們還定制了GHCi前端,實現了部分自有命令,簡化了工作流程。
  • 打包和構建系統 :他們發現,托管在 Hackage 上的Haskell開源包變化非常快,而且并不是所有包組合都可以很好地工作。因此,使用這些包意味著更多繁瑣的工作。于是,他們切換到了 Stackage 。Stackage提供了已知可用的包的版本組合。

要了解更多信息,可以查看 Protect the Graph 頁面,或者觀看他們最近的 反垃圾郵件@Scale 活動視頻。

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