質問

を使用していdjango apacheとmod_wsgi ール(すべて同じホスト)を取り扱う必要があり多くのダイナミックページをご希望の方は、数百円して変更することができます。私がこのボトルネックはdjangoない永続的なデータベース接続と再接続毎に要求する近5ms).なベンチマークっと接続を切り取りをすることはでき近くの500r/sがない50のr/sとなります。

誰にでもして相談すればいいのだろうか。変更する方法django使持続しています。または速度ップ接続からpythonへのDB

よろしくお願いします。

役に立ちましたか?

解決

Django 1.6 を追加 永続的な接続をサポート(リンクdocのためのdjango1.9):

持続的な接続を避けるオーバーヘッドの再構築 接続は、データベースできます。うに制御され CONN_MAX_AGEパラメータを定義する最大の寿命まで 接続します。設定することが可能で独立して各データベースです。

他のヒント

PgBouncer -軽量接続poolerのためのPostgreSQL.特徴:

  • 複数のレベルでの残虐行為が回転接続:
    • セッションプーリング
    • 取引プーリング
    • 決算リング
  • 低メモリ要件(2k接続によるデフォルト)。

Djangoのトランク、編集django/db/__init__.pyでと行をコメントアウトします:

signals.request_finished.connect(close_connection)

このシグナルハンドラは、それがすべての要求の後に、データベースから切断する原因となります。私はこれを行うの副作用の全てがどうなるかわかりませんが、それはすべての要求の後に新しい接続を開始するために、任意の意味がありません。あなたが気づいたとして、それは、パフォーマンスを破壊します。

私は今、これを使用していますが、私は何もブレークかどうかを確認するためにテストの完全なセットを行ってやりなさいます。

誰もが、これは新しいバックエンドまたは特別な接続プーラーまたは他の複雑なソリューションを必要と考えて、なぜ私にはわかりません。私は彼らが最初の場所でこれを行う作らいくつかのあいまいな落とし穴がある疑いはありませんが、これは、非常に単純なようだ - もっと賢明に対処する必要があります。あなたが気づいたとして、すべての要求のための5msのオーバーヘッドは、高性能なサービスのために非常に多くあります。 (それは私を取るの150msのの - 。私がやりなさい、なぜまだ考え出し)

編集:別の必要な変更はジャンゴ/ミドルウェア/ transaction.pyです。コミット呼び出し常に2 transaction.is_dirty()テストを削除し、()またはrollback()。それだけでロックが閉じられなければならないことを開いたままになるデータベースから読めばそうでなければ、それはトランザクションをコミットしません。

私はSQLAlchemyのプーリングを経由してのMySQLとPostgreSQLの接続プーリングを実装して、小さな Djangoのパッチを作成します。

これは、長時間の http://grandcapital.net/するの生産に完璧に動作します。

パッチは少し話題をグーグル後に書かれた。

免責事項:っていないのにします。

と思いを実装するために必要なカスタムデータベースに戻る。あの例のウェブがどのように実施するデータベースのバックエンとの接続をプールした.

を接続プールろうが良いソリューションの場合、ネットワーク接続を開放状態に保ったままでの時接続のプールがあります。

  • このポスト の達成にこぎDjangoのコメントポイントでは、より良い実装のカスタムのバックエン以外のコアベーコード)
  • このポスト 実装のカスタムdbのバックエン

両方のポMySQL-うまく利用できる類似の技術Postgresql.

編集:

  • のDjango帳つのPostgresqlの接続プーリング用 pgpool (チュートリアル).
  • 誰かが掲載 パッチ のpsycopg2バックエンドを実装する接続プール.私の提案作成のコピーを既存のバックエン独自のプロジェクト継ぎました。

私はグローバル変数を使用して、永続的な接続を実現し、いくつかの小さなカスタムpsycopg2のバックエンドを作りました。 これで、私は(いくつかの選択と非常にシンプルなページ)350から1600秒あたりの要求のamoutをを改善することができました ただ、任意のディレクトリにbase.py(例えばpostgresql_psycopg2_persistent)と呼ばれ、

設定で設定ファイルに保存します

projectname.postgresql_psycopg2_persistentするDATABASE_ENGINE

注!!!コードはスレッドセーフではありません - あなたがスレッドとpreforkのデーモンモードを使用してくださいのmod_wsgiの場合には、理由unexpectable結果のpythonのスレッドでそれを使用することはできません= 1

<時間>
# Custom DB backend postgresql_psycopg2 based
# implements persistent database connection using global variable

from django.db.backends.postgresql_psycopg2.base import DatabaseError, DatabaseWrapper as BaseDatabaseWrapper, \
    IntegrityError
from psycopg2 import OperationalError

connection = None

class DatabaseWrapper(BaseDatabaseWrapper):
    def _cursor(self, *args, **kwargs):
        global connection
        if connection is not None and self.connection is None:
            try: # Check if connection is alive
                connection.cursor().execute('SELECT 1')
            except OperationalError: # The connection is not working, need reconnect
                connection = None
            else:
                self.connection = connection
        cursor = super(DatabaseWrapper, self)._cursor(*args, **kwargs)
        if connection is None and self.connection is not None:
            connection = self.connection
        return cursor

    def close(self):
        if self.connection is not None:
            self.connection.commit()
            self.connection = None
<時間>

それともここでは、スレッドセーフですが、Pythonのスレッドが複数のコアを使用していないので、あなたが以前のものと同じようなパフォーマンスの向上を得ることはありません。あなたも、マルチプロセスのいずれかで、このいずれかを使用することができます。

# Custom DB backend postgresql_psycopg2 based
# implements persistent database connection using thread local storage
from threading import local

from django.db.backends.postgresql_psycopg2.base import DatabaseError, \
    DatabaseWrapper as BaseDatabaseWrapper, IntegrityError
from psycopg2 import OperationalError

threadlocal = local()

class DatabaseWrapper(BaseDatabaseWrapper):
    def _cursor(self, *args, **kwargs):
        if hasattr(threadlocal, 'connection') and threadlocal.connection is \
            not None and self.connection is None:
            try: # Check if connection is alive
                threadlocal.connection.cursor().execute('SELECT 1')
            except OperationalError: # The connection is not working, need reconnect
                threadlocal.connection = None
            else:
                self.connection = threadlocal.connection
        cursor = super(DatabaseWrapper, self)._cursor(*args, **kwargs)
        if (not hasattr(threadlocal, 'connection') or threadlocal.connection \
             is None) and self.connection is not None:
            threadlocal.connection = self.connection
        return cursor

    def close(self):
        if self.connection is not None:
            self.connection.commit()
            self.connection = None
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top