Nginx + uWsgi + Django странное поведение ответа json

Некоторые технические характеристики:

  • ЦенОС 6.0
  • UWSGI 0.9.9.2
  • Нгинкс 1.0.5
  • Джанго 1.3.1

uWSGI:

    [uwsgi]
    socket = 127.0.0.1:3031
    master = true
    processes = 5
    uid = xx
    gid = xx
    env = DJANGO_SETTINGS_MODULE=xx.settings
    module = django.core.handlers.wsgi:WSGIHandler()
    post-buffering = 8192
    harakiri = 30
    harakiri-verbose = true
    disable-logging = true
    logto = /var/log/xx.log
    vacuum = true
    optimize = 2

Сериализатор JSON:

class LazyEncoder(simplejson.JSONEncoder, json.Serializer):
    def default(self, obj):
        if isinstance(obj, Promise):
            return force_unicode(obj)
        if isinstance(obj, Decimal):
            u_value = force_unicode(obj)
            if u'.' in u_value:
                return float(u_value)
            return int(u_value)
        return super(lazy_encoder, self).default(obj)

HTTP-ответ в формате JSON:

class JsonResponse(HttpResponse):
    status_code = 200
    json_status_code = 200
    message = _('OK')

    def __init__(self, json={}, *args, **kwargs):
        mimetype = kwargs.pop('mimetype', 'application/json')
        if not 'status' in json:
            json['status'] = {'code': self.json_status_code, 'message': self.message}
    super(JsonResponse, self).__init__(LazyEncoder(indent=settings.DEBUG and 4 or None, separators=settings.DEBUG and (', ', ': ') or (',', ':')).encode(json), mimetype=mimetype, *args, **kwargs)

У меня есть несколько подклассов JsonResponse с другим json_status_code и сообщением.

Вид:

....
if application.status == Application.STATUS_REMOVED:
    return JsonApplicationSuspendedResponse()
....
return JsonResponse()

ПРОБЛЕМА:

Даже когда статус приложения меняется, случается, что я получаю старый json, скажем, в течение 3-4 секунд, а затем он правильно возвращает JsonApplicationSuspendedResponse().

Я проверил, что обновление статуса приложения базы данных происходит немедленно, также заметил, что если я перезагружу uWSGI и отправлю ответ на запрос, то произойдет обратная ситуация. Второй запрос после изменения статуса может иметь старый json.

Похоже, что они пишут ответ для нескольких сенкодов и имеют проблемы с ее обновлением (кэш отключен).

Любые идеи, где это может быть проблемой?

Тот же код отлично работает на Apache2 и mod_wsgi.

исправлено

Это была действительно глупая ошибка, в JsonResponse у меня было:

def __init__(self, json={}, *args, **kwargs):

часть json={} здесь очень важна, JsonResponse и каждый подкласс JsonResponse после инициализации совместно использовали исходный dict и его содержимое, поэтому ответ выглядел так, как будто он не изменился.

def __init__(self, json=None, *args, **kwargs):
    mimetype = kwargs.pop('mimetype', 'application/json')
    if not json:
        json = {}
    if not 'status' in json:
        json['status'] = {'code': self.json_status_code, 'message': self.message}

Спасибо за ваше время


person dancio    schedule 28.09.2011    source источник
comment
Попробуйте добавить временную метку в запрос GET.   -  person spicavigo    schedule 28.09.2011
comment
Я пробовал это, не работает, я думаю, что-то с серверной частью   -  person dancio    schedule 28.09.2011
comment
модуль uwsgi nginx имеет несколько директив для управления кэшированием. Вряд ли это ваша проблема, насколько я знаю кэширование не включено по умолчанию.   -  person zeekay    schedule 28.09.2011
comment
Я склонен винить в таких вещах uwsgi по умолчанию, он действительно глючит. Попробуйте gunicorn или uwsgi 0.9.6.8 (это лучшая версия, которую я нашел)   -  person Dave    schedule 28.09.2011
comment
Пожалуйста, ответьте на свой вопрос и подтвердите его.   -  person shkschneider    schedule 27.08.2012


Ответы (1)


Вы пытались отключить оптимизатор python (удалить параметр оптимизации из конфигурационного файла uWSGI)?

Даже если это больше похоже на проблему с js/html/client, какой-то объект может создать какой-то беспорядок с включенной оптимизацией. И, пожалуйста, не следуйте глупым советам, таким как переход на неподдерживаемые версии старше 1 года.

person roberto    schedule 29.09.2011
comment
Я удалил оптимизатор из файла конфигурации uWSGI и удалил все файлы *.pyo, *.pyc, но ничего не изменилось. - person dancio; 29.09.2011
comment
так что это проблема с кэшированием наверняка. Можете ли вы попробовать поставить uWSGI за apache вместо nginx? (можно добавить mod_uwsgi вместе с mod_wsgi без проблем). Таким образом, мы можем понять, где проблема. - person roberto; 29.09.2011
comment
... и еще один тест, который вы можете сделать, это напрямую запросить у nginx представление json через curl, поэтому вы можете быть уверены, что кеширование браузера не будет задействовано. Вы пробовали использовать mod_wsgi как в режиме eambedded, так и в режиме демона? damon_mode больше похож на подход uWSGI. - person roberto; 29.09.2011
comment
Теперь это Nginx -> uWsgi (императорский режим) -> Django, на тестовой машине у меня Apache2 -> mod_wsgi -> Django, я пробовал тестировать через urllib, также я добавлял временную метку к каждому запросу (example.com/?20110927122345), но ответ по-прежнему выглядит как "кэшированный". Я попробую apache2 и дам вам знать - person dancio; 29.09.2011
comment
извините, забыл предложить еще один тест. Если вы снова включите ведение журнала uWSGI, вы сможете увидеть, проходит ли запрос json через него или останавливается на nginx. - person roberto; 29.09.2011