2011-06-24 11 views
14

私たちはかなりの数の地方紙(現在は13、次の月には30以上になる予定)のニュースポータルを作成し、それぞれ2kから100kのページビュー/日。各サイトが大きくカスタマイズされている状況から、それぞれの違いが構成やカスタムテンプレートの問題である状況に変化しているため、私たちのソフトウェアはすべてのサイトですでにほぼ同じです。現在、当社の展開戦略は、各サイト(サイトトラフィックに応じて1〜17人ずつ)、16コアサーバーと12GB RAMの1つのガンコーンインスタンスです。この設定の問題は、使用されているかどうかにかかわらず、各作業者(通常の前もって準備されたガンコーン)が110MBかかります。今では新しいサイトではそれほど多くのリクエストを処理するためにRAMを増やす必要があるので、基本的には拡張できません。また、各サイトが独立しているこのモデルから移動するので、各サイトには独自のデータベースがあり、リレーショナルデータベース(mysqlはpgsqlに移行)を使用しているので、この方法で断片化する。同じpythonプロセスで複数のサイトを実行する

1つのgunicornインスタンスですべてのサイトを実行して実験していますので、サーバーを完全に使用し、ロードバランサの後ろにサーバーを追加することができました。問題は、Djangoは私がこれまで考えてきたもの、私が実装する必要があると思いますので、ために、1つのサイトは、プロセスごとに実行されている多くの場所で想定しているということです。

  • からHTTP_HOSTを取るミドルウェアスレッドのローカル変数に識別子を設定します。
  • この変数を使用してカスタムテンプレートをロードするテンプレートローダー。
  • Monkey patch django.db.model.Modelおそらくメタクラスが追加されているかもしれませんが(それは可能ではありませんが、ときどき使用する必要があるカスタムマネージャーのために必要と思われます)、マネージャーを上書きする最初に元のマネージャのdb_manager(識別子)を呼び出し、目的のメソッドを呼び出します。私はまた、常にusing =識別子パラメータを含めるために、saveメソッドとdeleteメソッドを上書きする必要があります。
  • 大きな問題ではなくinclusion_tagデコレータの使用をやめる必要があると思いますが、私はこのようなケースについて考える必要があります。
  • サイトごとにカスタムURLまたは追加URLが必要な場合は、urlresolversの重大で醜いパッチを適用してください。私は今はそれらを必要としないが、おそらくある時点でそうするだろう。

これは私がそれを実装しなくてもやって来て、どこが壊れているのか見ていて、それが働くにはさらに多くの変更が必要だと確信しています。だから私は本当にそれをやりたいとは思っていません。特に私が必要とするメンテナンスの余分な努力はありますが、私は何も見ていないし、誰かがすでにこれをより良い方法で解決したことを知りたいです。もちろん、私はDjangoの使用を止めることもできますが(私はすでにそうする理由はたくさんあります)、それは大変な書き換えを意味し、2つの互換性のないブランチを維持して新しいものがdjangoバージョンとの機能パリティに達するまで私はすべての醜いハックよりも悪いようです。

+0

*正確に*サイトが提供しているものはありませんか? –

+0

サイトcontribは、すべてのサイトが同じデータベースにあるとみなし、それぞれのモデルに外部キーを追加します。また、サイトごとにカスタムテンプレートを用意するという私の要求をカバーしていません。 –

+0

それは確かです。テンプレートパス内のSiteオブジェクトから特定の部分のみを使用することができます。 –

答えて

6

私は最近、同様の要件を持つ電子商取引システムを開発しました。ほとんどの場合、同じプロジェクトから実行される多くのインスタンスがほぼすべてを共有しています。システムの以前のバージョンは独立したインストール(〜30)の束だったので、それはかなり維持できませんでした。要件はあなたのものとはまだ異なっていると思います(たとえば、すべてのインスタンスが私の場合は同じモデルを共有していました)が、私の経験を共有するのにはまだ役立つかもしれません。

あなたはDjangoがこのようなシナリオを手助けしないのは間違いありませんが、実際には驚くほど簡単に処理できます。ここで私がしたことの簡単な説明です。

私は達成したいものとdjango.contrib.sitesとの間の相乗効果を見ることができました。また、他の多くのサードパーティのDjangoアプリケーションが、現在のサイトへの絶対URLを生成するなど、それを使用して作業する方法を知っているためです。 sitesの主な問題は、現在のサイトIDをsettings.SITE_IDに指定して、マルチホストの問題に対する非常に素朴なアプローチであることです。自然に望んでいることとあなたが言及していることは、Hostリクエストヘッダーから現在のサイトを判断することです。この問題を解決するには、django-multisiteからhttps://github.com/shestera/django-multisite/blob/master/multisite/threadlocals.py#L19

というフックのアイデアを借りました。次に、私のプロジェクトのマルチホストに関連するすべての機能をカプセル化したアプリケーションを作成しました。私の場合、アプリはstoresと呼ばれ、他にも2つの重要なクラス、すなわちstores.middleware.StoreMiddlewarestores.models.Storeがありました。

モデルクラスはdjango.contrib.sites.models.Siteのサブクラスです。 Siteをサブクラス化することの良い点は、Siteが期待される関数にStoreを渡すことができることです。したがって、あなたは事実上、まだ十分に文書化され、テストされている古いフレームワークsitesを使用しているだけです。 Storeクラスには、すべての異なるストアを設定するために必要なすべてのフィールドが追加されました。だから、urlconfthemerobots_txtなどのフィールドがあります。

ミドルウェアクラスの機能は、Hostヘッダーをデータベース内の対応するStoreインスタンスと一致させることでした。一致したStoreが検索されたら、https://github.com/shestera/django-multisite/blob/master/multisite/middleware.pyと同様の方法でSITE_IDにパッチを適用します。また、storeurlconfを調べ、それがNoneでなかった場合は、特別なURL要件を適用するようにrequest.urlconfを設定します。その後、現在のStoreインスタンスはrequest.storeに格納されていました。私は私の意見では、このようなことを行うことができたので、これは、非常に有用であることが証明されています

def homepage(request): 
    featured = Product.objects.filter(featured=True, store=request.store) 
    ... 

request.storeは私のためにプロジェクト全体requestオブジェクトの自然な追加の次元になりました。だから私は簡単に例えば、現在のストア以外でのオブジェクトへのURLを生成することができ

def get_absolute_url(self, to='/'): 
    """ 
    Return an absolute url to this `Store` or to `to` on this store. 

    The URL includes http:// and the domain name of the store. 

    `to` can be an object with `get_absolute_url()` or an absolute path as string. 

    """ 
    if isinstance(to, basestring): 
     path = to 
    elif hasattr(to, 'get_absolute_url'): 
     path = to.get_absolute_url() 
    else: 
     raise ValueError(
      'Invalid argument (need a string or an object with get_absolute_url): %s' % to 
     ) 

    url = 'http://%s%s%s' % (
     self.domain, 
     # This setting allowed for a sane development environment 
     # where I just set it to ".dev:8000" and configured `dnsmasq`. 
     # The same value was also removed from the `Host` value in the middleware 
     # before looking up the `Store` in database. 
     settings.DOMAIN_SUFFIX, 
     path 
    ) 

    return url 

Storeクラスで定義された

もう一つは、その実装大体このように見えた機能get_absolute_urlました

これは基本的に、ユーザーがDjango管理者経由で新しい電子ショップを独自のドメインに作成できるシステムを実装するために必要なものでした。

関連する問題