Pull to refresh

Comments 40

Программист еще не рассказывает :) Выступление в 15 часов. Один из докладов, которые с интересом послушаю. Особенно интересно сравнить с докладом про логику на LUA в Redis.
— фронтенд работает настолько быстро, что это может не понравиться бекенду. Между ними прямая связь, без прослоек. Я, например, уверен, что 10000 запросов в секунду LUA на фронтенде прожует легко. Но, если при этом оно захочет пойти в базу, тут могут возникнуть проблемы.

Какие именно проблемы возникали? Как решали? Какие базы используете?
Postgresql в основном. Он просто не успевает )) Искусственно ограничили количество одновременных запросов в локацию, где дергается база данных и воткнули пулеры, например pgpool2. Для redis и memcache тоже есть пулер, twemproxy. Если мощностей не хватает, добавляем еще бекендов с базой, оно все умеет балансироваться.
А как эта проблема проявляется для конечного пользователя? 503?
Вызов сабреквеста по факту в итоге возвратит нам какой-либо статус. Что с ним потом делать, решать тоже нам. Например,

content_by_lua '
                local res = ngx.location.capture("/some_other_location")
                if res.status == 503 then
                ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
                end';


Если логично будет отдать 503, можно отдавать )) Если нужно что-то еще, не проблема тоже.
Сделайте карту покрытия домашних провайдеров. Чтобы при клике на дом было видно какие провайдеры там есть.
Интересный был доклад.
И я был весьма удивилен такой высокой скорости в 1мс на 16000RPS на довольно сложной логике (по словам выступающего :)).

Если все прикрыто кэшами, везде включен keepalive, то работает очень быстро. И что самое главное, не надо по каждому чиху поднимать и заставлять работать медленный комбайн, как в случае если все сделано на php.
Мы у себя уже недели 2-3 обдумываем как раз, а не попробовать ли lua в подобном решении. А тут аж два выступления на эту тему: ваше плюс вчера было, пусть и не столь удачное, про redis+lua.
Полюбому теперь будем пробовать :)

Спасибо еще раз за материал!
Использовать только image_filter_module всё равно не вышло бы из-за навернутой логики промежуточных хранилищ. Использовать его совместно с lua — был вариант, но ngx_http_image_filter_module использует gd, с которым мы чуть-чуть понатерпели так что к нему у меня предвзятое отношение.

imagemagick — безумный комбайн, способный перемолоть всё =)

Суть решения: сохраняем в S3-подобное хранилище оригинал изображения, а на стороне клиента можем использовать произвольные разрешения (test.jpg -> test_15_14.jpg, test_iphone_retina_small.jpg, ...), которые после уменьшения так же попадают в хранилище и в последствии отдаются напрямую.
Главная причина — resize не единственное, что было заложено в требованиях к сервису, imagemagick все же надо было оставить.
Также, файл нам надо надо сначала достать из хранилища и это на пару с самой пережимкой все блокирует nginx-овский воркер. Плюс сам модуль весьма прожорлив под нагрузкой.
Доставание из хранилища неблокирующее всё же
Окей, вопрос про блокировки тут наверное и не приоритетный. Два остальные вопроса не решены совсем )
Навскидку, если даже брать только resize, в данном конкретном случае у меня получается 25-30 локаций и довольно сложно что-то сделать, если с файлом что-то не так или его нет. На lua у нас возможности шире и легко дописать именно то, что необходимо. Бизнес штука такая, необходимость у них часто резкая и часто мечется в разных плоскостях )))
Да, еще немаловажный момент. У нас бы появилась целая ферма ресайзеров со временем, которые ничего больше не умеют ) А тут штука многофункциональная и в случае недогруза может заняться чем-то другим, рассказав перед этим об этом своим соседям по кластеру.
Да, луа это очень удобная технология. Использую во многих проектах. Если есть возможность, то переписываю всю внешнюю часть проекта целиком на луа. Если же такой возможности нету, то луа может использоваться как минимум для быстрого взятия нужных страниц из редиса или другого подобного хранилища (в тех случаях, где взятие идет не просто по ключу, а требуется какая-то дополнительная логика).
1) Луа — это таки язык а не технология. Технология есть использование связки lua + nginx
2) Не нужно пытаться писать всю сложную логику на луа в nginx. У иначе Вас получится nodejs ;) По причине однопоточности nginx использование воркеров, или внешней логики на много эффективнее.
>>Луа — это таки язык а не технология. Технология есть использование связки lua + nginx

Да, это я и имел ввиду ;)

>>Не нужно пытаться писать всю сложную логику на луа в nginx. У иначе Вас получится nodejs ;) По причине однопоточности nginx использование воркеров, или внешней логики на много эффективнее.

Но луа позволяет написать практически любое приложение и это работает намного быстрее пхп. Для сложных вещей вроде зипования можно использовать внешние си модули, которые можно подключать через ffi — luajit.org/ext_ffi.html.
>>По причине однопоточности nginx использование воркеров, или внешней логики на много эффективнее.
Я пока мало разобрался, но в описании nginx-lua говорится о subrequests и корутинах самой lua.
Да, это все есть в луа. Можно подробнее почитать об этом на wiki.nginx.org/HttpLuaModule.

В моем случае пока не возникало необходимости это использовать. Все работает и так очень быстро. По сравнению с пхп просто фантастика.

Есть правда и проблемы с луа, иногда может при некоторых условиях возникать утечка памяти. Отследить источники проблем не так-то и просто. Можно решить с помощью костыля — перезапуском nginx.
Примерно по этой доке и разбираюсь) Правда взял вариант с github самого разработчика.
Как я понял, перекладывание большого количества логики на lua не понравилось rozhik из-за однопоточности nginx. Но синхронный Lua код выполняется только на стадии обработки конфигов (в ngix master), потом код встраивается в nginx event loop и все, при адекватном коде, должно работать очень быстро (еще и в каждом nginx worker, а не как с Perl все в том же мастере).
Lua спас мой сервер от ошибок 502/504. Буквально пара строчек (пусть и костыль) — и сервер автоматически перезапускает сбоящую подсистему, которую чинить нет времени — да теперь уже и необходимости тоже.
как говорят, нет ничего более вечного, чем временное =)
Может здесь кто-то из компании читает :) Написал вам на sales хотел купить платную версию. Только мне нужно было ее использовать для спец-задачи и интегрировать в текущий код сервера на objC. Контактная персона промямлила что-то про fastCGI, который я попробовал завести и конечно он не завелся :) Написал человеку про это, попросил просто пример интеграции и он исчез с концами. Я конечно понимаю что может вы настолько богаты что не нужны деньги :) Но если нет — отпишите кого-то вменяемого мне в личку и продолжим разговор.
М… а под компанией вы кого подразумеваете? 2Гис, nginx или lua? =)
Подозреваю что таки nginx, тогда это вам к тов. Сысоеву
Такое пишут в рассылку, например, но никак не сюда.
Вопрос — зачем вы каждую строку заканчиваете точкой с запятой? Обычно в Lua так не принято — точку с запятой можно применять, но ее ставят для однозначности, в случае двух действий в одной строке.
Привычка с других ЯП. Самодисциплина в каком-то смысле… Это как с Javascript-ом в общем-то.
Я сам тоже ставлю точки с запятой в Луа. Позволяет не теряться в вопросе — «а тут ставить надо? А там?»
Ну если в JavaScript есть разные неоднозначные моменты у точки с запятой, то в Lua, как в Python — используется только для однострочных записей. Хотя в этом смысле Lua еще более свободный, чем Python — можно писать «a = 1 b = 2» в одну строку :)
Ахаха. Не обращал внимания )) Подозреваю, что это php виновато ) Часть кода писал программист-пхпшник
Еще пару фишек, который, возможно вам будут полезны:
1. Взятие из таблицы по ключу можно делать через точку, как у атрибута: myTable['myKey'] и
myTable.myKey идентичны
2. Ключ в таблице не обязательно заключать в такую конструкцию -> ['myKey'], это необходимо только, если ключом будет число. К примеру, таблицу { ['vars'] = { ['key'] = apiKey } } можно записать так {vars = {key = apiKey}}, что выглядит намного лаконичней.
3. Storages.lua можно вообще переписать так:
module ( ..., package.seeall )

return ngx.shared

Как это будет работать? Если мы импортируем модуль Storage (пример: local Storages = require('Storages')), то после этого переменной Storages будет присвоено значение переменной, которая указана после return. В данном случае — это ngx.shared
Соответственно, Storages.banTmp будет обращаться к ngx.shared.banTmp
UFO landed and left these words here
Ну, то есть, что LUA «жует» вас не смутило )) Как жаргон допустимо же?
UFO landed and left these words here
Жаль не дошли до этого Вашего доклада. Посетили только рассказ про графовые БД.

У нас вот тоже связка nginx+Lua довольно успешно работает. Как раз писали про свой опыт недавно тут:
freepcrf.com/2013/10/10/pcrf-experience-dynamic-script-based-policy-decision-maker-or-what-do-we-need-lua-for/
Там с описанием кейса и цифрами производительности, кому интересно.
На PyCon.ru 2013 товарищ Протасов довольно подробно с рабочим примером написанным на лету рассказал про связку Nginx+Lua, при этом уложившись в пять(!) минут. Есть даже видеозапись этого выступления. Всё довольно просто и понятно, как и всё в Nginx.
Only those users with full accounts are able to leave comments. Log in, please.

Information

Founded
Location
Россия
Website
2gis.ru
Employees
1,001–5,000 employees
Registered

Habr blog