Monzo: как построить бэкенд банка нового поколения

Оливет Битти, глава технического департамента английского необанка Monzo, говорит о выстроенной его командой архитектуре бэкенд-совокупностей банка.

Бэкенд в Monzo строился с нуля. Из первичных требований была отмечена необходимость для совокупности быть дешёвой 24 х 7 и масштабируемой до миллионов клиентов в мире — это стало причиной тому, что сначала совокупность разрабатывалась как коллекция распределенных микросервисов. Для стартапа на ранней стадии данный подход необыкновенен; в большинстве случаев, такие компании выбирают уже привычную централизованную архитектуру с привычными фреймворками и реляционными базами данных.

Но в Monzo данный вариант не рассматривался, поскольку несет за собой привычные «детские заболевания» — единую точку отказа, необходимость в периодическом отключении с целью проведения технического обслуживания и нехорошую масштабируемость.

На старте создания собственной платформы у Monzo было всего три разработчика, и приходилось быть прагматичными

Большие компании, такие как Amazon, Netflix и Twitter, продемонстрировали, что единые монолитные базы данных не масштабируются на разработчиков и большое количество пользователей — а вдруг банк собирается выходить на множество разных рынков с неповторимыми требованиями на каждом, то ему просто нужно будет держать большое количество команд, трудящихся над различными частями продукта. Всем этим группам придется самостоятельно осуществлять контроль собственный процесс разработки, масштабирования новых и вывода версий без необходимости координации упрочнений с другими командами. Следовательно, процесс разработки должен быть распределенным и декомпозированным, как и продукт.

На старте создания собственной платформы у Monzo было всего три разработчика, и приходилось быть прагматичными — были выбраны уже привычные разработки, каковые вели в нужном направлении, и разработка велась с учетом того, что программисты в будущем постоянно смогут кардинально поменять тот либо другой модуль.

Monzo: как построить бэкенд банка нового поколения

При запуске тестирования бета версии бэкенд Monzo включал в себя около 100 микросервисов. на данный момент их около 150, и команда разработки выросла соответственно. Так как получение банковской лицензии было уже практически решенным делом, команда пересмотрела кое-какие архитектурные подходы и пришла к необходимости сфокусировать работы на следующих направлениях:

  • Управление кластером.
  •  Многоязычные сервисы.
  • RPC-транспорт, снабжающий сообщение компонентов.
  • Асинхронный обмен сообщениями.

Давайте разберем каждое из этих направлений подробнее.

Управление кластером           

Команде Monzo был нужен действенный и автоматизированный метод руководить громадным числом серверов, распределять между ними нагрузку и реагировать на их выход из строя.

  • Для чего это необходимо?

В случае если вам нужно выстроить отказоустойчивую гибко масштабируемую совокупность, то у вас должна быть возможность додавать и удалять новые сервера: по мере того как совокупность начинается, сервера выходят из строя либо изменяются требования пользователей. Запускать по одному сервису на хосте — трата ресурсов (так как сервису смогут быть не необходимы все ресурсы хоста), а классический подход ручного распределения сервисов по хостам через чур сложно масштабируется.

  • Какое ответ применили?

Контейнеризация — это комбинация разработок, используемых в ядре Linux

В Monzo применяют планировщики для кластеров, каковые разворачивают приложения на серверах в соответствии с ресурсными требованиями, масштабируют их при необходимости и заменяют сервера при выходе из строя. В этом оказывает помощь контейнеризация, и в частности Docker. Контейнеризация — это комбинация разработок, используемых в ядре Linux, объединенная в образ, что разрешает отделить приложение от ОС и изолировать от вторых приложений на том же сервере.

Так, совокупности управления кластером приходится иметь дело только с контейнерами.

В Monzo применяют планировщик Kubernetes, запускаемый на серверах с CoreOS. Данный планировщик тесно интегрируется с Docker и известен тем, что употребляется в эксплуатации Гугл.

  • Что это дало?

Не считая увеличения надежности Kubernetes разрешил Monzo снизить затраты на инфраструктуру — сейчас она обходится банку всего в четверть от привычных затрат. К примеру, в случае если раньше для выпуска на production употреблялось пара дорогих производительных серверов с CI-совокупностью Jenkins, то сейчас Kubernetes применяет для работы свободные ресурсы на уже имеющейся инфраструктуре — фактически безвозмездно. Подобный подход разрешает верить в том, что ресурсоемкие, но низкоприоритетные задачи (такие, как формирование отчетов) не повлияют на производительность критически ответственных сервисов, применяемых клиентом.

Многоязычные сервисы

Главным языком разработки микросервисов в Monzo был и остается Go, но в неспециализированную совокупность бесшовно включаются модули на вторых языках.

  • Для чего это необходимо?

Применение языка Go разрешает создавать сервера, снабжающие параллельную работу с низкими задержками, но ни одна экосистема языка не содержит всех инструментов, нужных для банка. В Monzo поняли важность применения громадного количества инструментов, как коммерческих, так и с открытым исходным кодом, и грядущую эволюцию архитектуры платформы по мере трансформаций в разработках.

В Monzo выделили повторно применяемый код в отдельные сервисы

В большинстве случаев фрагменты кода, каковые применяют пара приложений, принято объединять в библиотеки, но данный подход не годится в многоязычной совокупности — если бы было нужно реплицировать и поддерживать в актуальном состоянии сотни и тысячи тысяч строчков повторно применяемого кода любой раз, в то время, когда к платформе подключается сервис на новом языке, все это достаточно скоро стало бы неуправляемым.

  • Какое ответ применили?

В Monzo выделили повторно применяемый код в отдельные сервисы. Дабы заблокировать эти с целью проведения в них трансформаций, сервис фиксирует их в распределенном хранилище etcd посредством чистого RPC. Все многоязычные сервисы, применяющие неспециализированную инфраструктуру (включая базы данных и очереди сообщений), реализуются подобным образом.

  • Что это дало?

Переход на подобные сервисы разрешил уменьшить количество кода для каждого языка — нужен лишь клиент для вызовов RPC. Данный подход уже на данный момент разрешает Monzo писать сервисы на Java, Python и Scala.

RPC-транспорт

В то время, когда много сервисов распределено между серверами, датацентрами а также континентами, успех совокупности зависит от объединяющего компоненты слоя удаленного вызова процедур (RPC, remote procedure calling), что может обеспечить работоспособность при выхода из строя отдельных компонентов, снизить задержки при передаче данных и оказать помощь в понимании поведения совокупности при работе.

  • Для чего это необходимо?

В совершенстве запросы к элементам совокупности производятся через уже имеющиеся соединения

С учетом того что разработка сервисов ведется на множестве языков, протокол для удаленного вызова процедур обязан их все поддерживать. Победителем стал HTTP — у каждого языка имеется под него стандартные библиотеки.

Но для того дабы создать надежную мультисервисную платформу, к слою RPС было нужно добавить следующие элементы:

  • Балансировка нагрузки. Большая часть HTTP-библиотек поддерживают балансировку кругового обслуживания (round-robin) на базе DNS, но это не самый разумный вариант. В совершенстве балансировка нагрузки обязана выбирать нужный хост, основываясь одновременно и на минимизации отказов, и на времени отклика — так кроме того при утрата части серверов и наличии медленных реплик совокупность останется работоспособной и стремительной.
  • Автоматические повторы запроса. В распределенных совокупностях сбои неизбежны, и в случае если приводимый к сервису не имеет возможности обслужить идемпотентный (в то время, когда при повторном выполнении итог будет таким же, что и при начальном) запрос, тот возможно безболезненно перенаправлен на другую реплику сервиса, тем самым поддерживая работоспособность совокупности в целом кроме того при выходе из строя отдельных компонент.
  • Пул соединений. Открытие нового соединения на любой запрос весьма не хорошо отражается на времени отклика совокупности. В совершенстве запросы к элементам совокупности производятся через уже имеющиеся соединения.
  • Маршрутизация. Полезно иметь возможность руководить поведением RPC-совокупности на протяжении работы, к примеру при запуске новой версии сервиса возможно направить на него лишь часть трафика. Это разрешает создавать внутреннее и внешнее тестирование — вместо того дабы всецело реализовывать тестовое окружение, возможно вывести в тестовый режим только кое-какие сервисы для некоторых пользователей.
  • Какое ответ применили?

Одна из самые сложных RPC-совокупностей — это Finagle, она выстроена на модульной архитектуре и владеет фактически всей нужной функциональностью. На ее базе создан linkerd, что и применяют в Monzo. Вместо того дабы связываться с другими частями совокупности напрямую, любой компонент платформы Monzo общается с локальной копией linkerd, что направляет запрос к нужному узлу, применяя балансировку нагрузки Power of Two Choices + Peak EWMA.

