[C] Nginx - модули: можно или нет использовать потоки ?

Yulka-MOl

Всем привет.
При написании модуля к веб-серверу nginx потребовалось создать фоновый поток для регулярного обновления данных.
Идея в общем такая.
Внутри функции модуля, которая парсит конфиг, создается поток. Раз в n секунд функция потока просыпается и обновляет данные с диска из базы.
Например, сейчас на диске лежит файл data.json и я хочу раз в 30 секунд перечитывать его содержимое в память.
При этом обработчик запросов будет отдавать клиенту данные из памяти.
Детали.
Я посмотрел небезызвестную статью Evan Miller'а про его модуль Circle GIF, рисующий GIF-изображение в виде круга в браузере.
Дополнительно посмотрел модуль GeoIP, использующий файл соответствий IP-адреса и геобазы.
Вроде бы получилось их скрестить. Потоки я не использовал. Файл читается один раз с диска.
Проблема Я решил добавить потоки.
Выяснилось, что начиная с версии 0.7.4 опция --with-threads запрещена в конфигурации.
Использовать кроссплатформенные обертки для работы с потоками в nginx я не могу.
PS Код будет исполняться на CentOS и я могу использовать pthreads библиотеку, заточенную под UNIX.
Но насколько это правильно? Делал ли кто-нибудь что-нибудь подобное?
Буду признателен любой помощи.

marat7256

Зачем пихать явно отдельную задачу в код web-сервера?
Воспользуйся crontab для выполнения регулярных действий.

iravik

предполагаю, что там есть какие-то данные, отдающиеся модулем нгинкса, и эти данные он хочет периодически обновлять

marat7256

Я исходил из абзаца "Например".
Ну, и аналогичную задачу я именно так и решал: регулярно (crontab) отдельный скрипт парсил базу и клал данные в memcache, откуда уже забирал php-скрипт, запускаемый апачем.

Lexa111

У nginx есть собственные таймеры (см ngx_add_timer, ngx_del_timer чем они не устраивают?

Yulka-MOl

У nginx есть собственные таймеры (см ngx_add_timer, ngx_del_timer чем они не устраивают?
Спасибо. Изучу сегодня этот вопрос.

salamander

> Nginx
> Я решил добавить потоки.
> Но насколько это правильно?
Совсем неправильно. Nginx основан на event-loop, твое решение идет точно поперек его архитектуры. Используй его таймеры, как тебе сказали выше.

Yulka-MOl

Ну, и аналогичную задачу я именно так и решал: регулярно (crontab) отдельный скрипт парсил базу и клал данные в memcache, откуда уже забирал php-скрипт, запускаемый апачем.
@
Вот я, если честно, тоже к такой архитектуре пришёл.
@__
Если делать обновление через ngx_add_timer и ngx_del_timer, то поток по обработке запросов будет тормозить все то время, что обновляются данные.
Или я не прав?

tokuchu

А почему таймеры, а не inotify какое-нибудь?
Или ещё файл в память замапить не поможет?

Lexa111

Если делать обновление через ngx_add_timer и ngx_del_timer, то поток по обработке запросов будет тормозить все то время, что обновляются данные.
Да, именно так.
[кэп]
Если файл большой, а вычислений мало - можно посмотреть в сторону aio. Если требуется много CPU time - то да, либо потоки, либо обработка сторонним процессом с последующей подгрузкой уже обработанных данных из него.
[/кэп]

Yulka-MOl

А почему таймеры, а не inotify какое-нибудь?
@
Архитектура nginx такова, что есть процесс master и процессы workers.
Вызов обновления внутри worker'a через таймеры или inotify будет тормозить поток worker'a.
Вместо обработки запросов он будет заниматься обновлением данных.
@__ и @
P.S. Я вот главного не пойму.
Добавить новый поток в worker - это плохо.
А схема crontab - memcached - util process - вроде как хорошо. :)

tokuchu

Вызов обновления внутри worker'a через таймеры или inotify будет тормозить поток worker'a.
А если обновление длительное по времени, то зачем пытаться это дело вкорчевать в nginx? Не проще ли его бекэндом запустить тогда?

Yulka-MOl

А если обновление длительное по времени, то зачем пытаться это дело вкорчевать в nginx? Не проще ли его бекэндом запустить тогда?
@
Вместо одной сущности (модуля nginx я должен буду завести 3 сущности (модуль, утилиту и общее хранилище всё это синхронизовать, правильно сконфигурировать и так далее.
Спасибо. :)

artimon

Я вот так и не понял зачем тебе модуль?

Lexa111

Добавить новый поток в worker - это плохо.
А схема crontab - memcached - util process - вроде как хорошо.
Потоки плохи тем, что
а) усложняется решение (блокировки, экспоненциальный рост состояний и т.п
б) если падает поток, падает весь процесс,
в) оскверняется event-loop nginx-а,
г) если воркеров у nginx несколько, то каждому воркеру придется перечитывать файл (немного некрасиво)
Если ты готов с этим жить, не вижу причин, почему бы не использовать потоки.
(была еще идея перечитывать файл мастер-процессом по reload-у, и релоадить nginx по обновлению файла, но раз в 30 секунд это делать не вариант)

