flask-compress 和JSON壓縮

weixin_33670713發表於2018-11-10

    年初我還在寫Java,一轉頭,已經寫了一段時間的Python了 :)。 讓程式設計師吵起來的話:“PHP是最好的語言”,我老闆表示不服,說我進組晚,最好的語言是Perl,最好的IDE是Visual Studio。 我能說什麼呢? 我可不打算和老闆吵架。嗯, 最好的語言是Java。

9402357-4eff61ad77c9bec3.jpeg
清空我的求生欲

    也不知道老闆會不會看我的文章,鄭重宣告:上面的表情包純屬搞笑效果,老闆說什麼我都是認真聽的!從來沒有裝模作樣!

    好了好了,說正經的。

=====不正經分界線=====

    最近工作中遇到的一個小問題(小問題我都得寫一寫,就是這麼一個雞毛的女人!),前端要載入的JSON資料重達6M左右,開啟Chrome的控制檯,就能看到在一個請求中,狀態已經變成200了,但仍然要10s+ 去載入這麼重的資料,於是,在給老闆演示基於原生程式碼的效果的時候,就有幾十秒的靜默時間。嗯……慢到我想給老闆表演胸口碎大石(沒有)。

9402357-ddb44185e7557404.jpg
來啊~

    描述一下場景條件:

        1. 前端顯示資料為幾百K

        2. 前端實際載入了超過5M資料(有別用,不細說)

        3. 伺服器在國外,瀏覽器在國內

    針對於上述問題,要採取JSON壓縮的方式提高效能。網上給出兩種策略: 1. 使用flask-compress 2.配置Nigix。 下面我們先來看一下flask-compress的使用。

    寫一個小小的模擬例子。 鑑於是在本地,網路傳輸很快,所以首先把Chrome 控制檯Network的offline設定為Fast 3G,來模擬一個比較限制的網速,如下圖:

9402357-7ce7376aeccc89e8.png
限速

    然後下面是基本程式碼:

    前端: 點選按鈕請求後端資料,只顯示‘content_to_show’

    後端:讀取一個大小為5M的檔案內容,為‘content_not_show’,並和‘content_to_show’包成JSON返回(今天看了《毒液》,嘻嘻)

9402357-5520a4c3e33c2fc8.png
前端
9402357-55ddd182df38be39.png
後端

    點選按鈕,看一下Chrome的記錄,28.34s載入了5M資料。

9402357-3b6773facb188409.png
無壓縮訪問結果

    看一下Waterfall,可見Content Download花了27.78s,幾乎可以說是網速限制了一切。日常生活中,這不是網的錯,是我的,誰讓我沒有辦理光纖入戶呢?

9402357-8e8422b13d3532b4.png
無壓縮waterfall

    然後呢,我們開啟flask-compress的開關,傳送愛心 ,biubiu~

9402357-0bd60998dce6f556.jpeg

    這是README: https://github.com/jmcarp/flask-compress/blob/master/README.md

    步驟超級簡單: 1. 開啟冰箱,2. 把大象塞進去,3. 關上冰箱門

9402357-3526183a31f0e647.jpeg
嗯?

        哦,走錯片場了。

        重來。步驟很簡單:

        1. 安裝flask-compress

        2. import flask-compress

        3. compress app

        下面是使用flask-compress的程式碼,加兩行,好很多~

9402357-ef1ff9446fd409cc.png
壓縮後端程式碼

    然後我們再看一下效果,Size變成了5.4K,時間為毫秒級。很滿意有沒有!!

9402357-74cb32344bc4f66b.png
壓縮結果1

  再看看Waterfall,可喜可賀~

9402357-b57366a6bcd7fee8.png
壓縮的waterfall

    下面讓我們對比一下response的引數,左邊是壓縮的,右邊的是不壓縮的。

9402357-4c41c1d3c272f8b8.png
response對比

    那多出來的引數怎麼來的呢? 這就要看flask-compress做了什麼了。

9402357-d96dd558825e8d53.jpg
Look what u made me do

    開啟原始檔,程式碼註釋加空行總共119行,嗯,優秀的程式碼都這麼短。

    flask-compress做的事情就是,向app中插入自己的after_request方法,在這個after_request方法中進行資料壓縮,引數設定:

      if (app.config['COMPRESS_REGISTER'] and app.config['COMPRESS_MIMETYPES']):

              app.after_request(self.after_request)

after_response中主要的程式碼,根據各種引數判斷要不要做壓縮,壓縮完了設定encoding等引數,告訴瀏覽器如何壓縮的,使瀏覽器知道如何解壓。

9402357-08e86e212f920448.png
flask-compress的after_request方法
9402357-2ecf2b531eb8f7fa.jpg
這個人說完了嗎?

    回答上面圖片:沒有。

    這裡提出一個問題: 根據flask-compress 的程式碼,它是作用在application級別的,也就是說,經過這個application的請求都執行這個after_response方法,compress是需要消耗CPU的,如果不想所有的response都壓縮怎麼處理?

      我認為有兩種解決辦法:

        1. 設定flask-compress提供的各種引數,來達到控制的效果

        2. 這個是我想的,抽取壓縮方法,結合flask的make_response方法,壓縮特定的請求。

    分開來說,第一點,這種產品肯定會考慮到我們的問題,如果每個請求都壓縮,就有點笨了。可以設定兩個引數控制是否壓縮:COMPRESS_MIN_SIZE 和 COMPRESS_MIMETYPES。

    COMPRESS_MIN_SIZE 控制最小壓縮閾值,小於這個值的就不壓縮,預設值是500. COMPRESS_MIMETYPES 控制的是壓縮型別,不在型別範圍內不壓縮,預設值是['text/html','text/css','text/xml','application/json','application/javascript']。設定方式如下,測試程式碼我就不寫啦,大家自己玩玩~

9402357-fbb8f65a2a283f15.png
引數設定

    另外,還有第三個引數,COMPRESS_LEVEL,這個引數是控制壓縮級別,就是gzip的壓縮級別,1-9,1的壓縮速度最快,壓縮率最小,9 反之,預設值是6。在上面的例子中看不出來效果,我在專案中做測試的時候,有一種壓縮使用了很多時間經歷,特別設定了這個引數,效果立刻不一樣~

    第二種,通過make_response方法獲得response,複製flask-compress的程式碼內容,進行壓縮。 經過測試,一樣可以達到效果,作用域就變成了當前方法了。

9402357-08c448692247d670.png
紅色程式碼摘自flask-compress

    除了flask-compress,常用的壓縮方法還有配置nigix。 這篇就不說啦,如果我能活過接下來的UAT,那我再繼續寫(基於前面的天津遊記過了半年仍然沒有後續,這個nigix的文章,嗯……have a nice life……)

9402357-44b19cdb2eefe6b8.jpg
我會寫的!

==============================

    寫之前覺得很有意思,終於寫完了,反而覺得像是在做測評,寫完了就不好玩了。果然寫東西就是要享受過程。 比如,一開始沒有注意到Chrome控制網速的開關,本地load資料,500M也就用了幾秒好嘛~看了之後差點崩潰,我去哪裡找個遠端伺服器嘛~難道去找哆啦A夢・陳寶石? 說來還是我腦子好使~?辦法總比困難多~自己製造的困難自己放棄嘛(不是) ~

    這篇廢話連篇的文章,就當作是又一個光棍節給自己的小小獻禮。

    P.S. 最好的瀏覽器是IE,我說這個應該沒人反對吧?

相關文章