- PVSM.RU - https://www.pvsm.ru -
Поэтому мы вышли из беты и сделали релиз!
Что нового в релизе? Зачем вообще нужен userver и какие существуют технологии для обеспечения надёжной работы серверных приложений? Можно ли воспользоваться крутыми C++ классами из userver, не используя при этом корутины? Какие дальнейшие планы? Ответы на все эти вопросы ждут вас под катом.
После выхода в бету [2] мы получили много фидбэка и постарались реализовать все запрошенные улучшения:
Подробный список всех изменений можно найти в changelog [3].
Мы развиваем фреймворк по модели green trunk, а это значит, что каждый комит в userver проходит тесты и оказывается в нашем проде. Так что просто берите последнюю версию из develop-ветки Гитхаба и пользуйтесь, если вам не требуется повышенная стабильность интерфейсов.
Разумеется, все остальные функции никуда не делись: HTTP- и HTTPS-клиенты, PostgreSQL, Mongo, Redis, HTTP-сервер, поддержка различных форматов данных, gRPC, congestion control и всё остальное. Простота написания кода тоже сохранилась:
Один из самых частых вопросов после выхода в опенсорс: «А вот есть библиотека X или технология Y. Стоит мне использовать что-то из них или userver?»
Зависит от ваших потребностей. Фреймворк userver хорош тем, что он производителен, прост в использовании, а все его части проинтегрированы друг с другом. Например, если вы пользуетесь базой данных PostgreSQL, то сразу получаете её метрики, быстрый бинарный протокол отправки (недоступный из libpq), статистику по времени выполнения запросов, pipelining, возможность менять конфигурацию без рестарта сервиса, автоматическое создание prepared statements, Deadline Propagation, указание таймаутов на выполнение запросов и многое другое.
Вот несколько ситуаций, в которых удалось избежать больших неприятностей благодаря функциям, доступным «из коробки».
userver пишет множество метрик. На них у нас настроена автоматика, которая предупреждает разработчика в случае отклонения от допустимых значений. И вот разработчику как раз прилетело такое предупреждение: «Ваш сервис начал подозрительно часто отвечать не 200 HTTP-кодом».
Идём читать метрики. На общем графике запросов сервиса ничего подозрительного нет, но вот график одного из REST API URL настораживает:
Что-то не так именно с GET запросами на /v1/cached-value
! Теперь мы знаем, какой части сервиса поплохело, и можем целенаправленно поискать логи именно этого URL с кодом ответа 404 (например, с помощью Kibana):
... level=INFO meta_type=/v1/cached-value method=GET uri=/v1/cached-value?id=experiment_42 meta_code=404 ...
Смотрим на графики или в логи и понимаем, что на некоторых инстансах нашего сервиса почему-то нет данных для experiment_42
. Дальше идём к поставщику данных и выясняем, как так получилось.
В этой ситуации помогли следующие технологии userver:
Команда разработчиков сделала крутую фишку, благодаря которой заказы и такси приезжают к пользователям на минуту быстрее. Обложили тестами, проверили на тестовых окружениях, выкатили в прод… а потом обнаружили опасную вещь: есть шанс с вероятностью 1 к 100 000, что запрос уронит сервис из-за ошибки в коде.
Ребята порадовались, что в userver встроен механизм перезапросов. Когда сервис падает, запрос приходит уже на другой инстанс, и он благополучно отвечает. Пользователи получают свой заказ и уезжают на такси — для них всё хорошо.
Ну а потом разработчики мгновенно отключили новую функциональность через динамический конфиг и для этого не потребовалась перевыкатка.
if (dynamic_config[kFasterDeliveryV5]) {
return do_fast_delivery_v5(params);
}
return do_fast_delivery_v4(params);
В спокойной обстановке разработчики стали смотреть по логам параметры запросов. Через встроенный трейсинг запросов они выяснили, что один из вышестоящих сервисов иногда не проставляет параметр — в этом случае с шансом 1 к 10 всё может упасть. Зарепортили багу в вышестоящий сервис.
Потом ребята написали тест, в котором поднимают свой сервис и задали пару сотен запросов, роняющих его:
async def test_bad_param(service_client):
for _ in range(200):
response = await service_client.get('/v1/prod', params={'important': ''})
assert response.status == 200
assert response.content == b'Some answer'
Исправили проблему, спокойно перевыкатились — всё заработало как часы.
В этой ситуации помогли следующие технологии userver:
Закончился футбольный матч, все стали вызывать такси и заказывать домой еду. И притом как-то очень не вовремя для нас: всё случилось ночью, когда в дата-центре что-то экстренно меняли. Да ещё один из сторонних сервисов затупил и разом отправил на один инстанс нашего сервиса десяток миллионов запросов…
… и ничего плохого не случилось!
В этой ситуации помогли следующие технологии userver:
И это хорошо, ведь userver нашёл багу в вашем коде! Фреймворк прилагает множество усилий, чтобы упростить разработку и сделать код более надёжным:
Не обязательно. У нас в компании на userver написано как множество микросервисов, так и огромные серверные приложения с кэшами на сотни гигабайт, которые ближе к монолитным приложениям.
Если вы не собираетесь писать серверы, у нас для вас хорошие новости. userver можно использовать для написания консольных приложений, использующих корутины (например, netcat или dns_resolver).
Но что делать, если вы уже давно работаете над своим проектом и вам не нужен целый фреймворк? Вам лишь не хватает небольших вспомогательных C++ классов и функций, о которых мы так часто рассказываем на конференциях. Для вас у нас тоже есть хорошие новости: с недавнего времени userver предоставляет CMake-цель userver-universal
, которая не содержит корутин и драйверов. Только всякие полезные C++ мелочи:
std::chrono::steady_clock
.
Полный список функций здесь — userver universal [17].
После релиза работа не останавливается. Мы продолжим улучшать производительность и внедрять новую функциональность и постараемся к следующему релизу реализовать драйверы для YDB и Кафки, а ещё упростить конфигурирование и заняться пакетированием.
Заглядывайте к нам в Гитхаб [1]. Надеемся, что фреймворк вам пригодится и понравится!
Спасибо всем, кто контрибьютил и багрепортил в userver. Вы лучшие!
Автор: Antony Polukhin
Источник [18]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/387209
Ссылки в тексте:
[1] userver: https://github.com/userver-framework/userver
[2] выхода в бету: https://habr.com/ru/companies/yandex/articles/674902/
[3] changelog: https://userver.tech/da/d9a/md_en_2userver_2roadmap__and__changelog.html
[4] utils::FastPimpl: https://userver.tech/d8/d4b/classutils_1_1FastPimpl.html
[5] cache::LruMap: https://userver.tech/d1/d2c/classcache_1_1LruMap.html
[6] cache::LruSet: https://userver.tech/d5/d9c/classcache_1_1LruSet.html
[7] utils::TrivialBiMap: https://userver.tech/d9/dbf/classutils_1_1TrivialBiMap.html
[8] utils::FastScopeGuard: https://userver.tech/d0/d34/classutils_1_1FastScopeGuard.html
[9] formats::yaml::Value: https://userver.tech/da/dc1/classformats_1_1yaml_1_1Value.html
[10] formats::json::Value: https://userver.tech/de/d91/classformats_1_1json_1_1Value.html
[11] decimal64::Decimal: https://userver.tech/df/dec/classdecimal64_1_1Decimal.html
[12] utils::FixedArray: https://userver.tech/d6/d84/classutils_1_1FixedArray.html
[13] crypto::Certificate: https://userver.tech/da/dd6/classcrypto_1_1Certificate.html
[14] crypto::PrivateKey: https://userver.tech/d8/db8/classcrypto_1_1PrivateKey.html
[15] crypto::PublicKey: https://userver.tech/d5/d1f/classcrypto_1_1PublicKey.html
[16] utils::datetime::SteadyCoarseClock: https://userver.tech/d5/d89/structutils_1_1datetime_1_1SteadyCoarseClock.html
[17] userver universal: https://userver.tech/d7/d67/group__userver__universal.html
[18] Источник: https://habr.com/ru/companies/yandex/articles/760244/?utm_source=habrahabr&utm_medium=rss&utm_campaign=760244
Нажмите здесь для печати.