Yulka-MOl

Я вот так и не понял зачем тебе модуль?
@
Это упрощенный прототип, на котором я тренируюсь.
на диске лежит файл data.json и я хочу раз в 30 секунд перечитывать его содержимое в память.
При этом обработчик запросов будет отдавать клиенту данные из памяти.
Более крутой модуль мне нужен, чтобы работать с Cookies на nginx сервере.
Вся проблема в том, что информация, которая пишется в Cookies, обновляется каждые N секунд c диска / из БД.
Логика формирования Cookies не совсем простая. В двух словах не расскажешь.
Своего рода метрика посещения страниц сайта для рекомендательного сервиса и в БД лежит словарь.
Подробно @: в БД хранятся идентификаторы страниц сайта и идентификаторы мета-тегов для страницы сайта. Обновление этой БД довольно регулярное: раз в 2 минуты. В куку я пишу идентификаторы и мне требуется их список регулярно пополнять, читая из БД.
@__ Пункт г можно обойти организовав общий семафор.
Выполнять reload на высоконагруженных серверах раз в n секунд - это совсем плохо. :)
Ладно, пока буду думать в направлении предложенным товарищем ым.
Раз уж другого способа не предлагается. :)
Всем тогда спасибо.

zya369

а aio разве не через потоки сделан (в линуксе, по-крайней мере)?
в случае с мемкешом - чтение из него тоже надо будет либо встраивать в main-loop (что вряд ли просто либо читать синхронно - тогда точно так же worker может залипнуть
ЗЫ а кроме "надругания" над чистотой архитектуры нгинкса есть какие-нибудь причины не создавать тред?

zya369

 
Модуль мне нужен, чтобы работать с Cookies на nginx сервере.
Вся проблема в том, что информация, которая пишется в Cookies, обновляется каждые N секунд c диска / из БД.

может, ты более детально напишешь, чего хочешь достичь?

Hastya

Я вот так и не понял зачем тебе модуль?
+1

zya369

блин, не делай так больше - не добавляй ответы на вопросы в ранее созданные посты :crazy:
на мой взгляд аккуратно написанный тредик типа

sleep
load_data
swap_data

ничего не усложнит и ничего не сломает

Yulka-MOl

блин, не делай так больше - не добавляй ответы на вопросы в ранее созданные посты :crazy:
@
Извини. Не буду так больше делать.
Я привел пример в первом сообщении треда и обозначил проблему.
А меня завалили вопросами "зачем тебе это?". Чтобы не отвечать каждому, я все объединил в один пост.
Примите, как дано, что мне это надо. И мне нужен nginx, потому что есть другая бизнес-логика на нем. :)
на мой взгляд аккуратно написанный тредик типа sleep load_data swap_data ничего не усложнит и ничего не сломает
Здесь я согласен, но выше приведены аргументы, что
1) Мы должны будем организовать работу так, чтобы 10 worker'ов 10 раз не делали одну и ту же работу по обновлению данных в памяти (скорее всего через команду flock это можно обойти).
2) В nginx нет механизма работы с потоками. Их запретили в версии 0.7.4. И любая попытка это обойти - по сути хак. :(
Остается только один вариант. Делать отдельный процесс, вызов которого осуществлять по cron или через те же ngx_add_timer / ngx_del_timer.
А потом можно будет поиграться и переписать через потоки и посмотреть, как изменится производительность.

zya369

1) Мы должны будем организовать работу так, чтобы 10 worker'ов 10 раз не делали одну и ту же работу по обновлению данных в памяти (скорее всего через команду flock это можно обойти).
2) В nginx нет механизма работы с потоками. Их запретили в версии 0.7.4. И любая попытка это обойти - по сути хак.
1) не факт, что это нужно. Если там операция не супер ресурсоёмкая (именно ресурсо-, а не времени- то можно и 10 раз считать
2) в нгинск нет мехнаизмов для работы много с чем - это не повод ограничивать себя. Потоки они "запретили" наверняка для того, чтобы 1) никто не пересекался с mainloop-ом; 2) никто не заблокировал основной поток исполнения непродуманным mutex-ом али еще чем;

salamander

P.S. Я вот главного не пойму.
Добавить новый поток в worker - это плохо.
А схема crontab - memcached - util process - вроде как хорошо. :)
Ты не с той стороны на это смотришь.
Добавить новый поток для обработки асинхронных событий - это плохо, поскольку события обрабатываются в nginx через event-loop.
Вынести тяжеловестные и независимые от вебсервера вычисления в отдельный процесс - это хорошо, и вебсервер разгружается, и независимая сущность выделяется в отдельную компоненту.

Garryss

В утилите обновления по кронтабу:
1. Подготавливаешь бинарный файл с данными ровно в том виде, в котором будешь работать в nginx'е (boost/serialization или что-то подобное в помощь).
2. Далее читаешь файл в холостую один раз, чтобы он закэшировался в ОС
3. Посылаешь уведомление в nginx о том, что готова новая версия данных (сигнал?).
При получении уведомления в nginx'е:
1. mmap(PROT_READ, MAP_SHARED) + mlock на указанный файл. Так как файл уже закэшировался, то это быстро отработает даже для многогигового файла.
2. используешь полученный кусок памяти по назначению

Yulka-MOl

@
Я планировал примерно то же самое через shared memory сделать.
Но за рекомендацию с файлами тоже большое спасибо.

zya369

2. Далее читаешь файл в холостую один раз, чтобы он закэшировался в ОС

1. mmap(PROT_READ, MAP_SHARED) + mlock на указанный файл. Так как файл уже закэшировался, то это быстро отработает даже для многогигового файла.
1) полагаться на то, что файл закешируется - фэйл
2) любой вид лока на внешний ресурс - потенциальный блок основного воркера (тут как с ружьем на стене)
3) насколько я понял, предполагается держать лок все время обработки запроса, т.е., если запросов много, то лок держится почти всегда и тогда, когда придет время отдельной утилите писать в файл, она заберет лок и фэйл из пункта 2) точно случится

zya369

Я планировал примерно то же самое через shared memory сделать.

с шаредмемори те же проблемы с локами
+ шаред мемори легко еще может остаться жить и засирать оперативку, если процесс упадет не освободив ее (и тут вообще непонятно, кто должен ее освобождать)

Garryss

1) полагаться на то, что файл закешируется - фэйл
2) любой вид лока на внешний ресурс - потенциальный блок основного воркера (тут как с ружьем на стене)
3) насколько я понял, предполагается держать лок все время обработки запроса, т.е., если запросов много, то лок держится почти всегда и тогда, когда придет время отдельной утилите писать в файл, она заберет лок и фэйл из пункта 2) точно случится
Мне кажется, ты пишешь о каких-то совсем других локах. :confused:
mlock(2) - Linux man page

Yulka-MOl

+ шаред мемори легко еще может остаться жить и засирать оперативку, если процесс упадет не освободив ее (и тут вообще непонятно, кто должен ее освобождать)
@
Ну а что тут можно предложить?
Да. Есть такая проблема. Память освободит и лок с флага снимет наша же утилита, запущенная через 30 секунд прямо при старте. (flock для подстраховки).
Фактически я хочу сделать 2 буфера в общей памяти. Один для чтения, один для записи.
И менять их местами после окончания обновления через какой-то общий флаг.
Вариант, который предложил , по моим прикидкам скушает столько же памяти, только внутри самого nginx.
Хотя он может и проще с точки зрения реализации.

zya369

я потому и написал "насколько я понял" ) - с ммапами я дела давно не имел. но все равно мне кажется, что основная проблема в том, что у тебя все закладывается на то, что файл попадет в дисковый кеш - я сомневаюсь (точнее, не знаю что это можно гарантировать. А если нельзя то чтение его сдиска опять таки заблокирует воркера

zya369

Хотя он может и проще с точки зрения реализации.
ну, если тебе отдельный процесс и синхронизация его с воркером (сигналами или как-то еще) проще, чем отдельный тред - то, конечно, делай так

zya369

только имей еще в виду, что тебе придется заморочиться с сериализацией данных в "сырой" кусок памяти и с тем, чтобы ты одновременно не писал/читал один и тот же кусок - просто "указателем" на тот кусок, который сейчас "актуален" тут не отделаешься

Yulka-MOl

отдельный процесс и синхронизация его с воркером (сигналами или как-то еще) проще, чем отдельный тред
@
Вы на самом деле очень клевые советы даете. Я бы до них сам точно не догадался.
придется заморочиться с сериализацией данных в "сырой" кусок памяти и с тем, чтобы ты одновременно не писал/читал один и тот же кусок
Ну для этого в утилите можно предусмотреть какой-нибудь отладочный режим с сериализацией данных.
Понятно, что хорошо бы checksum проверять и прочие вкусности.
@ Спасибо, что предложил вполне работающее решение. Но мне пока мой вариант нравится больше.
Пишу утилиту с shared_memory, весь код собираю в библиотеку.
Конфигурацию всего этого хозяйства отдаю модулю nginx.
Никаких сигналов, только проверка лока на каком-то флаге внутри обработчика запросов.
Дальше уже можно полностью перенести всё внутрь nginx (тот же pthread поток создать).
И если тесты покажут, что производительность не упала, то в таком виде и оставить.
А если нет, так придется cron или ngx_add_timer использовать.
Мыши плакали, кололись, но продолжали кушать кактус. :)

zya369

я бы на твоем месте начал с реализации через поток (т.к. на мой взгляд она гораздо проще за счет простоты синхронизации потоков по сравнению с процессами) и сравнил ее производительность с производительностью просто nginx-а с константными данными (т.е. без перезагрузки данных)

pilot

А чо будет если указать нгинксу отдавать файл с диска, а файл поменять? Не решает ли он самостоятельно ту же задачу?
Зы: скорее всего задачу решает вообще файловая система, а не нгинкс.

Marinavo_0507

