1

リクエストの前と後の両方で、URL を完全に動的に制御する必要があるシステムがあります。

私はこれにシグナルを使用しており、リクエスト前のシグナルにシグナルを使用しています(私が問題を抱えているシグナルには、シグナルに接続するこのようなミドルウェアがあり、現在の request.path が適用されるかどうかを確認できますこれは通常は問題なく動作し、かなりエレガントです):

class PreRouteMiddleWare(object):
    def process_request(self, request):
        url = request.path.strip('/')
        if url == '':
            url = '/'
        pre_routes = pre_route.send(sender=request, url=url)
        for reciever, response in pre_routes:
            if response:
                return response
        return None

ここで、Django ルーティング スタックの「前」に発生することを登録するには、アプリの で次のようにしますmodels.py

@receiver(pre_route)
def try_things(sender, url, **kwargs):
    try:
        thing= Thing.objects.get(url=url)
        from myapp.views import myview
        return myview(sender, some_args)
    except Thing.DoesNotExist:
        return False

これは、私の開発サーバーでもうまく機能します。

ただし、uWSGIを使用する本番環境で問題が発生します。次のように(upstartから)uWSGIを開始します。

sudo /usr/local/bin/uwsgi --emperor '/srv/*/uwsgi.ini' --enable-threads --single-interpreter

そして、私の uwsgi.ini は次のようになります。

[uwsgi]
socket = /srv/new/uwsgi.sock
module = wsgi:app
chdir = /srv/new/myapp
virtualenv = /srv/new
env = DJANGO_SETTINGS_MODULE=myapp.settings
uid = wsgi_new
gid = www-data
chmod = 770
processes = 2

発生しているように見えるのは、uWSGI プロセス/スレッドごとに、最初のリクエストで models.py をロードするだけのようです。つまり、各プロセスの最初のリクエストはシグナルの接続に失敗します。これは、models.py が起動時に (開発中のように) ロードされないため、n (n はプロセスの数) のリクエストが完全に失敗することを意味します。

uWSGI の設定が間違っていますか? 起動時に信号を強制的に接続するより良い方法はありますか?

4

2 に答える 2

3

Django は実際に遅延読み込みを行います。開発サーバーを使用すると、実際の WSGI サーバーで物事がどのように機能するかについて誤った安心感を与えます。これは、開発サーバーによる管理コマンドの読み込みにより、運用サーバーでは発生しない多くの初期化が強制されるためです。

あなたは読むかもしれません:

http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

これは、mod_wsgi で発生する問題を説明しています。uWSGI でも同じことが起こります。

于 2012-06-19T22:24:57.317 に答える
0

OK、ミドルウェアに process_request ではなく process_view をフックする必要があることがわかりました。

class PreRouteMiddleWare(object):
    def process_view(self, request, *args, **kwargs):
        url = request.path.strip('/')
        if url == '':
            url = '/'
        pre_routes = pre_route.send(sender=request, url=url)
        for reciever, response in pre_routes:
            if response:
                return response
        return None

そして今、それはうまく機能します!

于 2012-06-21T12:37:35.740 に答える