All streams
Search
Write a publication
Pull to refresh
63
0
Александр @Treg

CTO

Send message
У нас собственное хранилище для сессий, работа с которым осуществляется через специальный класс, отвечающий за работу с демоном. SessionHandler-ы PHP и массив $_SESSION не используются.
Вы правы, специалистов с глубоким знанием Symfony на момент создания фреймворка у нас не было (или кто-то прятался). Изначально мы собрали рабочую группу, которая рассмотрела разные фреймворки, плюсы-минусы, но не могу сказать, что это был очень глубокий обзор.

Рисковать, используя сторонний фреймворк, тоже не хотелось, т.к. нагрузки большие и очень важна скорость. Свое всегда можно достаточно быстро оптимизировать, со сторонними приложениями сложнее. Highload подразумевает зачастую эффективные, но некрасивые решения.
Я бы не сказал, что Application — это God-object, если я Вас правильно понял, и он не Singleton. Он выполняет четко заданную функцию — исполнить определенный алгоритм обработки HTTP-запроса, основываясь на «чек-поинтах» — событиях.

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

90% страниц у нас работают как SPA — у нас своя достаточно интересная реализация этого в JS, заточенная под наши нужды, достойная отдельной статьи. Думаю, коллеги из отдела Frontend, в скором времени расскажут про нее.

Я знаю, что системные программисты у нас активно интересуются приложениями на Go, каких-то деталей не могу назвать. HHVM возможно кто-то пробовал, не используем в продакшене.
StreamedResponse в данном случае будет выглядеть костылем, на мой взгляд. У нас есть отдельное событие — RenderEvent. Подписчики получают результат из контроллера и осуществляют шаблонизацию. В данный момент у нас есть два подписчика — первый в объект ParseResult доставляет js_vars, актуальные для большинства страниц, а второй занимается непосредственно шаблонизацией и преобразованием в JSON разных данных. Это достаточно объемная часть, заслуживающая быть выделенной отдельным компонентом.

Layout — это объект, который, во-первых, знает, какие еще контроллеры, помимо главного, надо запустить, принимает результат их работы и знает как его использовать. Это происходит до шаблонизации. Обычно, Layout создает базовый ParseResult_Blitz (который при шаблонизации будет преобразован в HTML при помощи шаблонизатора Blitz). Устанавливает результат работы главного контроллера в блок CENTER, принимает на вход результат работы контроллера сайдбара и устанавливает в SIDEBAR. А сама шаблонизация произойдет позже. То есть под сборкой блоков понимается именно подготовка структуры.

Конечно, можно было бы и на Symfony и на каком-то другом фреймворке сделать подобное, но вопрос в сроках, поддержке и уровне вхождения остается, на мой взгляд, открытым.
Событийная архитектура — да, тот же очень удобный принцип, но реализация другая. Главное отличие — у нас отрисовка данных (шаблонизация) осуществляется в последний момент. А также сборкой разных блоков занимается сам Application при помощи объектов Layout.
Такое желание есть, но пока фреймворк сыроват и не подготовлен к этому. Поживет еще какое-то время, причешем и, думаю, никаких преград открыть в open source не возникнет.
Ничто не мешает сделать вложенный роутинг, но таких задач не появлялось. Пока столкнулись лишь с ситуацией, когда в маршруте указан Action, результатом работы которого будет другой Action, но с тем же Request-ом. Например, возвращает специальный Action для неавторизованного пользователя.

Шаблоны с action-ами никак не связаны. Контроллер явно создает объект ViewModel, на основе имени которого будет найдет класс View, например ViewModel_Profile -> View_Web_Profile. А дальше в каждом конкретном случае View сама решает откуда брать шаблон, какие пути использовать и т.д.
Пока что не требовалось, а делать максимально универсально задачи не стояло.
Во-во! Логика именования и порядок аргументов в функциях PHP настолько суровые, что приходится постоянно уточнять.
1. Для пользовательских данных используется MySQL. События в демоне, агрегирующем уведомления, хранятся по user_id получателя.

  • Если пользователь удаляется — прошел коммит в MySQL, то в демон отправляется команда — удалить все по user_id. Если команда не прошла, то консистентность может быть нарушена.
  • Перед каждой отправкой мы проверяем, что получатель не удален.
  • Каждого пользователя, который отправил вам уведомления мы также проверяем, что он не удален. Таким образом невозможна ситуация, когда вам придет уведомление, в котором фигурируют удаленные пользователи (на момент отправки, конечно).


2. 25kreq/s — это на 4 демона, то есть на каждый по 6 в пике. (подробнее могут ответить наши системные программисты)

3. Событие не будет продублировано. Отданные скрипту уведомления демон внутри себя откладывает в специальную очередь и ждет, когда ему подтвердят отправку специальной командой — cancel(timeout, flags) или confirm. По умолчанию он по таймауту очистит эту уведомления командой confirm. Второй раз он может отдать то же уведомление, если мы его отложили командой cancel на некоторое время с какими-то флагами, которые означают причину. К примеру, причина — пользователь еще онлайн.
Это все, в основном, шардинг пользовательских данных — есть X серверов баз данных, на каждом крутится Y схем, в каждой из которых Z таблиц по N пользователей в каждой.
У нас 2 дата-центра — один в Америке, другой в Европе, и данные пользователей по ним распределены соответствующим образом. Поэтому в каждом из них в определенное время нагрузка все таки падает.
Всю задачу от начала и до конца ведет один php-программист. Допустим, мне пришла задача, в ней PRD с макетами. Я сразу ставлю задачу в пул команды Frontend, ссылаясь на родительскую задачу. Если нужен биллинг, к примеру, это промо акция и при переходе по ссылке мне надо начислить 100 кредитов, я договариваюсь с человеком из биллинга, который отвечает за промо-акции и ставлю на него подзадачу. Если я не знаю, кто среди них может мне помочь, тогда я обращаюсь к менеджеру.

Когда я ставлю задачу на верстку макетов и на заведение новой промо-акции, я всем говорю одну ветку в git, в которой необходимо вести разработку. То есть синхронизировать ничего не надо, я лишь дожидаюсь пока будут сделаны подзадачи, параллельно подготавливая свою часть. Далее я свожу все вместе, проверяю и отправляю на тестирование.
Полного ТЗ у нас не бывает, есть именно продуктовый документ, в комментариях к которому действительно много чего может обсуждаться. Если в процессе разработки мне что-то не понятно, я могу позвонить менеджеру и уточнить вопрос, а в комментарии к тикету дописать «договорились с менеджером, что полоски будут синего цвета», чтобы избежать вопросов от тестировщиков.

Как функционал работает с технической точки зрения, этот документ может описывать, но очень поверхностно. Обычно мы пишем такую документацию постфактум на особо сложные участки системы.
Нет, мы ничего не отключаем (возможно только для обновления ПО). Просто подбирается время, когда низкий трафик, чтобы не создавать проблем пользователям и выполняется альтер. Когда на все сервера накатились изменения, то да, мы выкладываем код, который их использует.
Специфика такая, что править базу приходится достаточно редко, поэтому у нас нет большой необходимости в скриптах миграции. Небольшие изменения вносятся руками прямо в консоли mysql. Когда надо очень много таблиц обновить (к примеру таблицы, по которым шардятся пользователи, их тысячи), то тут конечно системный администратор запускает скрипт, который обходит базы и выполняет sql запрос.
Простые и быстрые правки делают разработчики самостоятельно. Если надо обновить сотню баз, такие альтеры осуществляет отдел системного администрирования в низах трафика. Самое частое обновление схемы — это добавление новых полей, поэтому никаких проблем не возникает.

Если нужно изменить существующие поля:
1. пишут код совместимый со старой и новой схемой работы, релизят его
2. вносят правки в базы
3. оставляют код, работающий по новой схеме
Менеджер проектов, как у нас любят говорить, работает в основном со списками и осуществляет первичную приемку задач. Дальше уже задачу целиком ведет разработчик, а менеджер следит за ее статусом и сроками. Зачастую задачу сразу можно отнести к тому или иному компоненту, поэтому она достаточно быстро минует менеджера проектов и попадает в пул задач соответствующей группы разработчиков. Когда разработчик берет задачу, если там что-то не понятно, то он сам все уточняет у продуктового менеджера. Отсюда бутылочного горлышка в виде менеджера не создается, но возрастает ответственность разработчика, которому приходится самостоятельно переводить с «птичьего». Конечно, при необходимости менеджер разруливает спорные вопросы и разрастания требований. К примеру, если product team очень хочет внести какие-то существенные изменения, мы можем запланировать вторую итерацию для этого проекта.
Ветка билда на завтра создается сегодня, и сегодня же туда начинают домерживаться протестированные задачи до определенного часа. Если какая-то задача уже смерженная в билд не работает и быстрым фиксом никак не поправить, ее откатывают из билда (раньше git revert, сейчас как-то хитрее, т.к. реверт добавляет проблем впоследствии), либо просто собирают билд заного без этой задачи (создается ветка от мастера и туда заного мержатся задачи).

Для патчей в билд у нас сделан специальный интерфейс, в который достаточно отправить diff правок, после чего они будут просмотрены и закомичены прямо в билд релиз-инженером.
Как попадает на машины уже ответили чуть ниже, на эту тему был целый доклад addconf.ru/event.sdf/ru/add_3/authors/YuriyNasretdinov/786

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Registered
Activity