法國新總統馬卡龍的IT之路,看他的開源Web平台架構
本案例的研究是由EnMarche Project的首席工程師兼產品負責人Titouan Galopin撰寫的客座講話。 請注意,這是一個嚴格的技術文章;任何政治評論都會被自動刪除。
項目背景
2016年4月,現任法國總統 Emmanuel Macron(埃曼紐爾·馬克倫)創立了一個名為「En Marche!」的政治運動。 (英文名為「On the Move」),最初是作為上門對民眾詢問的這麼一個運動,主要的詢問內容是法國當前存在的問題。
不同於既定的政黨,En Marche 沒有任何的基礎設施,預算和支持其事業的成員。 這就是為什麼En Marche 從一開始就依靠互聯網的力量來尋求支持者,推廣活動和募集捐款。
2016年10月,我作為志願者開始為En Marche 工作。剛開始的團隊很小,所有的IT操作都是由一個人維持。 所以他們高興地接受了我想幫助他們的提議。 那時候,這個平台是用WordPress創建的,但是我們需要用一些允許更快、更個性化的開發方法來取代它。 所以就選擇了Symfony:它適合當前項目的規模,而且我有使用經驗,可以輕鬆處理我們現有的大量用戶。
架構概述
可擴展性是該項目首要考慮的要素,特別是在他們面臨該平台的第一版的問題之後,此時還未使用Symfony構建平台。 下圖顯示了項目架構的概述,該架構在需要具有極強的可擴展性和冗餘:
我們使用Google Container Engine和Kubernetes來提供可擴展性,滾動更新和負載平衡。
Symfony應用程序是作為Dockerized應用程序從底層構建的。配置使用環境變數,應用程序是只讀的,以保持其可擴展性:我們不會在運行時容器中生成任何文件。 應用程序高速緩存在構建Docker鏡像時生成,然後使用與Redis實例結合的Symfony Cache component伺服器之間進行同步。
由兩名RabbitMQ管理的工作人員在後台處理一些繁重的操作:發送電子郵件(有時我們必須在單個請求中發送45k個電子郵件),並構建應用程序的幾個部分使用的序列化JSON用戶列表,避免處理緩慢和複雜的SQL查詢。
該資料庫使用Google Cloud SQL,這是我們不必親自管理的集中式MySQL資料庫。我們使用Cloud SQL代理Docker鏡像來連接到它。
部署
?
該項目使用持續交付策略,這與連續部署(Continuous Deployment)方法不同:每次提交自動部署在臨時伺服器上,但生產部署是手動的。 Google Container Engine和Kubernetes是我們部署流程的關鍵組件。
連續交付流程、單元和功能測試都由CircleCI處理。 我們還使用StyleCI(以確保新代碼與項目其餘部分的編碼風格相匹配)和SensioLabsInsight(執行自動代碼質量分析)。 這三個服務被配置為每個Pull請求在合并之前必須通過的檢查。
當Pull請求合并時,連續傳送過程開始(見配置文件):
使用Circle CI環境變數在Google Cloud上進行身份驗證。
構建用於生產的Javascript文件。
構建項目的三個Docker鏡像(應用程序,郵件工作者,用戶列表工作者)。
將內置鏡像推送到Google Container Registry。
使用kubectl命令行工具更新登台伺服器(滾動更新)。
手動執行的唯一過程是SQL遷移。 即使可以自動化操作,我們更傾向於在應用這些遷移之前仔細檢查這些遷移,以防止嚴重的生產錯誤。
前端
應用程序前端不遵循單頁應用程序模式。 事實上,我們希望儘可能少的使用JavaScript來提高性能並依靠本地瀏覽器功能。
React + Webpack
JavaScript應用程序的代碼是由Webpack編寫的React來實現的。 我們不使用Redux - 甚至React-Router - 而是使用純粹的React代碼,我們僅在頁面上的特定作用域中載入組件,而不是使用它們構建整個頁面。 這有兩個原因:
在React載入之前,HTML內容被完全渲染,然後React根據需要修改頁面內容。 這使得應用程序在沒有JavaScript的情況下可以運行,即使頁面仍然在慢速網路上載入。 這種技術被稱為「漸進增強」,它顯著地提高了感知性能。
我們使用Webpack 2進行tree shaking和chunks載入,所以每個頁面的組件只在需要時載入,因此不會使最小化的應用程序代碼膨脹。
這種技術使我們組織前端代碼如下:
應用程序的根目錄前端/目錄存放所有的SASS和JavaScript文件。
微型kernel.js文件並行載入JavaScript和應用程序代碼。
app.js文件用於載入不同的應用程序組件。
在Twig模板中,我們載入每個頁面所需的組件(例如,地址自動完成組件)。
前端性能
前端性能往往被忽視,但網路通常是應用程序的最大瓶頸。 在後端保存幾毫秒不會佔用太多的時間,但為圖像保存3秒或更長的載入時間將會影響網站的體驗效果。
圖像是主要的前端性能問題。 市場活動經理希望發布大量圖像,但用戶想要快速載入。解決此問題的方案是使用強大的壓縮演算法並應用其他技巧。
首先,我們將圖像內容存儲在Google Cloud Storage及其元數據中(使用名為Media的Doctrine實體)。例如, 允許我們不需要載入就能知道圖像尺寸。 這有助於在創建一個網頁設計,圖像載入時不會跳轉。
其次,我們將Media實體日期與Glide庫結合起來實現:
上下文圖像調整大小:例如,顯示在主頁上的小網格塊上的圖像可以比顯示為主要文章圖像的相同圖像小得多,解析度更低。
更好的圖像壓縮:所有圖像都被編碼為jpegs格式。 與其他格式(如PNG)相比,明顯減少了載入時間。
在 AssetController 中引入了一個簡單的端點,並使用了簽名和緩存來減少對此端點的 DDoS 攻擊。
第三,在滾動載入圖像時需要一些技巧,遵循三步驟:
在滾動時儘可能快地載入上方的所有元素,並等待下面的元素。
載入超低解析度版本(使用Glide生成),並使用本地JavaScript代碼為圖片做gaussian blur filter(高斯模糊濾鏡)處理。
當載入高質量的圖像時,更換這些模糊的佔位符。
我們實現了一個應用範圍廣泛的Javascript listener(JavaScript監聽器),用於網站的各個地方。
Forms(表單)
該項目用了一些有趣的表單。 第一個是註冊網站:根據國家和郵政編碼欄位,城市欄位從輸入文本更改為下拉選擇列表。
技術上有兩個欄位:「cityName」和「city」(第二個是根據法國規定分配給城市的代碼)。 窗體組件正常從請求中填充這兩個欄位。
在視圖方面,最初僅顯示cityName欄位。 如果所選國家是法國,我們使用一些JavaScript腳本來顯示城市的選擇列表。 JavaScript還可以偵聽郵政編碼欄位的更改事件,並發出AJAX請求以獲取相關城市列表。 在伺服器端,如果所選國家是法國,我們需要提供城市代碼,否則我們使用cityName欄位。
這個技術是本文前面討論的漸進增強技術的一個很好的例子。 JavaScript使整個項目的體驗更好,但對整體功能不起決定性作用。
由於這些地址欄位在應用程序中被大量調用,我們將其抽象為與地址Javascript組件關聯的 AddressType form type(AddressType表單類型。)
另一個是有趣的表單是發郵件給一個試圖說服他們投票給候選人。 這是一個多級的表單,詢問有關其他人(性別,年齡,工作類型,興趣愛好等)的一些問題,然後生成可通過電子郵件發送的定製內容。
在技術上,該表格結合了一個高度動態的Symfony Form與Workflow組件。 該實現基於InvitationProcessor模型類,由多級和動態表單類型填充,並將內容存儲在會話中。 Workflow組件用於確保模型對象有效,定義每個模型狀態允許的轉換:請參閱InvitationProcessorHandler和workflows.yml config。
搜索引擎
由Algolia提供的搜索引擎,具有速度快、搜索結果實時性強。 使用AlgoliaSearchBundle對應用實體(文章,頁面,委員會,事件等)進行索引的整合。
這個捆綁是非常有用的。 我們剛剛向Doctrine實體添加了一些注釋,之後,每當創建,更新或刪除實體時,搜索索引都會自動更新。 從技術上講,捆綁包監聽了Doctrine事件,因此不需要擔心搜索內容的是否為最新的問題。
安全
跟其它網站一樣,我們的站點也成為某些組織攻擊的目標。且大多都是暴力攻擊,其目的是將網站關閉而不是攻破。
該網站遭受過DDoS攻擊,其中五次在最後兩周內。 它們對Symfony應用程序沒有影響,因為Cloudflare緩解和基於Kubernetes的按需擴展性。
首先,我們遭受了基於WordPress pingback的三次攻擊。 攻擊者使用數千個被黑客攻擊的WordPress網站將pingback請求發送到我們的網站,迅速重載。 我們在nginx配置中添加了一些檢查來減輕這種攻擊。
其他攻擊更加複雜,Cloudflare和Varnish都需要減緩攻擊。 使用Cloudfare來緩存資源是非常有效的,我們認為沒必要使用反向代理。 然而,在DDoS攻擊中被證明需要一個反向代理:在這個運動的最後幾天,攻擊是巨大的(每秒可能達到30萬個請求),我們不得不禁用用戶系統並啟用Cloudfare上的「Cache Everything」。
我們不能阻止安全攻擊,但可以通過遵循Symfony的最佳做法來減輕它們,順便說一下,這是具有公共安全審計的少數開源項目之一。
開源
在 @EnMarche github 帳戶中,已公開了.enEnmarche.fr平台及其相關項目。 不過,我們並沒有推廣這個想法,因為開源對於非技術人員來說是非常複雜的。然而,我們收到了一些人的貢獻,並且很高興將它開源。
我們也在考慮通過為項目開發一些元素來回饋給Symfony。 例如,UnitedNationsCountryType表單類型可能對某些項目很有用。 我們還開發了與Mailjet服務的集成,可以作為Symfony捆綁包發布。
點擊展開全文
※深度學習,先跟上再說
※驚呆了,使用空格縮進的開發者比使用Tab的薪水高很多
※父親節,技術人不應放棄對那些編程語言之父的愛
※朋友,真正的程序員到底應該是什麼樣子的?
※編譯和解釋的區別在哪?
TAG:CSDN |
※微軟開源之路:近鄰搜索演算法SPTAG開源啦
※架構之爭,MIPS走上開源道路!
※MIPS CPU架構宣布開源:龍芯的機會來了
※龍芯的好機會:MIPS CPU架構完全開源
※RISC-V 危矣?MIPS 走上開源道路
※開源RISC-V架構正在改變IoT處理器的遊戲規則
※硬碟大佬也玩CPU!西部數據公布RISC-V自研架構SweRV及開源指令集模擬器
※LG宣布開源webOS
※OURS譚章熹:開源RISC-V指令架構與AI晶元
※GOSINT:開源智能(OSINT)方面較新的一款工具
※陳天奇的tvm更新了:VTA,開源AI晶元棧
※對話 CTO〡和 PingCAP CTO 黃東旭聊開源資料庫新藍海
※beego開源之路
※DejaVU:開源蜜罐框架;PHP 0e 開頭的魔法 Hash 列表
※IBM開源POWER指令集,國產高性能CPU迎來新機遇?
※IssueHunt:一個新的開源軟體打賞平台
※Facebook 最新開源框架 PyRobot,開闢 AI 機器人研究新紀元
※介紹開源IaaS開源平台
※中國大學MOOC+項目開源
※IBM 重磅開源 Power 晶元指令集!國產芯迎來新機遇?