обслуживать различные wsgiapplications в зависимости от домена запроса на GAE с помощью threadsafe: true - PullRequest
1 голос
/ 15 марта 2012

я пытаюсь загрузить разные приложения (webapp2.WSGIApplication) в зависимости от домена запроса.например, www.domain_1.com должен загрузить приложение в app1.main.application, в то время как www.domain_2.com должен загрузить app2.main.appplication.
конечно, я в том же приложении GAE и использую пространства имен для разделения приложенийdata.

это работает довольно хорошо с 'threadsafe: false' и файлом runner.py, где функция определяет, какое приложение вернуть

, кажется, что при 'threadsafe: true' первый запросзагружает wsgiapplication в экземпляр и дальнейшие запросы больше не выполняют логику «диспетчеризации приложений», поэтому запрос получает ответ от неправильного приложения.

im, использующий python2.7 и webapp2

whatлучший способ сделать это?

edit:

очень упрощенная версия моего runner.py

def main():
    if domain == 'www.mydomain_1.com':
        from app_1 import application
        namespace = 'app_1'
    elif domain == 'www.domain_2.com':
        from app_2 import application
        namespace = 'app_2'
    namespace_manager.set_namespace(namespace)
    return wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
    main()

и в app.yaml

- url: /.*
  script: app-runner.py

Ответы [ 2 ]

0 голосов
/ 20 марта 2012

сделал это путем создания подкласса webapp2.WSGIApplication и переопределения __call__(), который вызывается перед отправкой в ​​RequestHandler.
префикса маршрутов (и удаления префикса в инициализаторах обработчиков) и конфигурации субструктуризации для возможности использования экземпляраобъем памяти.

class CustomWSGIApplication(webapp2.WSGIApplication):

    def __call__(self, environ, start_response):

        routes, settings, ns = get_app(environ)
        namespace_manager.set_namespace(ns)

        environ['PATH_INFO'] = '/%s%s' %(ns, environ.get('PATH_INFO'))

        for route in routes:
            r, h     = route # returns a tuple with mapping and handler
            newroute = ('/%s%s'%(ns, r), h,)
            self.router.add(newroute)


        if settings:
            self.config[ns] = settings

        self.debug  = debug

        with self.request_context_class(self, environ) as (request, response):
            try:
                if request.method not in self.allowed_methods:
                    # 501 Not Implemented.
                    raise exc.HTTPNotImplemented()

                rv = self.router.dispatch(request, response)
                if rv is not None:
                    response = rv
            except Exception, e:
                try:
                    # Try to handle it with a custom error handler.
                    rv = self.handle_exception(request, response, e)
                    if rv is not None:
                        response = rv
                except HTTPException, e:
                    # Use the HTTP exception as response.
                    response = e
                except Exception, e:
                    # Error wasn't handled so we have nothing else to do.
                    response = self._internal_error(e)

            try:
                return response(environ, start_response)
            except Exception, e:
                return self._internal_error(e)(environ, start_response)
0 голосов
/ 16 марта 2012

Ваш скрипт бегуна является CGI-скриптом.Полное поведение сценария CGI с включенной многопоточностью не задокументировано, и способ написания документов, я полагаю, не будет полностью поддерживаться.Вместо этого в документах говорится, что вы должны ссылаться на объект приложения WSGI непосредственно из app.yaml, используя путь модуля к глобальной переменной, содержащей объект, когда включена многопоточность.(Сценарии CGI сохраняют свое старое поведение в Python 2.7 с отключенной многопоточностью.)

Поведение, которое вы видите, объясняется вашим использованием импорта.В пределах одного экземпляра каждый оператор импорта оказывает влияние только при первом обнаружении.После этого предполагается, что модуль импортирован, а оператор импорта не влияет на последующие запросы.Вы можете импортировать оба значения в отдельные имена, затем вызвать run() с соответствующим значением.

Но если вы хотите включить многопоточность (и это хорошая идея), ваш диспетчер должен быть самим приложением WSGI, сохраненнымв глобальном модуле, указанном app.yaml.Я не знаю, как от руки отправлять запрос в другое приложение WSGI из приложения WSGI, но это может быть разумным решением.В качестве альтернативы вы можете рассмотреть возможность использования или создания слоя выше WSGI для выполнения этой отправки.

...