メモ_Flask-Cachingと簡易静的サイト配信の比較

FlaskにはWebサイト・アプリ全体に適用できるキャッシュ機構としてFlask-Cachingがありますが、最近よく見かけるAstroなどの静的サイト生成みたいに、最初から静的HTMLを生成しておいてFlask側で読み込むだけにした場合、Flask-Cachingを有効にしたWebアプリと比べて、どのくらい処理が高速になるか、簡単に実験してみました。

 

準備:

まずはFlaskアプリで自動生成しているWebページをhtmlファイルとして取得します。

テスト用に1~100までの連番ページを以下のコードでゲットしていきます。


import requests
import os

base_url = 'http://localhost:5000/'  # ベースURLを指定
output_dir = 'static_pages'  # HTMLファイルを保存するディレクトリを指定
os.makedirs(output_dir, exist_ok=True)  # ディレクトリが存在しない場合は作成する

for i in range(1, 101):  # 1から100までの連番でループ
    url = f'{base_url}{i}'
    response = requests.get(url)
    
    if response.status_code == 200:
        file_path = os.path.join(output_dir, f'page_{i}.html')
        with open(file_path, 'w', encoding='utf-8') as file:
            file.write(response.text)
        print(f'Saved: {file_path}')
    else:
        print(f'Failed to retrieve {url}, Status code: {response.status_code}')

取得したhtmlファイルを静的HTMLとして配信するため、専用にルーティング設定をします。


# テスト用 / 静的HTMLを配置して表示させる

from flask import Flask, send_from_directory, abort
import os

# 静的ファイルが保存されているディレクトリ
STATIC_DIR = '<Flaskアプリのプロジェクトルート>/app/static_pages/'

@static_bp.route('/')
def serve_static_file(filename):
    if filename.endswith('.html'):  # HTMLファイルのみを提供
        file_path = os.path.join(STATIC_DIR, filename)
        if os.path.isfile(file_path):
            return send_from_directory(STATIC_DIR, filename)
    abort(404)  # ファイルが存在しない場合は404エラー

あとは実際にアクセスして正常に表示されるかを確認した後、負荷テストをかけてみます。負荷テストにはLocustを利用しました。

比較用にFlaskアプリで自動生成の状態でも同条件でテストしています。

結果:

最大ユーザー数1800、秒間10ユーザー増加、wait_time を0.1~1秒間に設定して、3分間のテストを実行しました。

 

Flaskアプリのほうは、RPSが約350、平均レスポンスタイムが約3300ms、Failuresは3%となりました。

静的HTML配信のほうは、RPSが約650、平均レスポンスタイムが約500ms、Failuresは0%となりました。

Flaskアプリの高負荷時では、平均レスポンスタイム3300ms(≒3.3秒)となり、これはちょっと厳しいですね。負荷テスト中に手動でもアクセスしてみましたが、かなりストレスを感じる遅さでした。

一方の静的HTMLのほうは、最初にレスポンスタイムが6000msほどになる謎の山場がありますが、それ以降は500ms以下でサクサクと表示されます。

どちらのグラフも、RPSの伸びが途中で低下したり停滞しているので、それぞれこの環境では限界っぽいです。条件を変えて試行してみましたが同様でした。

 

まあ、静的HTMLのほうが速いのは自明で、さらにいえば、該当ページを設計上からもFlaskアプリから外してNginx 直配信にすれば、もっと高速化するはずです。

RPS(秒間リクエスト回数)が300というのは、1時間あたり108万(月間だと数億PVクラス)にもなるので、それだけのアクセス負荷を捌ければ十分とも言えますが、比較的容易に負荷耐性を2倍以上にできるのは嬉しいですね。