copist
@copist
Empower people to give

Может ли в highload проекте c архитектурой frontend + REST backend использоваться PHP на обеих сторонах?

Недавно начал изучать Yii и приложения, поделенные на две части https://www.dropbox.com/s/s6kc8as1o07qovm/split.png

Фронтенд в данном случае - это весь интерфейс пользователя: и гостям, и авторизованным, и админам. Он отдаёт в браузер HTML+JS+CSS.
А бакенд - это вся серверная логика (базы данных, очереди, общение с другими серверами - например, читалка погоды и чужих RSS). Фронтенд общается с бакендом по протоколу REST поверх HTTP.
У меня на бакенде и фронтенде используется фреймворк Yii на PHP.

Упёрся в технический тупик: для генерации одной страницы во фронтенде требуется данных для 10 блоков HTML, они запрашиваются с бакенда десятью HTTP запросами. Тестовый сервер бакенда в виртуалке отвечает на один запрос за 100 - 300 миллисекунд. В общем, получается, что одна страница на фронтенде сгенерируется не менее чем за 1 - 3 секунды.

Я придумал способ, как собрать в кучу все запросы и послать не серией, а одновременно (multy curl) - но это надо кодить, потому что в фреймворке Yii такого, кажется, нет и готовых решений в Интернет я тоже не нашёл. Времени-то на кодинг этой логики мне не жалко, но вопрос такой - я вообще в правильном направлении копаю или нет? Может быть вообще фронтенд не на PHP делать?

Допустим, фронент выйдет на нагрузку 100 000 page view в сутки. Это ~1.1 запрос в секунду. На бакенд в параллельном режиме multy curl уйдут 11 запросов в секунду. А если page view будет 1 миллион? Не велика ли будет нагрузка на сервер бакенда, когда ему в пик начнут приходить 100+ запросов в секунду?
Как спрогнозировать потребности в ресурсах и настроить nginx и php-fpm для такой работы? Я предположил, что на 1 воркер на фронтенде потребуется 10 воркеров на бакенде, а это в 10 раз больше памяти на PHP, которым понадобится в 10 раз больше коннектов к БД и кэшу, которым тоже понадобится больше ресурсов.

По поводу 100 - 300 миллисекунд на запрос:
1) На стороне бакенда используется кэш на Redis и также файловый page cache на уровне nginx, но сейчас я их отключил для оценки максимальной длительности - как будто постоянно запрашивают то, чего в кэше нет. Включение кэша может на порядок уменьшить время ответа.
2) Сервер работает в виртуалке с ограничениями на память, процессор, воркеров nginx - продуктовый сервер, конечно же, будет жечь в полную силу :)
3) У фреймворка Yii есть довольно ощутимый вклад в время ответа, но это из-за режима отладки YII_DEBUG = true. Отладку можно выключить и скорость немного возрастёт.
4) Протокол HTTP, скорее всего, имеет вклад в время передачи туда-сюда. Стоит ли их физически размещать на одном сервере (запросы будут на 127.0.0.1/...) ? Может быть для запросов между фронтендом и бакендом пользоваться fsockopen, а не curl?

Вот такая куча вопросов. Нет у меня многомудрого коллеги, который на них ответит.

Коротко перечислю их ещё раз:
* стоит ли придумывать оптимизации в логике обмена фронтенда с бакендом в реализации на Yii+PHP или уже есть более производительные решения на других языках?
* выдерживают ли пром сервера работу с нагрузкой 1000+ запросов в секунду?
* стоит ли физически размещать на одном сервере фронтенд и бакенд?
* стоит ли между фронтендом и бакендом обмениваться через сокеты?
  • Вопрос задан
  • 6446 просмотров
