[Разработка веб-сайтов, PHP, Symfony, API] НЕкостыль: gRPC-клиент на PHP в продакшене
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет! Я хочу показать, что завести gRPC на PHP — это нормальное боевое решение, которое пишется быстро, легко разворачивается и может быть для вас проще, чем сокеты.
Сначала все работало на REST и работало хорошо, но начался рост…
Skyeng постоянно взаимодействует с учениками: периодически нам надо позвонить — чтобы подтвердить запись на пробный урок или, например, уточнить, все ли хорошо, если человек пропустил занятие.
На заре школы работа со звонками велась вручную, но бизнесу быстро захотелось как-то автоматизировать и анализировать работу операторов. Это помог сделать Voximplant. Мы до сих пор пользуемся их технологиями — удобно.
Чтобы операторы не слушали гудки, не тратили время на прозвон недоступных номеров и так далее, у ребят есть PDS (predictive dialing system) — система автоматического дозвона. Она берет два пула — операторов и клиентов, и по ходу прозвона вычисляет контактность базы, задавая скорость дальнейшего набора номеров. Идея в том, чтобы операторы и клиенты как можно меньше ждали на линии.
Долгое время все работало по примерно такой схеме.
Например, мы загружаем PDS список из 1000 номеров — и знаем, что сейчас у нас 50 операторов. Начинаем прозванивать первые 100.
- Номер недоступен — обрабатываем сценарий на JS, отправляем на endpoint номер и его статус, пишем в базу факт неудачного звонка.
- Срабатывает автоответчик: все то же самое, но со статусом «автоответчик».
- Происходит дозвон до клиента — он берет трубку и говорит «Алло». В это время из пула операторов срочно подыскивается первый подходящий: мы знаем, что если держать человека «на проводе» больше двух секунд, он просто положит трубку.
При росте начались сложности. PDS вычисляет контактность базы — и набирает еще сколько-то номеров. А параллельно считает длительность текущих разговоров и обновляет статистику, чтобы балансировать время ожидания операторов и клиентов. Упор всегда делается на удобство клиента (те самые пара секунд), но время простоя оператора то не должно затягиваться. Нормально, если это 30-40 секунд. На практике случалось, что утилизация времени операторов достигала почти 30% — они долго сидели в ожидании, это было критично.
Также мы стали сталкиваться с кейсами двойного прозвона. С утра мы собирали большой колл-лист на тысячи номеров и загружали его в систему. Но параллельно через сайт приходили новые потенциальные ученики — опять же, опытным путем бизнес установил, что их надо прозвонить в приоритетном порядке в ближайшие часы после заявки. Опции «докинуть номеров» у PDS не было. Поэтому мы останавливали ее, обновляли лист и снова запускали его в работу. Но на момент остановки часть номеров могла уйти в набор — а вот их статусы в базу еще не пришли. Они не помечались как прозвоненные и, бывало, что с человеком поговорили, а через две минуты ему набирает следующий оператор… Мы не могли пометить, что номер отдан в прозвон, на своей стороне: так как работали сразу с тысячами номеров, это вызывало большие тормоза на нашей базе.
Тогда ребята из Voximplant дали нам нам прототип своей новой PDS — более продвинутого решения, которое получило название PDS2. И нам надо было как-то подключиться к нему.
Почему выбрали gRPC? И почему не подошел клиент на Go
Ох, у gRPC много классных фич:
- Protobuf как инструмент описания сериализации типов данных — мы описываем протокол в протофайл, это быстро.
Вот типичный protobuf-файл — очень похож на JSON, всё достаточно просто:
syntax = "proto3" ;
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3
}
- Есть gRPC-плагин, который позволяет сгенерировать весь необходимый код из протофайла — сервис, типы, PDS-клиент, в нашем случае. Единственное, что он не генерит, это серверную часть на PHP.
- HTTP/2 в качестве транспорта — можно прекратить выполнение запроса на сервере, а еще переиспользовать один cокет для нескольких параллельных запросов.
- Вместо набора «domain.com/сервис/коллекция/ресурс/запрос? параметр=значение», как в REST, есть только сервис. Все остальное описывается через Protobuf в терминах нашей модели и ее событий.
Однако, выбрали не из-за фич: просто выбора не было — PDS2 общалась только по gRPC.
А вот с Go мы попробовали. Прототип клиента от разработчиков из Voximplant какое-то время крутился в проде, но его тяжело было поддерживать. PHP основной язык в Skyeng, на нем написано почти все. И мы поняли, что надо тащить в Go-клиент много кода, а затем поддерживать его и в клиенте, и PHP-части. Например, у нас были проблемы с таймзонами — и было решение, но на PHP. И это всё приходилось уносить на тот Go-клиент.
Долго обсуждали это с тимлидом, и в итоге решили, что проще затянуть все на PHP. Спустя месяцы эксплуатации понимаю, что это было верное решение.
Что делать, если PHP не завезли? Написать свое решение — это (почти) просто
Я следовал рекомендациям с gRPC.io для PHP. В принципе, там описано все, что нужно.
Был лишь один забавный нюанс. Пару дней искал решение, как сгенерировать код с неймспейсами в нашем протофайле. Все сгенерил, все нормально, только их не хватает. В итоге засел перечитывать всю документацию. Оказалось, оно называется packages.
Так что, если тоже зададитесь вопросом, всё достаточно просто: пишем в файле
package foo.bar;
message MyMessage {}
И это сгенерирует вот такой namespace.
Foo\Bar\MyMessage
Детали по ссылке.
Как это работает. При генерации мы задаем необходимые параметры подключения к Voximplant, стартуем, и у нас получается бесконечный цикл, который постоянно слушает наш стрим. Наш клиент — по факту, обычный демон.
Вот пример от Voximplant. Наш бандл показать не могу: он сильно разросся за счет сложной и специфичной для нас логики.
Что в итоге
Наш клиент вместе с supervisorD крутится на проде с января, он стабилен. В сочетании c супервизором это почти демон — если что, супервизор поднимет и запишет падение к себе.
Проблемы роста мы решили.
Благодаря демону мы отгружаем номера по запросу, динамически, маленькими порциями — по 50 за раз. И теперь, если у нас появляются какие-то «горячие» номера с морды сайта, он уже знает, что эти номера имеют самый высокий приоритет — когда от Voximplamt приходит новый запрос, отправляет их. У нас появилась гибкость.
А еще, время ожидания операторов сократилось примерно до 20 секунд, — но это уже чисто за счет лучших алгоритмов самой PDS2, которую писали не мы.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, JavaScript, Программирование] Сниппет, расширение для VSCode и CLI. Часть 2
- [CMS, PHP, Laravel] Как обновить October CMS до Laravel 6?
- [API] Демистификация JWT
- [Разработка веб-сайтов, Учебный процесс в IT, Карьера в IT-индустрии] Frontend-образование или как могут помочь курсы новичку
- [Разработка веб-сайтов, Scala, API, ООП, Функциональное программирование] Изучаю Scala: Часть 5 — Http Requests
- [PostgreSQL, .NET, API, C#] Development of “YaRyadom” (“I’mNear”) application under the control of Vk Mini Apps. Part 1 .Net Core (перевод)
- [PHP, Zend Framework] Простой Telegram бот, который задаёт 1 вопрос
- [PHP, Совершенный код] Мнение о PSR-1: Базовый стандарт написания кода
- [Программирование] kotlinx.coroutines 1.4.0: представляем StateFlow и SharedFlow (перевод)
- [Программирование, Go, Микросервисы] Создаем высокопроизводительные микросервисы с помощью gRPC, Ballerina и Go (перевод)
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_php, #_symfony, #_api, #_php, #_grpc, #_blog_kompanii_skyeng (
Блог компании Skyeng
), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_php, #_symfony, #_api
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:53
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет! Я хочу показать, что завести gRPC на PHP — это нормальное боевое решение, которое пишется быстро, легко разворачивается и может быть для вас проще, чем сокеты. Сначала все работало на REST и работало хорошо, но начался рост… Skyeng постоянно взаимодействует с учениками: периодически нам надо позвонить — чтобы подтвердить запись на пробный урок или, например, уточнить, все ли хорошо, если человек пропустил занятие. На заре школы работа со звонками велась вручную, но бизнесу быстро захотелось как-то автоматизировать и анализировать работу операторов. Это помог сделать Voximplant. Мы до сих пор пользуемся их технологиями — удобно. Чтобы операторы не слушали гудки, не тратили время на прозвон недоступных номеров и так далее, у ребят есть PDS (predictive dialing system) — система автоматического дозвона. Она берет два пула — операторов и клиентов, и по ходу прозвона вычисляет контактность базы, задавая скорость дальнейшего набора номеров. Идея в том, чтобы операторы и клиенты как можно меньше ждали на линии. Долгое время все работало по примерно такой схеме. Например, мы загружаем PDS список из 1000 номеров — и знаем, что сейчас у нас 50 операторов. Начинаем прозванивать первые 100.
При росте начались сложности. PDS вычисляет контактность базы — и набирает еще сколько-то номеров. А параллельно считает длительность текущих разговоров и обновляет статистику, чтобы балансировать время ожидания операторов и клиентов. Упор всегда делается на удобство клиента (те самые пара секунд), но время простоя оператора то не должно затягиваться. Нормально, если это 30-40 секунд. На практике случалось, что утилизация времени операторов достигала почти 30% — они долго сидели в ожидании, это было критично. Также мы стали сталкиваться с кейсами двойного прозвона. С утра мы собирали большой колл-лист на тысячи номеров и загружали его в систему. Но параллельно через сайт приходили новые потенциальные ученики — опять же, опытным путем бизнес установил, что их надо прозвонить в приоритетном порядке в ближайшие часы после заявки. Опции «докинуть номеров» у PDS не было. Поэтому мы останавливали ее, обновляли лист и снова запускали его в работу. Но на момент остановки часть номеров могла уйти в набор — а вот их статусы в базу еще не пришли. Они не помечались как прозвоненные и, бывало, что с человеком поговорили, а через две минуты ему набирает следующий оператор… Мы не могли пометить, что номер отдан в прозвон, на своей стороне: так как работали сразу с тысячами номеров, это вызывало большие тормоза на нашей базе. Тогда ребята из Voximplant дали нам нам прототип своей новой PDS — более продвинутого решения, которое получило название PDS2. И нам надо было как-то подключиться к нему. Почему выбрали gRPC? И почему не подошел клиент на Go Ох, у gRPC много классных фич:
Вот типичный protobuf-файл — очень похож на JSON, всё достаточно просто: syntax = "proto3" ;
message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3 }
Однако, выбрали не из-за фич: просто выбора не было — PDS2 общалась только по gRPC. А вот с Go мы попробовали. Прототип клиента от разработчиков из Voximplant какое-то время крутился в проде, но его тяжело было поддерживать. PHP основной язык в Skyeng, на нем написано почти все. И мы поняли, что надо тащить в Go-клиент много кода, а затем поддерживать его и в клиенте, и PHP-части. Например, у нас были проблемы с таймзонами — и было решение, но на PHP. И это всё приходилось уносить на тот Go-клиент. Долго обсуждали это с тимлидом, и в итоге решили, что проще затянуть все на PHP. Спустя месяцы эксплуатации понимаю, что это было верное решение. Что делать, если PHP не завезли? Написать свое решение — это (почти) просто Я следовал рекомендациям с gRPC.io для PHP. В принципе, там описано все, что нужно. Был лишь один забавный нюанс. Пару дней искал решение, как сгенерировать код с неймспейсами в нашем протофайле. Все сгенерил, все нормально, только их не хватает. В итоге засел перечитывать всю документацию. Оказалось, оно называется packages. Так что, если тоже зададитесь вопросом, всё достаточно просто: пишем в файле package foo.bar;
message MyMessage {} И это сгенерирует вот такой namespace. Foo\Bar\MyMessage
Детали по ссылке. Как это работает. При генерации мы задаем необходимые параметры подключения к Voximplant, стартуем, и у нас получается бесконечный цикл, который постоянно слушает наш стрим. Наш клиент — по факту, обычный демон. Вот пример от Voximplant. Наш бандл показать не могу: он сильно разросся за счет сложной и специфичной для нас логики. Что в итоге Наш клиент вместе с supervisorD крутится на проде с января, он стабилен. В сочетании c супервизором это почти демон — если что, супервизор поднимет и запишет падение к себе. Проблемы роста мы решили. Благодаря демону мы отгружаем номера по запросу, динамически, маленькими порциями — по 50 за раз. И теперь, если у нас появляются какие-то «горячие» номера с морды сайта, он уже знает, что эти номера имеют самый высокий приоритет — когда от Voximplamt приходит новый запрос, отправляет их. У нас появилась гибкость. А еще, время ожидания операторов сократилось примерно до 20 секунд, — но это уже чисто за счет лучших алгоритмов самой PDS2, которую писали не мы. =========== Источник: habr.com =========== Похожие новости:
Блог компании Skyeng ), #_razrabotka_vebsajtov ( Разработка веб-сайтов ), #_php, #_symfony, #_api |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:53
Часовой пояс: UTC + 5