В случае если идемпотентные запросы не смогут быть выполнены, они машинально возобновляются. Вся логика сотрудничества между сервисами вынесена в RPC-слой, что разрешает писать сервисы на любых языках без необходимости помощи RPC-библиотек.

  • Что это дало?

Это сэкономило время на удаленный запуск процедур и повысило надежность RPC. Он развернут как комплект демонов в Kubernetes, так что сервисы постоянно обращаются к нему на локальном хосте, что пробрасывает запрос дальше. В тех случаях, в то время, когда реплики обоих сервисов, связь между которыми снабжает RPC, находятся физически на одном сервисе, запрос кроме того не уходит в сеть.

Асинхронный обмен сообщениями

Дабы бэкенд был производительным и надежным, используются очереди сообщений для планирования фонового исполнения задач. Эта механика обязана обеспечивать возможность постановки задания в удаления и очередь из нее, и то, что данные в очереди ни при каких обстоятельствах не будут утрачены.

  • Для чего это необходимо?

Большинство задач в бэкенде Monzo выполняется асинхронно. К примеру, кроме того в то время, когда обработка платежа занимает меньше секунды, бэкенд в течение десятка миллисекунд информирует платежной совокупности об одобрении либо отклонении платежа с карты Monzo. Работы по обработке данных мерчанта, рассылке push-нотификаций а также включение транзакции в поток данных пользователя происходят асинхронно.

Не считая асинхронности, эти шаги не должны быть пропущены. Кроме того в случае если случится неточность, на протяжении которой будет нереально машинально вернуть состояние совокупности, должна быть возможность исправить эти и возобновить процесс. Это определяет следующие требования к асинхронной архитектуре:

  • Высокая доступность. Паблишеры (модули, публикующие сообщения) должны иметь возможность трудиться в режиме «выстрелил-забыл», независимо от отказов серверов либо состояния модулей-слушателей.
  • Масштабируемость. В Monzo желали иметь возможность расширять очередь сообщений без прерывания работы сервиса и без добавления нового «железа» — очередь сама по себе должна быть горизонтально масштабируемой.
  • Персистентность. В случае если узел очереди сообщений выйдет из строя, эти не должны быть утрачены. Совершенно верно так же в случае если выйдет из строя модуль-слушатель, у очереди должна быть возможность повторной доставки сообщения сервису.
  • Воспроизводимость. Нужна возможность воспроизвести поток сообщений с какой-то исторической точки для того, чтобы новые процессы имели возможность обрабатывать исторические эти (к примеру, обучать нейросети, разбирать ретро-выборки, etc).
  • По большей части разовая доставка. Все сообщения должны достигнуть слушателей. Не смотря на то, что, в большинстве случаев, нереально доставить сообщение лишь один раз, в обычном режиме работы очередь не должна создавать множественную доставку.

 

  • Какое ответ применили?

В качестве платформы обмена сообщениями между сервисами в Monzo выбрали Apache Kafka. Ее реплицируемый модульный дизайн разрешает обрабатывать выход узлов из строя и масштабировать платформу по мере необходимости без прерывания обслуживания. Дизайн слушателей в данной платформе также увлекателен: тогда как большая часть вторых платформ держат отдельную очередь для каждого сервиса, в слушатели проходят «курсором» по неспециализированному изданию сообщений.

  • Что это дало?

Это разрешило удешевить совокупность паблишеров / слушателей, уменьшить их требовательность к ресурсам. Так как сообщения сохраняются в издании независимо от событий, их неизменно возможно воспроизвести для определенных сервисов.

 

В завершение хочется обратить внимание на то, что три наиболее значимых компонента, снабжающих цельность и связность бэкэнда Monzo — совокупность управления кластером Kubernetes, совокупность удаленного вызова процедур linkerd и совокупность асинхронного обмена сообщениями Kafka — это безвозмездно распространяемые совокупности с открытым исходным кодом. Возможно, архитектурные перемены в банке — это не верно уж и дорого?

MONZO — Walkthrough(Android \ iOS) — Trevithick Engine

Интересные записи

Похожие статьи, которые вам, наверника будут интересны: