Pull to refresh

Comments 60

Вроде как Varnish для этого более приспособлен
Я тоже его люблю, но ssi в nginx 0.6.x, 0.7.x, 0.8.x глючен. Иногда, вместо вставляемого блока он отдает кусок случайных символов (налицо какая то проблема с указателями на память).
И нам так же пришлось перейти на varnish в качестве esi-процессора.
это потому что SSI ради скорости сделан как upstream модуль.
если бэкенд тупит, то может и сглюконуть.
Делаем быстрый бэкенд и проблемы нет.
это слабо тянет на оправдание для такого нарушения целостности, imho.
Не вижу логической связи.
в Varnish так красиво не раскидаешь по контроллерам
не задашь параметры и экшены для бэкенда.

Может это возможно, просто у меня не получилось
поддерживаю, хотя в реализации esi:include гибкости оччень не достаяет…
как вариант в nginx
можно использовать ssi + xslt
я этот вариант рассматриваю как альтернатива
гибкости будет достаточно
единственное меня смущает скорость libxslt
очень правильно смущает, это вообще не вариант в реальной жизни.
Из int повлиять на то, что покажется в top (самый простой пример из body повлиять на title) мы с таким подходом не сможем?
ну почему же можем?

можно использовать shm для хранения общих объектов
или тот же мемкеш…

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

конечно ssi должно быть использовано в меру. По мимо ssi, для формирования контента я использую и первый и второй подходы.
Средствами «шаблонизатора» получается не можем. То есть для вывода одного блока информации в двух блоках страницы в разном виде нам нужно вызывать два разных контроллера.

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

В общем выходит, что перед вызовом шаблона нужно вызвать какой-то «суперконтроллер», который подготовит в shm, мемкэше или ещё в каком-то месте доступном разным процессам/потокам все данные, а затем из шаблона вызывать «миниконтроллеры», форматирующие данные как нужно в данном блоке. Или разгребать кучу зависимостей при изменении вёрстки, чтобы быть уверенным, что данные в общей памяти есть и актуальны. Для примера title и body мы должны в контроллере title получить данные и для title и для body, выведя title и поместив body в общую память, откуда их потом возьмёт контроллер body. А если мы откажемся от вывода title, то нужно будет переносить логику получения данных в контроллер body…

В общем, по-моему, налицо жёсткая и хрупкая связь между логикой приложения, бизнес-логикой и отображением в таком фреймворке и его применение должно быть оправдано (например скорость работы куда важнее простоты поддержки).
Блок «с этим товаром покупают» ни как не должен зависить от блока «карточка товара». Есть общая часть урла от нее и пляшем: goods/10235
для карточки товара формируем урл /int/goods/10235 а для блока «с этим товаром покупают» урл /int/with/10235. Первый блок тянет из БД таблицу goods id=10235. Второй блок тянет из таблицы withGoods id= 10235. Все!!! Ни каих зависимостей! Хотим чтоб работало быстро — готовим данные заранее в отдельную таблицу. Хотим делать как все — тогда игнорируем этот топик!
тогда мы не интересуемся высокими нагрузками.
то перед вызовом шаблона нужно вызвать какой-то «суперконтроллер», который подготовит в shm, мемкэше или ещё в каком-то месте доступном разным процессам/потокам все данные
У меня это понадобилось лишь один раз в одном месте, и я сделал так называемые «отложенные вычисления». Проверяем если есть в кеше (любом) — если нет, то готовим данные. Все и ни каких контроллеров. Будьте проще, не надо городить кучу кода.
Отвечаю сразу на все:

Каюсь, пример неудачный, в общем когда один блок зависит от динамически вычисляемого содержимого (а не id) другого блока. А готовить данные в отдельную таблицу смысла может не иметь, т. к. число чтений и записей примерно равно, а может быть и вредно, если записей намного больше.

«Контроллер блока» вы в посте употребили. И зависимость останется даже при отложенных вычислениях или надо будет дублировать код для подготовки данных.

В общем идея интересная, но, по-моему, и большей гибкости, и большей производительности можно добиться комбинируя сборку шаблона из блоков средствами SSI и подготовку динамических блоков, которых нет в кэше, одним вызовом PHP
у меня так и есть!
есть два класса Application & ApplicationSSI
первоночально использовался класс Application
в котором предусмотрено использование и блоков, и хелперов (1-й и 2-й подход MVC), потом я усложнил до ssi включений. Я не стал накручивать на класс Application, а продублировал часть функционала в ApplicationSSI.
разруливается это в location установкой переменной ssi=1 (вызов ApplicationSSI)

Для отладки можно вызвать блок напрямую, тогда сработает класс Application
Вот вы сравнивали с ZF, а сравните с Yii ;)
я работал в нескольких компаниях
и там Технические Директора считали ZF образцом кодинга
по этому с ним и сравниваю
Просто они не видели Yii/Symphony :) No holy wars plz
Просто они не видели Rails :) No holy wars plz
я думаю, что они видели и Yii/Symphony, и Rails, но не видели Django
Let the sratch begin!!!
по поводу исходников ZF я бы поспорил — там хватает всякого, я бы за образец взял Symfony2
но архитектура ZF вполне неплоха, и предлагаемые coding standards — весьма удобны
согл
хватает всякого!
некоторые части исходников я использую в своих целях.
Спасибо))) Все таки вы написали статью для нас))
спасибо Вам что меня подтолкнули…
пол года как исходники валяются на гитхабе

у меня есть еще пара интересного материала.
Действительно ли SSI в этом случае быстрый?
С каких пор у нас ZF стал колбэк из вьюх дергать? В последний раз контроллеры инжектили данные во вью
Самый спорный и кривой view helper, который противоречит самой идее MVC.
Даже разработчики ZF не рекоммендуют его использование, предлагая альтернативы.
Вполне интересная и жизнеспособная идея.
Идея не жизнеспособна. Простой фреймворк, называемый SSI, усложнили до безобразия реврайтами, пожертвовав простотой ради эфемерной гибкости.

В стандартном виде SSI шаблон реализуется в HTML файле так (это внутренности страницы, например /index.html):

<!--#include virtual="/templates/header_skin1.html?mode=1" -->
<!--#include virtual="/content/bmv.html" -->
<!--#include virtual="/templates/footer_skin1.html?mode=1" -->

Как видим, получилась SSI страница, которую можно смело назвать конфигом HTML страницы. Для каждой страницы (класса страниц) на сайте можно сделать свой конфиг. И верстальщику будет довольно просто управлять этим хозяйством — проверено практикой :)
конечно конфиг громоздкий, но в моем подходе формируются индивидуальные переменные для каждого контоллера

если url = /code/delete/123 то в моей схеме можно разрулить так:




если бы этого не надо было делать, то Ваше решение вполне подошло бы;
<!--#include virtual="/templates/header_skin1.html?mode=code" -->
<!--#include virtual="/content/bmv.html?action=delete&id=123" -->
это кусок к первому комментарию
э-э-э-м-м-м-м…
Так бы и сказали, что Вам нужен ЧПУ…
Для таких случаев действительно используют реврайт, но используют как-то так:

location /catalog/ {
rewrite ^/catalog/([^/]+)/([^/]+)/? /templates/catalog.ssi?action=$1&id=$2 last;
}

И в /templates/catalog.ssi пишут:

<!--#include virtual="/templates/header_skin1.html?mode=1" -->
<!--#include virtual="/fastcgi/script.php?action=${arg_action}&id=${arg_id}" -->
<!--#include virtual="/templates/footer_skin1.html?mode=1" -->

А если еще использовать конструкцию <--#if -->, то на одном SSI такое можно наворотить :)
Не вижу необходимости в реврайте задавать вид адреса и правила для парсинга переменных. При наличии десятка контроллеров с десятком экшенов каждый ваш конфиг или .htaccess в случае апача будет страшным монстром.
1) упрощает код контроллера
2) увеличивает производительность кода
3) апач в игноре, наверно забыли что находитесь в блоге «Высокие нагрузки»
SSI в принципе работает достаточно быстро. НО, некоторые господа забывают одну прекрасную вещь. Разбив свою страницу на блоки, которые например не кэшируются, или кэшируются на очень маленькое время, подключая их через virtual, нужно помнить, что это всё подзапросы. То есть, если на вашей странице («mysite.ru/main/») есть блок с профайлом пользователя (инклуд virtual="/userprfile/?id=123"), и блок последние комментарии пользователя (инклуд virtual="/lastcomment/?userid=123"), которые вы не кэшируете по тем или иным причинам, в результате выполнится три запроса к вашему скрипту обработчику.
В логах так и увидите
"/userprfile/?id=123"
"/lastcomment/?userid=123"
«mysite.ru/main/»
И, если вы установили в глобальный обработчик функцию проверки аутентификации, она выполнится три раза. Вы на один запрос пользователя будете его авторизовывать три раза.