Решения вопроса 2
@kazmiruk
Вы изначально неверно поняли картинку, посмотрите внимательно какие технологии используются на фронтэнде (HTML, CSS, JS). Обычно делается так:
бекэнд - любой язык, REST
фронтэнд - nginx отдает index.html (условно говоря на любой запрос) + стили + js (много кода на js. Фактически вся логика сайта написана на js). JS код уже смотрит на текущий адрес страницы, производит роутинг, рендерит layout (пока ни одного запроса к бекэнду, кроме инициализирующего), затем по ссылке он понимает какие данные ему нужны от бекэнда (к примеру список задач на сегодня) и делает асинхронный запрос (из js'а. Это может быть несколько запросов к разным частям апи). Получив ответ на этот запрос (в виде json) js разбирает его и рендерит на шаблон (все это на js). Таким образом мы получаем: бекэнд не занимается рендерингом шаблонов, значительная часть логики отрисовки и роутинга находится на клиенте и он сам с ней разбирается, гибкость системы (бекэнд может использоваться для мобильных приложений, к примеру).
То, что описали Вы - трудно назвать правильной архитектурой. По сути Ваш "фронтэнд" - обычный прокси запросов, который все также генерит Html на сервере (тратит ресурсы сервера, а не клиента) + еще курлом гоняет бекэнд. Прироста производительности с такой архитектурой Вы не получите.
Ответ написан
copist
@copist Автор вопроса
Empower people to give
Для всех, кто подписан на вопрос - текущее решение: многослойное приложение https://icons8.com/

Всё сложно.

1. бакенд https://api.icons8.com/ на PHP Yii MySQL Memcached RabbitMQ Sphinx CouchBase. Занимается хранением и организацией информации об иконках и их файлах. Работает по HTTP RPC-style API - принимает и выдаёт данные в форматах JSON/XML
2. фронтенд https://icons8.com/ на PHP Yii Memcached Gulp - занимается хранением JS, CSS, реализует авторизацию, личный кабинет и некоторые другие страницы, сборкой JS/CSS, выдаёт изображения для оформления страниц. Для личного кабинет работает с https://api.icons8.com/ через HTTP.
3. фронтенд (Reach Client Application) https://icons8.com/web-app/ https://icons8.com/responsive-icons/ и другие страницы, на которых что-то "шевелится" :) на AngularJS SCSS Jade
4. Приложения на ObjectveC для MacOC и С# для Windows https://icons8.com/app - реализуют то же, что https://icons8.com/web-app/ помощью CouchBase и https://api.icons8.com/
5. внутренние приложения по обработке файлов иконок PHP Yii RabbitMQ и много утилит для работы с графическими и векторными файлами - обрабатывает файлы SVG, конвертирует в другие форматы - работает с https://api.icons8.com/ через HTTP и очереди RabbitMQ
6. блог на PHP Wordpress icons8.com/blog который прозрачно стыкуется с icons8.com (описание habrahabr.ru/company/dataart/blog/236635/#comment_...
7. генератор страниц в формате HTML из страниц на JS на NodeJS PhantomJS с помощью https://github.com/icons8/impresser - это для успешной индексации поисковыми роботами

Любую часть системы можно размножить, но пока всё крутится на двух машинах: VDS для пунктов 1...6 и dedicated для пункта 7. Был ещё выделенный сервер Mac под пункт 5 чтобы выдавать иконки в формате PSD AI, но сломался слегка.

Планируется, что фронт на JS станет также работать с https://api.icons8.com/ через WebSocket
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
стоит ли придумывать оптимизации в логике обмена фронтенда с бакендом в реализации на Yii+PHP или уже есть более производительные решения на других языках?

Имхо, не стоит. Вообще говоря - у вас какое - то невероятно странное решение на мой взгляд. То есть по сути что вы делаете? Ага, пользовательский браузер устанавливает соединение с Вашим "фронтендом", отсылает ему HTTP-запрос, ваш "фронт" его получает, каким-то образом обрабатывает, устанавливает соединение с бэком, отсылает ему запрос, бекэнд его получает, обрабатывает каким-то образом, отвечает вашему фронту и потом фрон опять каким-то образом обрабатывает полученный ответ и отдает нечто клиенту.
Вам не кажется что это решение в принципе не может подходить под определение Highload?
У меня в крупном высконагруженном проекте есть, конечно, разделение на сервисы, которые физически на разных серверах, но они всегда отдают полную информацию в ответ на запрос(то есть если по запросу ясно, что это требуется для конечно пользователя, я отдам сразу html) и реализовывают принципиально разный функционал. Делается это для того, что бы модули друг от друга не зависили, то есть - навернулось что-то одно, работает другое. А в вашем случае зачем это? Бекэнд сможет работать, да, а фронт нет и толку от бека для клиента нет никакого. Короче, я, мягко говоря удивлен вопросом :=)
Ответ написан
Нужно тюнить "бекэенд" 200 мс это вообещ не лезет никуда. Доводите до 5-10 мс а продакшене - тогда это будет готово к highload. а теперь по вопросам - сокеты не стоит юзать для http, кеш тоже, и вообще все запросы на бекенд делайте постом. Про multy curl не уверен, должно хватить и простого curl(). 1000+ запросов что пройдут через кеш и фильтры до бекэнда - один сервер точно не выдержит. и да все это стоит размещать на одном сервере. А поверх нескольких ставить балансировщик.
Хотя 100 000 page view это вообще-то не high
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы