Мегапосты:
Обо мне

-------------------------------------

Мой стэк:

-------------------------------------

PHP: Symfony (3,4 (c 4-кой работал больше)), Yii (1,2), Laravel 5.

JS: Jquery, немного Vue.js

DB: MySQL, Postgres (на уровне ORM), MongoDb (на уровне ORM)

OS: Linux (Ubuntu)

IDE: PhpStorm


-------------------------------------

Решал разноплановые задачи:

-------------------------------------

PHP:

- Тестирование приложений (после написания кода).

- CRUD

- Парсеры веб ресурсов

- Импорты / экспорты большого объема данных в/из файл(а)

- Почтовый интерфейс на базе PHP-MySQL (многопроцессный демон на основе php pcntl - )

- Различные интеграции

- ROBOKASSA

- OnPay

- Интегрирование SOAP сервисов в систему

- Разворачивание REST API

- Системы логирования операций (CRUD) над сущностями (vendor package)

- Разработка микросервиса заказов и интеграция связок с другими микросервисами посредством RabbitMQ

- Разработка микросервиса — Picking (сборка заказа) -заказов и интеграция связок с другими микросервисами посредством RabbitMQ

- Разработка микросервиса — Warehous Mаnаgеment ( сборка заказов в сторонних системах ) - заказов и интеграция связок с другими микросервисами посредством RabbitMQ

- Разработка микросервиса Order service management

- Оптимизация приложения:

- оптимизация запросов посредством EXPLAIN (MySQL, Postgres)

- разработка системы кеширования (

Yii2: хранение ключей в бд с выводом в интерфейс — для возможности сброса конкретной части кеша вручную), Symfony: настройка кратковременного кеша (от 5 до 30 сек) через аннотацию (аннотация к сущности для именования ключа кеша и в целом обозначения необходимости кеширования)

)

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

- дробление больших запросов на более мелкие

- уменьшение offset | limit в консольных командах, запускаемых посредством демона CRON (для оптимизации расхода памяти и процессорного времени)

- уменьшение количества производимых в консольных скриптах действий за счет выноса некоторых (особо «тяжелых» частей кода в задания для RabbitMQ)


- Система отложенных операций (vendor package)

- Система поиска - использовалась во всех микросервисах компании (vendor package)

- Система автоматического перевода на основе Swager документации свойств и классов.

- Внутренние системы копирования / разделения / склеивания (дубли) заказов

- Много мелких задач (от правки верстки, js, до конфигурирования хоста nginx)

- Разрабатывал внутреннюю систему оповещений пользователей о новых событиях (для CRM)

- Разработка системы обработки Системных событий (с информером в CRM)

- Разрабатывал систему отката заказа по бизнес процессам

- Занимался доработками уже готовых модулей, систем, сервисов, микросервисов


-------------------------------------

Мои компетенции и опыт

-------------------------------------


##### 1. Подробнее про опыт работы с высокими нагрузками


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

Проект medbooking.com - Монолитное приложение.

Тематика: агрегатор:

- медицинских организаций

- врачей (Москва, Санкт-Петербург, Московская область и другие города)

На проекте medbooking.com по статистике было от 100 до 500 тыс уников в сутки в будни и до 50 тыс в выходные.

Сервер: Debian, 4 ядра, 8 гигов ОЗУ, обычный хард (точные характеристики не помню уже).


Назвать это хайлоадом нельзя по идее в сравнении с соц сетями (facebook.com, instagram.com и т. д.), но нагрузка на сервер была высокой (load overage достигал в пик нагрузки более 30, при допустимых 4).


Стек:

Бэкенд: PHP 5.6, Yii (часть проекта была на 1 версии, 40-60 % на второй версии) — на этом этапе я вклинился в проект), MySQL.

Фронтенд: Jquery.


Была поставлена задача на анализ проблем проекта:


В ходе анализа было выявлено:


- отсутствие индексов на полях таблиц, по котором постоянно или проводился поиск или сортировка или группировка или все вместе.

- сессии хранились в базе данных

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

- не оптимизированные участки кода в консольных скриптах

- жадные загрузки через ActiveRecord в коде приложения забирали большую часть данных из базы, но при этом использовали только пару полей из выборки (из разряда SELECT * FROM users ORDER BY id DESC name ASC — а в таблице users 100500 полей — из которых использовалось только id и name)

Оптимизировали:

- после изучения планов запросов (EXPLAIN) - индексы добавили (составные и одиночные).

- сессии перевели на хранение в redis

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

- код тоже оптимизировали, по большей части оптимизаци свелась к тому, что запросы, выполнявшиеся через ActiveRecord переписали на DAO — и прямые запросы скармливали в builder, отошли от работы с объектами ( ActiveRecord ) - перешли на массивы

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

Нагрузка снизилась, но LA был все же выше допустимого значения — 4. Добавили процы — стало 8. Стало легче)


Я также выносил на рассмотрение вопросы:


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

- вынос базы данных на другой сервер (DB, Redis, PHP, Nginx (для статики), Apache были на одном сервере). Вынесли на сервер с SSD — нагрузка уменьшилась, в целом стало легче жить.

- добавление кратковременного кеша (10 -30 — 60 секунд) на наиболее популярные направления. - добавили (продумали инвалидацию кеша).

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

- Балансировка запросов между инстансами приложений (php) — баласировка нагрузки — поставил задачу на DevOps, - не сбылось.

В общем и целом нагрузку удалось снять, что было потом не знаю, уволился из этой компании ))


-------

2) Вторая компания, где коснулся вопросов с высокими нагрузками Webslon — вебстудия, обслуживающая сеть магазинов Leroy Merlin (сеть строительных магазинов по всему миру фактически).


Сервер: 16 гигов ОЗУ, 8 ядер, ОС — Ubuntu. - сервер на котором разместили все микросервисы.


Стек: PHP 7.1, Symfony 4.1, Postgres.


# Предыстория: был монолит на самописной системе, решили разнести этот монолит на микросервисы для возможности гибко масштабироваться. Планировалось запаковать каждый микросервис в docker-контейнер и через kubernetes заниматься их оркестрацией (devOps занимался этим вопросом, но не дожали docker к сожалению).


После запуска большей части микросервисов (далее мкс) (запускали по 2-3 микросервиса). Всего их было около 15-ти (не много но и не мало). Общение между мкс шло поначалу посредством REST API (Json), без какого либо механизма для организации взаимодействия распределенных систем. Но это общение показало себя не эффективно. При росте нагрузки, сервер не справлялся, больше страдал процессор, чем память. Это было ожидаемо, но заказчик требовал запуска, видимо поэтому было решено запускаться так как есть (я вклинился в проект уже на стадии когда было запущено порядка 6 мкс).


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


- Я оптимизировал схему взаимодействия 4 микросервисов по направлениям CRUD операций над заказами. Использовал correlation_id и очереди для ответов. В первый мкс отправялся запрос (по REST), мкс обрабатывал и формировал сообщение для другого мкс, отдавая в ответ клиенту 202 (запрос принят, но не обработан) и correlation_id. Второй мкс, обрабатывал сообщение (консьюмер) и отправлял ответ для запрашивающей стороны в отдельную очередь. Второй мкс, так же формировал запросы для третьего и четвертого мкс, но ответ первому можно было отдавать уже после отработки второго микросервиса, что и делалось. Второй микросервис брал ответ из нужной очереди и формировал ответ клиенту, ответ закреплялся за correlation_id и клиент успешно его получал.

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


##### ##### ##### ##### ##### #####

##### Ссылки на репозитории: #####

##### ##### ##### ##### ##### #####

1) https://bitbucket.org/gambits/yii2-experienced/src/master/BuilderFormByDynamicAttrs/SystemEvent — модуль обработки системных событий (оповещения).


Реализован модуль со всеми рекомендациями SOLID, в 99% все завязано на интерфейсы, а не на конкретные реализации, интерфейсы не перегружены и отвечают за что-то одно. Но решение конечно не лишено недостатков, как и любое другое... (https://bitbucket.org/gambits/yii2-experienced/src/master/BuilderFormByDynamicAttrs/SystemEvent/components/interfaces/)


Тут же в этом модуле:


https://bitbucket.org/gambits/yii2-experienced/src/master/BuilderFormByDynamicAttrs/SystemEvent/components/FormBuilder.php — Builder ActiveForm (Yii2) — в реализации использовал декораторы


(https://bitbucket.org/gambits/yii2-experienced/src/master/BuilderFormByDynamicAttrs/SystemEvent/components/decorator/ - для конфигурирования отдельных полей формы). Конфигурация полей хранится в БД.


2) https://bitbucket.org/gambits/symfony-experienced/src/master/LoggableHistoryEntityBundle/ - Логирование действий с сущностями на основе Loggable behavioral extension for Doctrine2


3) https://bitbucket.org/gambits/symfony-experienced/src/master/MessageExchangeBundle/ - бандл для соверешения отложенных операций (по REST API) — для разгрузки основного процесса, данные складывали в бд, потом обрабатывали.


4) https://bitbucket.org/gambits/symfony-experienced/src/master/api-bundle/Service/CRUD/EnumService.php — получает все Enum классы в проекте (завязано все на пути к директориям, где могут храниться Enum классы), - использовался для вывода всех Enum в документацию по свагеру (в веб интерфейс), с возможностью поиска конкретных Enum — нужно было для получения описания перечислений (возможных значений).



-------------------------------------

Javascript:

-------------------------------------

Jquery: большая часть работы с этой либой связана с тем, чтобы найти готовый плагин, «прикрутить» его и кастомизировать. Кастомизация на основе api предоставляемого плагином.

- Vue.js - изучал для себя и применил на одном из проектов (опыт не большой, но общий смысл понятен).


-------------------------------------

HTML / CSS:

-------------------------------------

- Bootstrap 3, 4

- Semantic

- Metro


--- Сборки ---

-------------------------------------

- Webpack

- Grunt

- Gulp

- Менеджеры пакетов: npm, yarn


-------------------------------------

Опыт работы в команде

-------------------------------------

C 2013 года (от 2 человек до 30 человек). Одновременно над либой работает всегда не более 2-3 человека (как правило).


-----------------------------------------------------------

Качества, которые выделяют мои коллеги:

-----------------------------------------------------------

> Коммуникабельный

> Ответственный

> Самоорганизованный (flow: беру задачу, вникаю и планирую, задаю вопросы, делаю)

> Отзывчивый (легко делюсь знаниями, помогаю более слабым программистам)


-------------------------------------

От себя:

-------------------------------------

> В меру ленивый ) Ищу готовое проверенное решение

прежде чем писать свой "велосипед"


> Люблю море, кофе, свободу - поэтому предпочитаю работать удаленно


> Люблю свою семью, отсюда все вышеперечисленные качества


>> Основной мой опыт связан с серверной разработкой.


--------------------------------------

К сожалению, ни на одном проекте не применялось ни DDD (domain driven desing), ни TDD ("разработка через тестирование"), даже на тех, где использовался enterprise framework Symfony.

-------------------------------------


Профессиональные навыки
Опыт работы
Все проекты
Москва
Ведущий программист
Март 2013 — Декабрь 2019 (6 лет и 10 месяцев)

https://hh.ru/resume/361d7dcdff024b00e40039ed1f72475a4f7a7a

Информация о местах работы на hh.ru, или можете скачать резюме по ссылке https://yadi.sk/i/LgX1kzzmLv0U5g

Высшее образование
Московский университет МВД России
Москва
Факультет: Подготовки специалистов в области информационной безопасности Московского университета МВД России
Сентябрь 2000—Сентябрь 2004 (4 года)
Дополнительное образование
Самообразование
 
PHP, MYSQL, JAVASCRIPT
Июль 2010—По настоящее время (9 лет и 6 месяцев)

PHPPhpunitMySQL
Национальный открытый университет
Москва
PHP, MySQL, AJAX, JS
Октябрь 2011—Декабрь 2012 (1 год и 2 месяца)

PHPJavaScriptMySQLООПAjax
Школа программирования
 
PHP (1,2,3), Javascript (1,2)
Февраль 2011—Август 2011 (6 месяцев)