Как сделать платежную систему своими руками

Habrahabr 2

Привет, Хабр! Мы в RBKmoney новый платежный процессинг написали. С нуля. Ну не мечта ли?

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

Мы расскажем, как написали весь процессинг RBKmoney Payments, так мы его назвали. Как делали его устойчивым к нагрузкам и сбоям оборудования, как придумали возможность его практически линейного горизонтального масштабирования.

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

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

Disclaimer

Со дня последней публикации в нашем блоге прошло ни много ни мало 5 лет. За это время наша команда разработки заметно обновилась, у руля компании теперь новые люди.

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

Суровая реальность такова, что за платежным процессингом находятся платежные организации, вовсе не с распростертыми объятиями принимающие такой трафик, а иногда даже просящие "присылать нам не более 3 запросов в секунду". А на интерфейсы смотрят люди, которые, может быть, впервые в интернете решились что-то оплатить. И любой косяк UX, непонятность и задержка — это повод запаниковать.

Корзина, в которую можно положить покупки даже во время торнадо

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

Подход звучит знакомо, не так ли?

Да, мы вдохновлялись концепцией, описанной в Amazon Dynamo Paper. Парни из Амазона тоже строили все так, что пользователь должен иметь возможность положить книжку в корзину, какая бы жуть ни творилась по ту сторону его монитора.

Конечно, мы не нарушаем законы физики и не придумали как опровергнуть CAP-теорему. Не факт, что платеж тут же и проведется — ведь могут быть неполадки и на стороне банков, но запрос сервис создаст, и пользователь увидит, что все сработало. Да и нам до идеала еще десяток листингов беклога с техническим долгом, чего греха таить, можем и 504 ответить изредка.

Заглянем в бункер, раз торнадо за окном

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

Это решили минимизацией мест, где хранится состояние системы — очевидно, что stateless-приложения легко масштабировать до горизонта.

Сами приложения у нас крутятся в Docker-контейнерах, логи из которых мы надежно сливаем в центральное Elasticsearch-хранилище; друг друга они находят через Service Discovery, а данные передают по IPv6 внутри Макросервиса.

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

За порядком приглядывает SaltStack, в котором описано все состояние Макросервиса.

Мы еще вернемся с подробным описанием всего этого хозяйства.

С приложениями легче.

А вот если хранить где-то состояние, то обязательно в такой базе, в которой минимальна цена выхода из строя части нод. Еще чтобы в ней не было мастер-нод с данными. Чтобы могла с предсказуемым временем ожидания на запросы отвечать. Это тут мечтают? Тогда еще чтобы ее обслуживать особо не надо было, и чтобы разработчикам-эрлангистам нравилась.

Да, разве мы еще не сказали, что вся онлайн-часть нашего процессинга на Эрланге написана?

Как многие уже, наверное, догадались выбора у нас как такового и не было.

Все состояние онлайн-части нашей системы хранится в Basho Riak. О том, как готовить Riak и не сломать себе пальцы (потому что мозг вы сломаете обязательно), мы еще расскажем, а пока продолжим дальше.

Где деньги, Лебовски?

Если взять бесконечное количество денег, возможно, удастся построить бесконечно надежный процессинг. Но это не точно. Да и денег нам особо не выделили. В аккурат на сервера уровня "качественный, но Китай".

К счастью, это привело к положительным эффектам. Когда понимаешь, что тебе как разработчику, будет несколько затруднительно получить 40 физических ядер, адресующих 512GB оперативки, приходится выкручиваться и писать маленькие приложения. Зато их можно развернуть сколько угодно много — сервера все-таки недорогие.

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

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

Но с серверами легче.

Мы разобрались, где размещать приложения, их много, они масштабируются. База тоже распределенная, мастера нет, сгоревшие ноды не жалко, можем быстро нагрузить телегу серверами, приехать в ДЦ и покидать их вилами в стойки.

Но с дисковыми массивами так не поступить! Выход из строя даже небольшого дискового хранилища — это отказ части платежного сервиса, чего мы себе позволить не можем. Дублировать СХД? Слишком нецелесообразно.

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

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

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

Таким образом у нас получилась удобная, отказоустойчивая и универсальная система — стойка, набитая простыми дешевыми серверами, несколько свитчей. Следующая стойка. И так далее.

Просто, удобно и в целом — очень надежно.

Прослушайте правила поведения на борту

Нам никогда не хотелось приходить в офис, делать работу и получать оплату деньгами. Финансовая составляющая очень важна, но она не заменит удовольствия от хорошо сделанной работы. Мы уже писали платежные системы, в том числе и на предыдущих местах работы. И примерно представляли, чем мы не хотим заниматься. А не хотелось стандартных, но проверенных решений, не хотелось скучного энтерпрайза.

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

Мы решили ничего не запрещать, а наоборот, поощрять все новое. Так у нас в продакшене построился Макросервис из огромной кучи приложений в докер-контейнерах, управляемый через SaltStack, кластеры Riak'а, Consul в качестве Service Discovery, оригинальная реализация трассировки запросов в распределенной системе и множество других замечательных технологий.

И все это безопасно настолько, что можно без стыда публиковать программу Bugbounty на hackerone.com.

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

Спасибо, что выбрали нашу авиакомпанию!

P.S.: Original content! Все фотографии в посте — сцены из жизни нашего офиса.