я сомневаюсь (точнее, не знаю что это можно гарантировать. А если нельзя то чтение его сдиска опять таки заблокирует воркера
теоретически, в любой момент что угодно может заблокировать воркера (даже mlockall не панацея)
на практике, файл будет в кеше после первого прочтения, если памяти хватает
если рассуждать как ты, то даже index.html нельзя отдавать как есть - а вдруг воркер заблокируется при чтении файла, и пипец

stm5872449

А чо будет если указать нгинксу отдавать файл с диска, а файл поменять? Не решает ли он самостоятельно ту же задачу?
Зы: скорее всего задачу решает вообще файловая система, а не нгинкс.
Если менять именно тот же файл без локов, то все взорвется.
Если делать в отдельном файле новую версию и потом атомарно его перемещать, то будет ок, но ТС же вроде нужна какая-то логика обработки файла, а не просто отдача.

katrin2201

а) усложняется решение (блокировки, экспоненциальный рост состояний и т.п
С правильно расставленными мемори барьерами ничего этого не надо.

katrin2201

Проблема Я решил добавить потоки.
Выяснилось, что начиная с версии 0.7.4 опция --with-threads запрещена в конфигурации.
Использовать кроссплатформенные обертки для работы с потоками в nginx я не могу.
Я сорсы nginx не щупал, но быстрое гугление --with-threads говорит, что это просто переключает внутреннюю имплементацию воркеров нгинкса на треды вместо процессов, что давно не поддерживается и не работает.
Конечно, я тут могу быть не прав, но мне кажется довольно странным, что отключение подобного флага мешает в своем модуле использовать свои треды для себя.
Впрочем, shm lock-free - вполне нормальное решение, которое имеет смысл даже если треды в нгинксе таки можно плодить.

katrin2201

если рассуждать как ты, то даже index.html нельзя отдавать как есть - а вдруг воркер заблокируется при чтении файла, и пипец
Ну да. А зачем еще придумали DMA, AIO и sendfile?
Впрочем, "на практике, файл будет в кеше после первого прочтения, если памяти хватает" - согласен. Но надо понимать, что читать из памяти процесса vs читать с диска надеясь на кеш - одно лишнее копирование памяти во втором случае. Что, впрочем, может быть пренебрежимо.

Marinavo_0507

А зачем еще придумали DMA, AIO и sendfile?
sendfile как раз и предназначен, чтоб отдать файл из кеша в сеть
а если файл нужно прочитать с диска, то sendfile диск крутиться быстрее не заставит
AIO в теории как раз ничего не гарантирует
ну подождал ты пока блоки подгрузятся с диска и что? думаешь с ними уже можно работать теперь не блокируясь? нифига, диспетчер памяти мог сбросить любые страницы процесса, пока он ждал
ещё есть tmpfs если не хочется трогать диск совсем

katrin2201

sendfile как раз и предназначен, чтоб отдать файл из кеша в сеть
а если файл нужно прочитать с диска, то sendfile диск крутиться быстрее не заставит
sendfile - это такой AIO + zero copy. Из кеша там или не из кеша - пофиг, в обоих случаях все плюсы aio и zero copy сохраняются.
AIO в теории как раз ничего не гарантирует
ну подождал ты пока блоки подгрузятся с диска и что? думаешь с ними уже можно работать теперь не блокируясь? нифига, диспетчер памяти мог сбросить любые страницы процесса, пока он ждал
Да, AIO дает тебе только возможность, пока диск крутится, заниматься своими делами.
От своппинга можно защититься очень просто - отключив его.
К сожалению, это не вся картина, и остается хотя бы куча всяких прерываний, которые тоже могут "заблокировать" твой воркер. К счастью, речи о втыкании ядерного реактора в USB у нас вроде не идет, на риалтаймовую отдачу index.html мы не претендуем, так что проблемы от этих эффектов порядка микросов я не вижу. Эффекты порядка миллисов должны быть устранимы.
ещё есть tmpfs если не хочется трогать диск совсем
Согласен. Это + sendfile - довольно простой, быстрый и надежный вариант.

Marinavo_0507

Да, AIO дает тебе только возможность, пока диск крутится, заниматься своими делами.
на практике да, а в теории этого никто не гарантирует
От своппинга можно защититься очень просто - отключив его.
просто страничка с кодом может быть сброшена например и ты получишь page fault как только решишь что-то сделать с прочитанными даннными
от этого можно защититься через mlockall, но гарантия не полная: как только захочется выделить память, могут заставить подождать, причём выделить память может захотеть сисколл, та же запись в сокет например
хотя да, я понял про что ты говоришь: в nginx лучше использовать асинхронное чтение (если оно доступно оттуда) или же tmpfs

pilot

Что взорвется и как?
Атомарно перемещать = копировать новый файл вместо старого, так? Т.е. ничонеделать особенного.

zya369

я, боюсь, потерял нить вашего диалога и не понимаю, что и куда вы собираетесь посылать sendfile-ом :o
топикстартеру же не надо файл отдавать, а надо какие-то структурированные данные персчитывать откуда-то; вроде из базы вообще изначально - т.е. зачем тут файл вообще не очень понятно :D

Yulka-MOl

я, боюсь, потерял нить вашего диалога и не понимаю, что и куда вы собираетесь посылать sendfile-ом :o
топикстартеру же не надо файл отдавать, а надо какие-то структурированные данные персчитывать откуда-то; вроде из базы вообще изначально - т.е. зачем тут файл вообще не очень понятно
Если я правильно понял, то они развивают идею c файлами.
Только файл теперь на tmpfs.
P.S. Я совершенно не против, потому что идею с shared_memory или на простых потоках уже обсудили.

katrin2201

Что взорвется и как?
Если приводить аналогию из бд, у тебя случится read uncommitted.
Атомарно перемещать = копировать новый файл вместо старого, так?
Атомарно перемещать = например, делать posix rename.
Нажимание f5 или f6 в твоем любимом файлменеджере - это не то.

zya369

Если я правильно понял, то они развивают идею c файлами.

да, только они обсуждают, как послать файл куда-то, что тебе, насколько я понимаю, не нужно (я так понял, что тебе нужно считать данные и использовать их для "внутренней кухни", а не посылать просто куски отттуда клиенту)

zya369

 
Атомарно перемещать = например, делать posix rename.

только сначала еще unlink сделать надо => воркер может попасть в момент, когда файла нет => надо это как-то обрабатывать
UPD почитал ман - удалять не надо )
я, наверное, опять повторюсь, но я не понимаю, зачем тут вообще промежуточный файл (данные же вроде из БД)? и решение с потоком прекрасно решит задачу и не наплодит ненужных сущностей. Единственное "но" - чье-то чувство прекрасного может пострадать по каким-то сугубо субъективным причинам

pilot

Оставим твою напыщенную болванистость за скобками. Прям никак из командной строки posix rename не вызывается? :)
Зы read uncommited случается во всех файловых системах?

Marinavo_0507

unlink делать не надо
я, наверное, опять повторюсь, но я не понимаю, зачем тут вообще промежуточный файл (данные же вроде из БД)? и решение с потоком прекрасно решит задачу и не наплодит ненужных сущностей. Единственное "но" - чье-то чувство прекрасного может пострадать по каким-то сугубо субъективным причинам
с файлом проще (так как библиотек полно, которые могут прочитать из файла любые структуры в одну строчку) - быстрее будет работающий прототип
однако в продакшене будет сложнее - отдельный демон (или задача крона это нужно отдельно мониторить, и сильнее зависимость от системных настроек (та же tmpfs)

katrin2201

Это не беда, в рассуждениях про sendfile и tmpfs мы несколько ушли от поста топикстартера :)
Оптимальное по пефомансу решение задачи топикстартера, на мой взгляд, уже написано выше - shm\threads + memory barriers.
Пусть и корректный swap_data в общем случае нетривиален (но вполне выполним). Ибо перед тем, как делать load_data, надо убедиться, что все воркеры увидели предыдущий swap_data и не читают из места, куда собираемся load'ить.
Но при допущении, что релоадим редко, и за время между релоадами все воркеры успевают увидеть swap_data (что вполне разумно при фиксированном времени между релоадами порядка секунды) задача становится достаточно тривиальной.

zya369

с файлом проще (так как библиотек полно, которые могут прочитать из файла любые структуры в одну строчку) - быстрее будет работающий прототип

так в случае с потоком вообще серилиазовать не надо - у тебя все считывается из базы и сразу складывается в структурированную форму, а воркеру просто передается указатель на "корень"

Yulka-MOl

@
Решение получается некроссплатформенным.
На чем все это писать? На C++/Boost? Заворачивать в библиотеку, обернув extern C, и отдавать обертку в nginx?
PS Нужны примеры реализаций хотя бы одного из подходов.
А их нет, что забавно. Открываем Америку все дружно.

zya369

ну у топикстартера же один воркер на один поток будет и данные в одном адресном пространстве (безо всяких там shared memory) - воркер может просто лочить мутекс на время работы с общим ресурсом, а отдельный поток брать тот же мутекс только для swap-а. и никакой магии с барьерами и т.п.

Marinavo_0507

так в случае с потоком вообще серилиазовать не надо - у тебя все считывается из базы и сразу складывается в структурированную форму, а воркеру просто передается указатель на "корень"
ну там пока ты разберёшься с таймерами и блокировками - можно 20 сериализаций зафигачить за это время

zya369

какие еще таймеры и блокировки?
там в потоке ровно один sleep (ну да, время сна можно подгонять, чтобы интервалы были честнее, но это и в отдельном процессе так же будет?) и один mutex_lock на "быструю" операцию

katrin2201

> Оставим твою напыщенную болванистость за скобками.
Не обижайся, я же любя. Даже про "этих несведущих программистов на питоне" не стал ничего язвить :p
> Прям никак из командной строки posix rename не вызывается?
Не знаю.
Вероятно, "mv -f" в рамках одной фс в большинстве случаев делает то, что нужно. Но гарантий оно, судя по man'у, никаких не дает.

Marinavo_0507

а там у воркеров общее адресное пространство с мастер-процессом?

Marinavo_0507

гарантий в любом случае никто не даёт
а на практике есть проверенные способы

zya369

ненене, я предлагал в каждом воркере наспаунить по треду ) ( в предположении, что операция считывания данных - в данном случае из БД - не жрет проца - тогда не страшно, что одни и те же данные по несколько раз будут читаться)
но если данных много и в каждом воркере их держать накладно - то да, придется извращаться )

katrin2201

Можно и так, да. Если lock-free не прниципиально, то вполне можно жить.
Этот же вариант допиливается и до случая с shm - просто делается по мьютексу на каждый воркер. Мьютексы шарятся с релоадящим процессом, и при data_swap лочатся все по очереди.
Немножко хуже, но при ограниченном количестве воркеров все еще терпимо.

Marinavo_0507

ненене, я предлагал в каждом воркере наспаунить по треду ) ( в предположении, что операция считывания данных - в данном случае из БД - не жрет проца - тогда не страшно, что одни и те же данные по несколько раз будут читаться)
а, ну это ещё грубее, чем крон+файл
а эти процессы будут завершаться корректно? своих воркеров-то nginx прибьёт

katrin2201

rename старается: "If newpath already exists, it will be atomically replaced".

katrin2201

> Зы read uncommited случается во всех файловых системах?
Да. Так как в фс в принципе нет понятия commit на этом уровне, то read uncommitted - единственный способ прочитать в файле то, что записали другие.

pilot

Я за то чтоб не программировать, если можно не программировать. А тут по-моему можно и все должно работать, городить велосипеды незачем.

pilot

Понял, спасибо.

katrin2201

У тебя разумный ход мыслей. Просто ты не в курсе, что там внизу происходит, ну и вопросы от того соответствующие. Что вполне простимо, пока кто-то не машет флагом "я всех умней".
Городить что-то придется в любом случае, ибо задача автора не просто сервить изредка обновляющийся файл, на что тебе уже указали.
Чем плохо зашиваться на неспецифицированные детали имплементации того же mv, я, думаю, объяснять не надо, хотя это уже больше 'у комментарий.

Marinavo_0507

Чем плохо зашиваться на неспецифицированные детали имплементации того же mv, я, думаю, объяснять не надо, хотя это уже больше 'у комментарий.
ну тогда на всяких питонах вообще нельзя писать

katrin2201

Решение получается некроссплатформенным.
Оу. Ммм. Ну скопипасть к себе ту кроссплатформенную обертку, которая использовалась в самом нгинксе. Нгинкс же это как-то делал?
PS Нужны примеры реализаций хотя бы одного из подходов.
А их нет, что забавно. Открываем Америку все дружно.
Навскидку (сам не юзал, просто нагуглил): что-нить типа такого не пойдет? Написать на нем вообще всю твою логику и все?

katrin2201

Судя по всему, вот уже пару лет, как можно.
PS Спор ради спора. Я уже забыл, как это бывает. Всем хорошего дня!

pilot

> Городить что-то придется в любом случае, ибо задача автора не просто сервить изредка обновляющийся файл, на что тебе уже указали.
Где?

katrin2201

"..., но ТС же вроде нужна какая-то логика обработки файла, а не просто отдача."

Yulka-MOl

Написать на нем вообще всю твою логику и все?
@
Спасибо. Но веб сервер OpenResty не подходит. :) Нужен nginx.
Выше я уже объяснял почему (куча бизнес-логики, которую переносить не хочется).

Чтобы отдавать файл статикой, ничего программировать не требуется. :) Nginx это сам умеет.
Мне надо загрузить файл для некоторых нестандартных действий (например, формирование куки на его основе).
PS. У меня уже мозг взрывается от разных предложений. А задачка-то вроде проще не придумаешь. :)

zya369

ты опять отредактировал пост или это я еще не проснулся?
PS Нужны примеры реализаций хотя бы одного из подходов.

пример с отдельным тредом довольно простая штука и вряд ли кто-то снанет такое выкладывать (зачем?)
или ты хочешь, чтобы тебе тут кто-то написал код?)

Yulka-MOl

PS Нужны примеры реализаций хотя бы одного из подходов.
ты опять отредактировал пост
@
Нет. Просто все погрузились в спор и проигнорировали мое сообщение.
пример с отдельным тредом довольно простая штука и вряд ли кто-то снанет такое выкладывать (зачем?)
Дело тут не в простоте. Код некроссплатформенный убог и никому не интересен. :)
или ты хочешь, чтобы тебе тут кто-то написал код?)
Нет, зачем. Я, кстати, если реализацию через shared_memory допишу, обязательно куда-нибудь выложу.
PS. Беру таймаут на пару дней. С вами интересно, но надо работать. :)

zya369

Код некроссплатформенный убог и никому не интересен.

хз, мне вот виндакод, например, совсем неинтересен :D
ЗЫ хотя, если ты рассматриваешь возможность написания на С++, то в С++11 есть все необходимое, вроде бы

katrin2201

Нет, зачем. Я, кстати, если реализацию через shared_memory допишу, обязательно куда-нибудь выложу.
Вот еще вдогонку: http://github.com/openresty/lua-resty-lock.
Но тут уже надо мерять, что лучше. Очень может быть, что обычный мьютекс - лучше.
А если нужен пример, как красиво рожать тред в нгинксе, то чем код самого нгинкса под with-threads не устроит, я так и не понял.

pilot

клац: "..., но ТС же вроде нужна какая-то логика обработки файла, а не просто отдача."
Это примерно то же самое что ты сказал - вроде как ему что-то другое нужно, а где он это написал - хз.
В моем понимании это "что-то" можно записывать в файл, файл подменять. Что еще нужно ТС так ни разу и не ответил.

pilot

Нет, зачем. Я, кстати, если реализацию через shared_memory допишу, обязательно куда-нибудь выложу.
Назови ее varnish, пожалуйста :o

Dasar

>> Что еще нужно ТС так ни разу и не ответил.
Мне надо загрузить файл для некоторых нестандартных действий (например, формирование куки на его основе).

Yulka-MOl

А если нужен пример, как красиво рожать тред в нгинксе, то чем код самого нгинкса под with-threads не устроит, я так и не понял.
@
Расскажи, пожалуйста, как это сделать. --with-threads опция удалена.
Предлагаешь определять NGX_THREADS макрос прямо в коде?
P.S. Пропатчить nginx до OpenResty не предлагать. :)
@
Посмотри модуль GeoIP. Сможешь сделать, чтобы база обновлялась сама раз в сутки без перезапуска сервера? :)
PS Хорош троллить.

pilot

И я про то же.

zya369

тебе почти наверняка не надо рожать тред "как в нгинксе", т.к. там наверняка куча всяких дополнительных действий, которые тебе совершенно не нужны.
все, что тебе нужно сделать - создать тред при инициализации (или кофигурации - не знаю, насколько они там разнесены) модуля и сделать join на созданный тред в shutdown-е модуля (это, возможно, необязательно - в крайнем случае главный процесс наверняка просто убьет воркера)

pilot

@
Посмотри модуль GeoIP. Сможешь сделать, чтобы база обновлялась сама раз в сутки без перезапуска сервера?
PS Хорош троллить.
Попробуй внятно объяснять чего делать хочешь, а то приходится телепатически догадываться что за проблемы.
Файл что ли большой?

Yulka-MOl

тебе почти наверняка не надо рожать тред "как в нгинксе", т.к. там наверняка куча всяких дополнительных действий, которые тебе совершенно не нужны.
@
Согласен. Причем сам выше написал, что нашел в интернете, что код этот написан для старой архитектуры nginx.
Он может содержать ошибки, небезопасен. А кроме того, там нет нужных нам shm_lock и прочих вкусностей.

zya369

shm_lock
а что ты тут подразумеваешь?

Yulka-MOl

shm_lock
Я имел ввиду, что нет оберток функций mlock, semget и других вкусностей для работы с общей памятью.
Да и нафиг он вообще нужен, если есть boost и c++.
:)
Оставить комментарий
Имя или ник:
Комментарий: