Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 3, 2011 07:53:33

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

Андрей Светлов
Каким образом в одном потоке может работать несколько wsgi application одновременно?
Лучше сказать не одновременно, а поочередно (поток то один).
Вот эмуляция вызова app в одном потоке:
# coding: utf8

from bottle import default_app, request, get

@get('/')
def main():
from random import randint
if 'my_local' not in request: request['my_local'] = randint(0,100)
return str(request['my_local'])

# emulate wsgi
Stream = type('MyStream',(object,),{ 'write':lambda a,b:None })
start_response = lambda status,response:None
application = default_app()

# 5 questions
envs = map(lambda x:{ 'wsgi.errors':Stream() },xrange(5))

# 3 cycle
for i in xrange(3):
print [application(environ, start_response) for environ in envs]
Результат:
[['62'], ['50'], ['26'], ['4'], ['67']]
[['62'], ['50'], ['26'], ['4'], ['67']]
[['62'], ['50'], ['26'], ['4'], ['67']]
В данном примере мы “параллельно”, вызвали 5 запросов, 3 раза. Как показывает результат, код:
    if 'my_local' not in request: request['my_local'] = randint(0,100)
не “перебивает” переменные. Т.е. bottle может работать в неблокирующем режиме (хотя надо надо вывод подрихтовать, но суть не в этом)
Вообщем осталось дело за wsgi.

Офлайн

#2 Апрель 3, 2011 08:02:35

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

Андрей Светлов
Каким образом в одном потоке может работать несколько wsgi application одновременно?
кстати, wsgi не уничтожает созданные потоки, он передает новые запросы в старые потоки. т.е. один и тот же поток обрабатывает множество запросов, только каждый запрос обрабатывается единожды.

Офлайн

#3 Апрель 3, 2011 12:32:41

zheromo
От:
Зарегистрирован: 2010-10-02
Сообщения: 356
Репутация: +  2  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

o7412369815963
он передает новые запросы в старые потоки
Ключевое слово - одновременно - подразумевается что в одном потоке (процессе?) одновременно работает одно приложение, формально wsgi приложение должно работать и при multithread, и при multiprocess, и run_once. Т.е. нигде не сказано (run_once не гарантируется) как оно будет запущено, и будет ли поток переиспользован или нет - это вопрос реализации сервера - который нас не должен интересовать.

Вообще, на мой взгляд, если есть возможность не использовать thread local - лучше этого и не делать.
Формально у нас есть request (который мы создаем при начале запроса) - и его должно быть вполне достаточно для всего что зависит от отдельного запроса, также его, по моему, лучше передавать в контроллер в явном виде. Всякие параллельные запросы к данным и прочее, должно решать хранилище (база данных), а не как ни контроллер.

Прелесть же wsgi именно в абстракции от всякого рода реализаций, сокетов и прочего.

Архитектурно thread local решает, как правило, следующие вопросы:

1. Доступ к текущему контексту выполнения (request, конфигурация и т.д.) - решается передачей реквеста в контроллер, с конфигурацией можно поступить также (вообще environment самое то ей место, либо пусть там будет ссылка на то где ее взять), проблема возникает только в том случае, когда нам нужна конфигурация в модели, но туда можно ее и передать)

2. Совершение шаблонных действий при начале/завершении запроса. Например для соединения с базой данных, обработки самого реквеста, либо, например, добавления в контекст шаблонизатора чего-нибудь. Можно либо добавить в request соответствующие декораторы (типа flask-овского @app.before_request), для себя завел пару интерфейсов, вроде этого
class IRequestListener(Interface):
'''Request listener
'''

def before_request(context, request):
"""Call before request"""

def after_request(context, response):
"""Call after request"""


class ITemplateRenderListener(Interface):
'''Template render notifications
'''

def template_rendered(template, context):
"""Called when template rendered"""

def update_template_context(context):
"""Update the template context with some
commonly used variables."""
3. Может для чего-то еще.

PS. Также можно написать всякого рода middleware (там где это действительно нужно) типа сессий, csrf и т.д.

По мне, так tread local действительно используется только для “быстрого вхождения” в продукт. Сами авторы как-то обходятся. И, действительно, некоторые решения, лично мне, даются чуть более тяжело, но это, по моему, дело привычки.



Офлайн

#4 Апрель 3, 2011 12:43:18

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Нафига нам нужен тред локал.

Есть еще такие понятия как декомпозиция и тестирование. В этом плане thread locals недалеко ушли от глобальных переменных.



Офлайн

#5 Апрель 3, 2011 13:37:57

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

zheromo
Ключевое слово - одновременно - подразумевается что в одном потоке (процессе?) одновременно работает одно приложение
наоборот, в одном потоке несколько приложений “одновременно”. (про это разговор, иначе “кина” бы не было)
т.е. наподобие событийно ориентированного: запрос 1 прилетел, поработали с ним, отправили команду в БД, что-б не простаивать принимаем запрос 2 в это же поток, когда ответ из БД пришел даем управление запросу 1.

>Архитектурно thread local решает, как правило, следующие вопросы:
>1. Доступ к текущему контексту выполнения
Согласен

>2. Совершение шаблонных действий при начале/завершении запроса.
Для этого thread local необязателен

>Есть еще такие понятия как декомпозиция и тестирование. В этом плане thread locals недалеко ушли от глобальных переменных.
имхо, высосано из пальца

можно подытожить:
>По мне, так tread local действительно используется только для “быстрого вхождения” в продукт. Сами авторы как-то обходятся. И, действительно, некоторые решения, лично мне, даются чуть более тяжело, но это, по моему, дело привычки.

Есть “быстрое вхождение”/удобство, отрицательных факторов не выявлено. Счет 1:0 в пользу thread local, не зря разработчики фреймфоров его используют.

Офлайн

#6 Апрель 3, 2011 14:15:34

zheromo
От:
Зарегистрирован: 2010-10-02
Сообщения: 356
Репутация: +  2  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

o7412369815963
имхо, высосано из пальца
ну почему же
проще тестировать код где все передается явно
а то у вдруг у меня вьюха захочет себе cureent_app.config, ну конечно, мы ей его сделаем, но ни проще ли ей какой-нибудь request._blank(environ=self.test_env) передать
ну и всякие побочные эффекты (котрые мы обязательно выявим, и изменим тесты, и будем все это поддерживать)



Офлайн

#7 Апрель 3, 2011 14:31:14

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Нафига нам нужен тред локал.

o7412369815963
.е. наподобие событийно ориентированного: запрос 1 прилетел, поработали с ним, отправили команду в БД, что-б не простаивать принимаем запрос 2 в это же поток, когда ответ из БД пришел даем управление запросу 1.
Ну а я о чем?
Прилетел первый запрос, установили request для него, взяли параметры из этого request и кинули БД на обработку. Прилетел второй запрос. Переставили request, работаем. Подтянула БД что-то. Обработали кусок и спрашиваем дальше. А в request что? Нам снаружи снова первый запрос поставили? Но это же глобальная переменная в чистом виде! С такими переключениями запутаться немудрено.
Почему во всех GUI события приходят в обработчики как параметры, а не хранятся в глобальном объекте? Это был как-бы намёк.



Офлайн

#8 Апрель 3, 2011 20:07:25

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

Андрей Светлов
Почему во всех GUI события приходят в обработчики как параметры, а не хранятся в глобальном объекте? Это был как-бы намёк.
Может потому что на низком уровне нет волшебного “тред локал”. В GUI наверно так удобнее, передача параметров из ф-ии в ф-ию идет с преобразованием параметров, например влетает 4 DWORD, а в OnMouseMove приходит x,y,prm. + там не используются паттерны типа IoC. А вообще это другая сфера, хоть и есть похожие моменты.

Офлайн

#9 Апрель 3, 2011 20:26:17

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Нафига нам нужен тред локал.

IoC — это inversion of control? А почему в GUI его нет? С моей точки зрения — как раз классический случай.
Я не настаиваю, но мне кажется что различий меньше чем сходства.
Как по мне, thread locals для request/response не являются мировым злом, — но есть и более удачные варианты.



Офлайн

#10 Апрель 7, 2011 14:18:15

DcDr
От:
Зарегистрирован: 2011-01-09
Сообщения: 61
Репутация: +  0  -
Профиль   Отправить e-mail  

Нафига нам нужен тред локал.

Андрей Светлов
Реализовав их, например, в том же nginx - он ведь от рождения неблокирующий?
?



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version