Нужно очень внимательно смотреть на то, что вы подключаете как SSI. Такая вот горе оптимизация, ведет к тому, что вы усложняете работу вашего движка/скрипта…
а потом во вьюхе появляется куча условий и переменных х)
самый дельный комментатор!!!
ssi надо использовать там где это действительно дает эффект
пихать микрошаблоны для формирования одной строчки таблицы большой — это тупизм!!!
И, если вы установили в глобальный обработчик функцию проверки аутентификации, она выполнится три раза. Вы на один запрос пользователя будете его авторизовывать три раза.

если конкретно аутентификация — то используем серверную, например ngx_accesskey_module, и не надо нагружать бэкенд всякой ерундой. Кeep it simple — Девиз *nix ! 

Если что-то хотим некий объект (результаты работы класса) использовать несколько раз, то используем кеш APC, memcache или  shm — выбо ограничен вашими знаниями.
Неужели ssi в nginx работает настолько медленно? Я к тому, что если _это_ только в 4 раза быстрее ZF…
Решение оригинальное и классное. Но хочется, чтобы вы провели нормальные тесты по скорости. Я не верю, что у вас ZF такой шустрый :)
по тестам без SSI на одном блоке
на простом запросе выбор по PrimariKey = 0,1 мкс (БД на производительность не влияет)
мой — 17-21 мкс
ZF 79-84 мкс

грубо говоря в 4 раза.
сделать тоже самое (реализовать 5 блоков) на ZF ради теста не поднимается рука.

на 2х -3х блоках (запросы простые аналогичные) — 24-34 мкс

кеширование, акселераторы и опкоды не использовались
отдача кешировонного контента напрямую в 10 раз быстрее, отдачи кешированного контента через РНР скрипт.
Еще отличный момент, например пробрасывать какие-то запросы на другой бекенд. Например где у вас статистика, или к примеру биллинг. Когда дублировать эти данные на основном бекенде не хочется.

Еще вариант использования, который я вижу для себя это генерация JSON-а в RIA.
Например имеем такую структуру
{
«user»: {«messages»: 10},
«page»: {«goods»: [...]}
}
Если разнести это в ssi и закешировать обе части, то у нас вообще не будет уходить ни одного запроса на бекенд.
о том и речь…
кешируем то что нам нужно с какими нужно ключами

если надо — тянем бэкенд с другого сервера (у меня пока второго сервера нет по этому я про это промолчал)
по аяксу — отдельная тема
Программирование на Nginx ))

И еще момент, не уверен на 100%, но вроде желательно (если та часть, которая выделяется (\w+), далее использоваться не будет) вместо
location ~ ^/catalog/(\w+)/? {
сделать
location /catalog/ {
и будет шустрее работать. Недавно была на хабре ссылка на доклад Сысоева на эту тему habrahabr.ru/blogs/nginx/108703/
несомненно будет быстрее работать но Вы просмотрели одну деталь
location ~ ^/catalog/(\w+) {
rewrite ^(.*)$ /index.tpl;
set $memkey «top_$1»;
}

Догадались какую или кто подскажет???
Да, ключ мемкеша. Думаю можно в качестве set $memkey использовать целиком $uri, хотя это уже изврат получается.

В принципе, в том же докладе рекомендовали делать вложенные локейшены — внешний без регулярки, внутренний уже с регуляркой и пр.

Хотя, пожалуй, я бы в итоге все равно сделал как у вас)
см конфиг conf/local.nginx.conf
там использованы вложенные локейшены.

можно использовать весь ури, но есть следующая ситуация:
отображаем топ 10 всех компьютеров,
т.е есть ури /top10/computer/p1, /top10/computer/p2 и /top10/computer/p3
но для них должно быть одно и тоже отображение, которое формируется и кешируется результатами исполнения /top10/computer

нам не надо кешировать три раза одно и тоже
Зачем холиварить о скорости работы языков программирования? Что быстрее? Что надежнее? Что лучше?
Давайте, ребята, кодить на чистом nginx. :) Нужны только пара библиотек а-ля nginx_mongo, nginx_memcached итп. Нужно же где-то хранить данные.
а не лучше ли кодить на чистом Си, минуя nginx?
Разумеется, в чем-то лучше, а в чем-то и хуже. Задачи разные бывают. Например, у меня есть проекты, где бэк-эндом у меня моё приложение на Си, а фронт-эндом стоит nginx, которые раздает статику итп. Это очень удобно.
тоже есть подобные задачи,
считаю клики на Си — производительность 2.5 К запросов в сек.
Sign up to leave a comment.

Articles