Як ми створили просунутий інтернет-банк за 5 місяців

Так як це не зовсім звичайний інтернет-банк і розроблявся він нестандартними методами, я вирішив поділитися деталями того, як ми робили цей проект, що допомогло нам створити його менш, ніж за 5 місяців, а також розповісти про деякі технічні деталі.

Іншими словами те, що ми робили - можна назвати аджайлом (Agile software development), і якщо ще точніше, то XP - екстремальним програмуванням. Такого роду процес розробки ми відточили вже на багатьох наших попередніх клієнтів і дуже успішно використовували його і працюючи в естонському Swedbank-е.

архітектура

"Що? Play Framework в банку, ти напевно жартуєш?" - була перша реакція знайомих розробників.

Давайте подивимося, що вплинуло на рішення:

  • Ми хотіли писати на Java, так як маємо великий досвід з мовою і платформою. Java ще не мертва, якщо її використовувати правильно.
  • У нас була відносно невелика команда і трохи часу, так що ми повинні були бути максимально продуктивними. В цьому нам допомогла також середовище розробки Intellij IDEA, до речі, що розробляється в Пітері.
  • Java запускається на Лінукс, адміністрування якого в рази простіше і швидше, ніж будь-яких там Віндовс. Це мені за пивом підтвердили адміністратори, намучився з колишніми рішеннями.
  • Play Framework робить розробку на Java швидше за рахунок автоматичної перекомпіляції і перезавантаження коду, та й дозволяє все це запускати на своїй машині за секунди без пожирання величезних кількостей оперативної пам'яті, що властиво application-серверів в світі Java, і за що її недолюблюють стартапи, де продуктивність цінуватися понад усе.
  • Звичайно ж, як і багато інших фреймворки, Play також вирішує Значну частину розповсюджених проблем розробки веб-додатків як структуризація проекту тощо дуже елегантно, приносячи легкість динамічних мов в світ Java. Багато ідей інспіровані Ruby on Rails, Django для Python і навіть NodeJS.

Звичайно ж, дуже придався і наш багаторічний досвід розробки попередніх інтернет-банків і інших систем самообслуговування в інтернеті. Ми явно вже знали, чого точно ми хотіли, щоб створити дуже гнучку платформу спеціально для інтернет-банків на базі Play.

Чого ще доброго дав нам Play?

Play - це повністю stateless framework. Він працює так, як і розрахований працювати HTTP - сервер не знає нічого про сесії користувачів, не виділяє зайвої пам'яті для них, так що додаток масштабується лінійно - при збільшенні кількості серверів в два рази ми можемо обслуговувати в два рази більше користувачів. Поки їх тільки два і вони зовсім несильно навантажені. Сервери знаходяться в різних датацентрах і між ними йде розподіл навантаження через DNS. Так як інформація про сесії користувача зберігається тільки в cookie, то при падінні одного з них користувачі перекидаються на другий без необхідності нового входу.

Це, також, дає нам можливість робити оновлення програми посеред дня, не втрачаючи активних користувачів. У день запуску ми оновлювали додаток 4 рази, і все це під час того, як ми отримували більше 10 запитів в секунду від користувачів. Звичайно ж, дані користувача в cookie підписані, так що користувач не може їх підробити.

Для маскування невисокої продуктивності АБС ми використовуємо інтеграцію Play з memcached, що далеко не стандартне рішення в світі Java. При роботі з кешем ми, звичайно, враховуємо, що записів в ньому може і не бути, але якщо вони там є, то не робимо зайвих і, як правило, повільних запитів до АБС. Ми навіть довантажувати дані про рахунки і картах клієнта ще до того, як він встиг ввести СМС код для аутентифікації.

Для подгрузки в фоновому режимі нам у великій пригоді рідна підтримка Job-ів в Play. працює на основі Quartz. Якщо пароль ми просто асинхронно запускаємо відповідний Job в окремому потоці. Job-и також використовуються нами і для безлічі інших фонових завдань всередині інтернет-банку - від обробки регулярних платежів до прийняття банківських повідомлень через SMTP протокол.

Якщо вже почали говорити про асинхронности, то треба відзначити і можливість Play обслуговувати безліч одночасних HTTP запитів в одному потоці, ніж теж дуже хвалиться NodeJS. Це дозволяє економити ресурси пам'яті і обслуговувати набагато більшу кількість користувачів меншою кількістю процесів. Play містить відмінний асинхронний фреймворк на базі Promise-ів і continuation-ів, виконуючи більшість I / O операцій асинхронно, вивільняючи потоки на цей час для інших завдань (для тих хто володіє темою).

тестування

Де Play не відповідав нашим очікуванням - це автоматичні тести (а як ще робити по кілька оновлень в день на бойову систему без регресій?)

Play містить підтримку тестування. але вона, на наш погляд, не зовсім адекватна - ми не хотіли запускати тести в браузері, особливо unit-тести, і ми хотіли мати зручну можливість писати код за допомогою методики TDD (Test Driven Development), тобто писати тест для ще неіснуючого коду і тільки потім писати свій код, використовуючи тест як критерій готовності. Більшість функціональності можна покрити unit-тестами, які запускаються і пробігають швидше, ніж інтеграційні. Коли програма має працювати зі сторонніми системами, ми робимо до них тестовий запит, зберігаємо відповідь в початковому вигляді і пишемо unit-тест, який одержує збережений відповідь сторонньої системи на вхід і перевіряючий коректність інтерпретації вхідних даних. Це дуже зручно як для розробки, так і для документації поведінки тієї системи.

Для решти ми використовуємо бібліотеку Selenide. розроблену нашою компанією на базі Selenium WebDriver. Вона дозволяє писати лаконічні тести призначеного для користувача інтерфейсу, що управляють реальним браузером. При запуску тестів за допомогою JUnit автоматично стартує весь інтернет-банк з тестової in-memory базою даної, створюються всі необхідні таблиці, завантажуються туди тестові дані, запускається браузер і потім виконуються вже самі тестові сценарії. Все це займає всього кілька секунд, що важливо для продуктивної розробки. Всі тести, що покривають більшість функціональності програми, пробігають трохи більше, ніж за 5 хвилин, що дає нам досить швидкий зворотний зв'язок в разі виникнення регресій. Звичайно, для досягнення такої швидкості ми пройшли через багато стадій їх оптимізації. Головна мотивація оптимізації була в тому, що всі тести є частиною билда, а не запускаються окремо від нього, як робиться в більшості проектів.

Для білдів ми використовуємо Jenkins. Він стежить за будь-якими змінами в коді і відразу ж робить новий білд, попередньо запускаючи всі тести. Повністю автоматично. Коли нам треба встановити будь-які зміни в бойову середу, то ми просто беремо для цього останній вдався білд, нічого спеціально для цього робити не треба. Якщо потрібно швидке виправлення, то досить закоммітіть зміна в систему версіонірованія (git), і через 5 хвилин можна ставити. Як правило, такі термінові білди містять і інші не дуже термінові зміни, то так як вони вже на той момент протестовані, то немає проблем з їх потраплянням в бойову середу. І, роблячи поновлення досить часто, кількість змін встановлюваних за раз невелика, завдяки чому ймовірність великої поломки дуже мала і відкат на попередню версію в разі необхідності теж проходить з без зайвого ризику.

Трошки складніше йдуть справи з оновленням структури бази даних - але для цього Play містить вбудовану підтримку еволюційних скриптів (іноді званих дельта-скриптами). При установці нового билда інтернет-банк перевіряє поточну ревізію своєї бази даних і при необхідності доставляє все нові зміни, такі як створення нових таблиць, додавання колонок, індексів, і навіть пов'язану з цими змінами міграцію даних. Кожен білд інтернет-банку містить повний набір скриптів, за допомогою якого можна відтворити всю базу з нуля (за винятком даних). Завдяки цьому дуже легко піднімається нове середовище розробки або тестування, коли це буває потрібно.

Простота / Usability

Незважаючи на всі навороти і ефективний спосіб розробки, ніхто не буде використовувати новий інтернет-банк, якщо він складний або незрозумілий для користувача. "Не примушуй мене думати" називається відома книга Стіва Круга на цю тему.

На самому початку розробки ми взяли для себе мету зробити інтернет-банк зрозумілим звичайній людині, а не тільки бухгалтеру або економісту. Нормальні люди не зобов'язані знати, що таке овердрафтний рахунок або дивитися три окремих виписки, щоб зрозуміти на що вони витрачали свої гроші, тому інтернет-банк повинен досить сильно перетворювати дані, що приходять з АБС. Не можна також перевантажувати користувача надмірним кількістю деталей. Все повинно бути коротко і в точку.

Інший важливий аспект - це перевіряти ідеї на реальних людей - домогосподарок, школярів, працівників підприємств і т.д. Для цього банк провів usability-тестування, під час якого добровольців просили зробити конкретні завдання (наприклад, "переведи 100 рублів своєї бабусі") і спостерігали, наскільки швидко і легко користувачі з ними справлялися. Це ще один вид зворотного зв'язку, необхідний для створення успішного і інтуїтивно зрозумілого продукту. Дозволяє не писати нудну документації для користувача, яку все-одно ніхто не Новомосковскет.

Якщо ж у чинній системі все-таки виникає помилка, то замість технічної лайки ми показуємо користувачеві форму з кодом помилки і можливістю описати, що до неї призвело або просто вилити свої емоції. При надсиланні такого зворотного зв'язку надсилається повідомлення, що дозволяє швидко знайти причину виникнення помилки в логах і навіть відповісти користувачеві в разі виправлення. Це сильно допомогло нам протягом перших днів публічного запуску.

Безпека

Про безпеку інтернет-банків можна писати багато. Обмежимося тим, що Play framework при правильному його використанні відразу запобігає такі найпоширеніші вектори атак, як XSS (Cross-site scripting) і SQL Injection - все, що показується користувачеві, проходить через примусовий ескейпінг і все, що надсилається в базу через JPA / JDBC бінді і надсилається на сервер окремо від самого тексту запиту, виключаючи можливості його зміни користувачем за допомогою хитро складених запитів. Це елементарна практика, але, тим не менш, фахівці з аудиту безпеки з однієї української компанії зізналися, що це було перше застосування з коли-небудь тестованих ними, де не було знайдено жодної серйозної уразливості. Нам було приємно, але, звичайно, один тільки фреймворк не може повністю вирішити всі проблеми, пов'язані з безпекою. Розробники завжди повинні самі пам'ятати про такі речі, як приналежність переданих ідентифікаторів або номерів рахунків клієнта в активній сесії. Щоб не залишити де-небудь дірку, допомагає тільки увага до деталей і багаторічний досвід розробки веб-додатків. Для цього нам про всяк випадок довелося також змінювати сам Play і відключати автоматичне завантаження об'єктів з бази за ідентифікатором, що приходить із запиту. Також ще є більш хитрі атаки, як CSRF (Cross-site request forgery) або навіть HTTP Response Splitting, перехоплення сесій, replay-атаки і т.д. потребують запобігання з боку програмістів.

Важлива для безпеки і хороша аудітіруемость - всі дії користувачів детально логіруются в компактному форматі, зручному для обробки стандартними unix-утилітами, зі зв'язками з унікальним ID запиту і сесією. Вибір платформи роботи інтернет-банку (Лінукс) в цьому випадку теж має велике значення.

В цілому, нам було дуже цікаво і приємно розробляти це додаток. Сподіваємося, що простота і зрозумілість нового інтернет-банку будуть гідно оцінені клієнтами Банку Харків. А для нас, розробників, немає нічого приємнішого, ніж власний код, який працює в бойовому середовищі і робить життя користувачів трохи зручніше! В даний момент ми продовжуємо розробку, так що скоро користувачам будуть надані нові цікаві можливості. **

I checked out the new bank website and immediately came across something interesting. As an anonymous user under any page, have you tried clicking the "login" link in "You need to login in order to proceeed (sic!)" Box in a browser other than Chrome? ;)

Good read, cheers!

Як давній користувач інтернет-банку БСПб (так само як і інших інтернет-банків, включаючи просунутий ТКС), хочу сказати, що ваш проект, безперечно, вдався! Також не можу не відзначити відносно швидке виправлення знайдених (на ранніх стадіях) багів, про яких я, як користувач, писав в службу підтримки банка.Снімаю капелюх, молодці!

останні історії