Pycon2014 django performance

  • View
    3.520

  • Download
    1

  • Category

    Internet

Preview:

DESCRIPTION

Djangoアプリケーションチューニング、Djangoアプリケーションのチューニング方法、負荷測定方法を紹介します。PyConJP2014での発表資料です。 発表の動画はこちら http://youtu.be/1aLAZG4Udg0

Citation preview

Djangoアプリケーションパフォーマンスチューニング

@hirokiky

話すこと

Djangoアプリケーション高速化

パフォーマンス測定ツール

話さないこと

ミドルウェアパラメータ調整

検証用データの作成方法

なんか魔法みたいに速くなる技

自己紹介

@hirokiky

Python Django 好き

ギョームで100万ユーザーくらいのサイト

Django本体への貢献

Github

https://github.com/hirokiky/

Djangoアプリ高速化

SQLを吐きまくるコードは誰だ

インデックス

キャッシュキャッシュキャッシュ

アプリケーション外

SQLを吐きまくるコードは誰だ

● django-debug-toolbar

dbログ出力

django-debug-toolbar

デモ

https://pypi.python.org/pypi/django-debug-toolbar

django-debug-toolbar

dbログ出力

dbログ出力設定例

LOGGING['loggers']['django.db.backends'] = {

'level': 'DEBUG',

'handlers': ['console']

}

'console'ハンドラーは標準出力に表示する想定

SQLを吐きまくるコードを倒す

● .select_related/.prefetch_related

.bulk_create / .update

.count / .exists

.select_related (demo)

● FK先のデータも一緒に取ってくる

内部的にはJOINなどが走る

.prefetch_related (demo)

● FK元のデータも一緒に取ってくる

複数クエリを実行しPython側で結合

.bulk_create (demo)

● 複数のオブジェクトを一度に作成

.update

.exist - countダメ

その他

● .only / .defer

.values / .values_list

アプリケーションが複雑化しやすい....

QuerySetはlazy

https://docs.djangoproject.com/en/1.7/topics/db/queries/#querysets-are-lazy

>>> articles = Article.objects.all()>>> articles = articles.filter(title__startswith='title')>>> print(articles)>>> >>> q = articles.filter(author_id=1)>>> print(q)

ここでクエリ実行

ここまでのまとめ

● ORMが実行するSQLを知ろう

ORMの特性を意識しよう

他にも: https://docs.djangoproject.com/en/1.7/topics/db/optimization/

インデックス

● 適切なインデックスを使おう

結局相手にしてるのはRDB

インデックス

1) 吐かれてるSQLをみて適応してく

2) インデックスがかかるクエリに変更

吐かれるクエリは?

JetProfilerなどがツールも優秀です

検証環境などにデータたっぷりいれて

画面をポチポチします

JetProfiler for MySQL

http://www.jetprofiler.com/tour/

インデックスの貼り方

ここでは話しません

インデックスがかかるクエリにする

.extra: クエリの一部分を生SQLで書く

.raw: クエリを生SQLで書く

複雑化しやすいのでキャッシュとの兼ね合いです

ここまでのまとめ

あとそもそもテーブルの設計ちゃんとしましょう

● クエリを眺めてインデックス適応

好みのクエリを走るようにする

キャッシュキャッシュキャッシュ

キャッシュの種類と使いどころ

Redisでのキャッシュ

キャッシュの種類

レスポンスキャッシュ

ビューキャッシュ

テンプレートキャッシュ

オブジェクトキャッシュ

効果的

https://docs.djangoproject.com/en/1.7/topics/cache/

テンプレートキャッシュ

{% load cache %}

{% cache 500 sidebar %}

.. sidebar ..

{% endcache %}

https://docs.djangoproject.com/en/1.7/topics/cache/

キャッシュの使いどころ

ユーザーに依存する表示は基本キャッシュ無理

画面設計段階でどこキャッシュできるか考える

Redisでキャッシュ

Redisならではの型を有効利用:

* Set型でユニークユーザーの管理

* SortedSet型でランキング

http://redis.io/

まとめ

ユーザーに近いほどキャッシュは有効

あまり複雑化しないように設計

アプリケーション外

セッションバックエンド変更

静的ファイル圧縮

DBのPrimary/Replica構成

セッションバックエンド変更

Cacheバックエンド

Redisのバックエンド

Redisバックエンド

SESSION_ENGINE = 'redis_sessions.session'

https://pypi.python.org/pypi/django-redis-sessions

$ pip install django-redis-sessions

静的ファイル圧縮

django-compressor か django-asset

django-compressor

{% load compress %}

{% compress css %}<link rel="stylesheet" href="/static/css/one.css" type="text/css"><style type="text/css">p { border:5px solid green;}</style><link rel="stylesheet" href="/static/css/two.css" type="text/css">{% endcompress %}

http://django-compressor.readthedocs.org/en/latest/

DBのMaster/Slave

django-replicatedが便利

レプリ遅延にも賢く対応

django-replicated

$ pip install django-replicated

DATABASES = {'default': {...},

'slave1': {...}}

DATABASE_SLAVES = ['slave1']

DATABASE_ROUTERS = ['django_replicated.ReplicationRouter']

https://github.com/yandex/django_replicated

更新が master, 参照が slave になります

レプリ遅延対策

MIDDLEWARE_CLASSES = [

...

'django_replicated.middleware.ReplicationMiddleware',

]

https://github.com/yandex/django_replicated

GET, HEADで slave, それ以外で master

レプリ遅延対策 2

from django_replicated.decorators import use_master, use_slave

@use_master

def my_view(request, ...):

# GETで更新&参照するViewなんだぜ。。。

https://github.com/yandex/django_replicated

Viewに強制指定

まとめ

ORMの使い方は基本としてマスター

インデックス+キャッシュのバランス

まんべんなくやっとくのが吉です

Funkloadでパフォーマンス測定

負荷試験ツール (Pythonで書く)

セッション付きのシナリオ

静的ファイルの自動取得などリッチ

https://funkload.nuxeo.org/

Funkload (テストシナリオ)

1) 一覧画面

2) 詳細画面

3) 編集画面

4) 更新

5) 詳細画面

Funkload (demo)

$ fl-run-test test_Wiki.py

$ fl-run-bench test_Wiki TestWiki.test_update

Funkload 一覧画面

Funkload 詳細画面

Funkload 編集画面

Funkload 更新

Funkload 詳細画面

Funkload レポートビルド

$ fl-run-test test_Wiki.py

$ fl-run-bench test_Wiki TestWiki.test_update

レポートその他

2レポート間の差分レポート

複数レポートでのトレンドレポート

耐えるべき負荷は?

アクティブユーザー10万人、1日100万PV

ピーク時でその3倍として秒間34PV

人間1人5秒/1ページとして同時接続数170

このあたり模索中で良い方法などあれば教えてください

ここまでのまとめ

FunkloadはPythonで書ける

シナリオでかけるので信頼できる

全体まとめ

ORMの扱いなどは当たり前にやっておく

面倒、複雑なものは測定しつつ必要な分やる

感想

カッコいいこと言っても結局

設計とミドルウェアが重要

どううまく使うかを考えましょう

出会い系

オフィスアワー(会議室4/5)に13:15〜

Sprint(3日目)

@hirokiky

Recommended