Това е първата част от серия от статии посветени на Serverless. В тази първа статия ще се запознаем с основните принципи и характеристики на Serverless архитектурата и след това ще разработим бекенд за трансформиране на банкови извлечения. В следващите статии ще наградим това решение до цялостен процес за обработка на банкови извлечения и добавянето им в онлайн платформа за анализи и финансов отчет.

Описание на бизнес проблем

Преди да продължим с представянето на Serverless, ще дефинирам и специфичния бизнес проблем, който ще разглеждаме в тази серия от статии.

Обикновено повечето фирми използват определен софтуерн за финансов отчет, за да може да се следят приходи, разходи и други важни показатели за състоянието на фирмата. За това е нужно извлеченията от вскички сметки на фирмата да се добавят в дадения финансов софтуер. В много случаи софтуерните системи могат директно да работят с дадена банка, но има и случаи, в който това е невъзможно, защото софтуерът няма интеграция със съответната банка. При липса на интеграция, са необходими много ръчни операции и процесът изглежда по следния начин:

  1. Данните се експортват от банката.
  2. Данните се форматират на ръка (обикновенно с Ексел), за да отговарят на формата на софтуера.
  3. Данните се импортват в софтуера.

Стъпките на пръв поглед не са много, но целият процес може да отнеме няколко часа работа в зависимост от броя на сметките и форматирането, което трябва да се направи.

Нашата задача е да автоматизираме този процес и да олесним работата на човекът, който се занимава с финансовите отчети.

Въведение в Serverless

Serverless е много нашумяло понятие и най-просто казано представлява изпълнението на код в облaка. Само по себе си понятието Serverless може да звучи объркващо, тъй като Serverless на практика включва използването на много сървъри. Но тук главната идея е, че ние не трябва да се грижим за тези сървъри. Една от водещите идеи зад Serverless е, че ние се грижим само за нашия код и нашите данни, а всички други инфраструктурни задължения като скалиране, обновяване на ОС и др. се поемат от платформата.

Чисто хронологично Serverless представлява последната еволюция на услугите, предлагани в облака. Това е илюстрирано тук:

Cloud Evolution

Какво е serverless?

Нека накратко да дефинираме какво е serverless, без да навлизаме в излишни за момента детайли. Обикновено говорим за serverless, когато имаме следните характеристики:

  • Абстракция на сървъри
  • Бързи и автоматично скалиране
  • Таксуване на кратки интервали

Абстракцията на сървъри представлява менажирането на инфраструктурата от някой друг, при което ние не сме отговорни за това как нашият код е “инсталиран” на даден сървър и как този сървър работи. Други неща, за които не трябва да мислим са ъпгрейд на операционната ситемта, инсталиране на пачове и тн.

Бързото и автоматично скалиране означава, че платформата самостоятелно трябва да добави допълнителни ресурси (сървъри или по-точно инстанции), в случай, че те не достигат.

Последната точка е таксуване на кратки интервали. Тук може би и е най-примамливата част на Serverless за много бизнеси. При serverless плащаме само за времето през, което нашият код се е изпълнявал. Може би е добре този модел да се илюстрира с пример. Нека си представим, че сме написали serverless бекенд за оразмеряване на картинки, който взима дадена картинка и я смачква до определен размер. Ако нашия бекенд е бил извикан 10 пъти и всяко извикване е отнело по 1 секунда, то ние ще платим само тези 10 секунди, през които нашият код се е изпълнявал.

Това може много добре да се сравни с алтернативата, която имаме – да си купим виртуална машина, която работи 24 часа. Ако приемем, че нашият код отново се е изпълнил 10 пъти за 1 секунда, ние ще платим много повече, защото при последния модел, плащаме за самата виртуална машина и времето за изпълнение на кода няма никакво значение.

Като заключение може да обобщим, че serverless би трябвало да предостави следните предимства:

  • По-малко ресурси за инфраструктура или DevOps
  • Рентабилност
  • Продуктивност, защото се фокусираме върху бизнеса

Как работи serverless?

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

Conventional vs. Serverless infrastructure

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

Сценарии продходящи за Serverless

Хубаво е да смепонем и сценариите, в които ползването на serverless е добра идея. Като основно правило може да се отбележи, че serverless е много подходящ, когато трябва да реагираме на събития. Ето и една илюстрация:

Serverless Scenarios

Представяне на Azure Functions

Нека сега се фокусираме върху Serverless услугата наречена Azure Functions. Накратко казано, Azure Functions е платформа, която ни позволява да изпълняваме код в облaка.

Алтернативи на Azure Functions са налични при всички други основни играчи като Гугъл (Google Cloud Functions) и Амазон (AWS Lambda). Естествено всичките имат своите предимства и недостатъци, но много от нещата, в тази статия са приложими при всички serverless платформи.

Azure Functions ни предоставя следните функции/възможности:

  • Избор на език за разработване (C#, JavaScript, F#, Java, и др.)
  • Гъвкавост при разработване (избор на работна среда, език, начин на деплойване и др.)
  • Автоматично скалиране
  • Pay-per-use модел на таксуване
  • Отворен код
  • Базиран на Azure App Service (получаваме всички функции като бекъп, CI, и др.)

Когато искаме да създаддем serverless решение с Azure Functions, ние създаваме Function App. Function App ни позволява да групираме логически нашия serverless код и всичко свързано с него като деплоймънт и др.

В началото, ще се фокусираме изцяло върху нашата локална машина. След като сме готови с кода, ще разгледаме как може да го качим в облака.

Съдаване на локален Function App проект

За да започнем работа ни трябва Azure Functions Core Tools, това е CLI, което позволява локално да разработваме, тестваме, дебъгваме Ажур функции. Има две версии на CLI-то и ние се интересуваме от v2, което се инстлира по следния начин:

npm i -g azure-functions-core-tools@core –unsafe-perm true

Алтернативни методи за инсталиране (например с Chocolatey) са изброени на Github страницата на проекта. Също така допълнителна информация за разработване и дебъгване може да намерим тук – Code and test Azure Functions locally

След инсталацията вече може да създадем проект, който ще съдържа нашия serverless код. За да създадем нов проект трябва да изпълним следната команда:

func init DevBgServerless

На тази стъпка трябва да изберем и език/платформа – нека това да бъде Node. След като сме създали проект нека добавим и нашата функция.

cd DevgServerless
func new –template „Http Trigger“ –name TransformBankStatement

Тази команда ще създаде функция с име TransformBankStatement, която използва “Http Trigger”. Тригерите са много основен детайл от Ажур функциите и за тях ще научим повече след малко. За момента ще спомена, че тригерите указват как дадена фукнция ще бъде извиквана или стартирана.

Избирайки “Http Trigger”, ние указваме, че искаме нашата функция да бъде извиквана чрез HTTP. Има много голям набор от тригери, които може да разгледате тук. Пример за друг вид тригер би бил “Timer trigger”, с който може да създадем функция, която се изпълнява през определен интервал от време.

След като вече имаме фунцкия нека я стартираме и разгледаме по-отблизо.

# Трябва да сме в папка DevgServerless
func start

Така се стартира тъй наречения Function host, който ни позволява локално да тестваме нашите функции без да има нужда да ги качваме в облака. След като командата се изпълни би трябвало да видим следния резултат в конзолата:

Listening on http://0.0.0.0:7071/
Hit CTRL-C to exit…

Http Functions:

TransformBankStatement: http://localhost:7071/api/TransformBankStatement

[8/2/2018 2:38:45 PM] Host started (29487ms)
[8/2/2018 2:38:45 PM] Job host started

За да тестваме нашата функция просто трябва да изпратим рекуест на указания адрес. Например: http://localhost:7071/api/TransformBankStatement?name=DevBG

Файловата структура

В момента проекта, който направихме трябва да изглежда по следния начин:

DevBgServerless
| – host.json
| – local.settings.json
| – TransformBankStatement
| | – function.json
| | – index.js

Файлът host.json съдържа опции за конфигуриране на всички функции в един Function App. Повече информация за този файл може да намерите тук.

Фаилът local.settings.json съдържа кънекшън стрингове и други конфигурации, който се използват само локално и нямат ефект когато качим кода в облака.

Във всеки един Function App проект може да има една или много на брой функции – в нашия случай това е TransformBankStatement. Всяка функция като минимум съдържа function.json и index.js.

Файлът index.js съдържа кода, който ще се изпълни, когато нашата функция бъде извикана. Файлът functions.json съдържа конфигурационни метадани за дадената функция – например тук се указва какъв е тригърът на нашата функция.

Нека вече се насочим и към най-интересното – самия код.

Index.js

Както вече споменахме, index.js съдържа кода на нашата функция. Ето го и него:

За да може да работи нашата функция, тя трябва да бъде експортната през module.exports.

Всяка функция трябва да има един задължителен параметър (context). Това е тъй нареченият context object, който ни дава достъп до средата за изпълнение (runtime). Чрез context ние може да получим достъп до входните и издохните данни на нашата функция.

Context има два метода – context.done() и context.log(). Първият метод се използва да информираме, че нашия метод е завършил изпълнението си и съответно използването му е задължително във всяка функция. Вторият е очевидно какво прави.

Освен задължителният първи context параметър, нашата функция може да има и други такива, които представляват входни данни на нашата функция. В нашия пример имаме параметър req, който съдържа информация за HTTP заявката предизвикала изпълнението на нашата функция. Както се вижда от кода, може да използваме req да проверим дали заявката съдържа параметър name и да използваме стойността му.

Последното интересно нещо, на което трябва да обърнем внимание, е как нашата функция връща резултат. В случая се интересуваме да върнем HTTP отговор и това отново става чрез context. Използвйки context.res може да създадем response object, който има няколко основни полета – body, headers, status, isRaw. Най-често използваните са body (резултата който връщаме) и status (HTTP статус код).

За момента имаме цялата информация, за да продължим напред и започнем имплементацията на нашия serverless бекенд за трансформиране на банкови извлечения. Повече информация отностно писането на Azure Functions с JavaScript може да намерите в Azure Functions JavaScript developer guide.

Създаване на serverless бекенд за трансформиране на данни

Нека набързо припомним какво бяхме заложили да постигнем в началото на статията. Искаме да имаме услуга, която трансформира банкови извлечения от формата на дадена банка към друг специфичен формат. Ето и примерно извлечение от банката (за улеснение са махнати излишните полета от стандартните банкови извлечения).

Форматът, към който трябва да направим трансформацията е много подобен с няколко много важни разлики – полето datetime трябва да е във формат “YYYY-MM-DD”, a сумата (amount) трябва да е със знак минус ако имаме дебит. В момента знака се определя от полето dtkt.

Като краен резултат целим следното нещо:

Нека започнем с кода.

Добавяне на npm пакети

Без никакъв проблем може да използваме пакети при разработването на нашия serverless код. За момента ще имаме само един такъв за работа със дати.

# В папка DevBgServerless
npm init
npm install moment –save

Модул за трансформиране на извлечения

Това е основният ни код. Нека го отделим в собствен модул като добавим файл “bank-statement-transform.js” в папка “TransformBankStatement”.

Този код по никакъв начин не е зависим от спецификите на Azure Functions и може да бъде използван в други услуги или приложения – това е нашата бизнес логика. Главната функция е transformStatement, която очаква като вход банвковото извлечение, които трябва да се трансформира. Използваме пакета moment, за да обработим датите. Кодът е доста стандартен и не мисля, че има нещо, което заслужава да бъде обсъждано по-обстойно.

Използване на модула за трансформиране в нашата serverless функция (index.js)

След като вече имаме бизнес логиката, нека видим как може да я интегрираме с нашата функция. Ето как трябва да променим index.js:

Първото нещо е да добавим нашата бизнес логика – функцията transformStatement().

Другото, което прави нашата обновена функция е да провери дали HTTP заявката има body. Ако има такова очакваме, че банковото извлечение ще е там, което се трансформира с функцията transformStatement().

След трансформацията следва да приготвим response object, който ще съдържа резултата.

Ако случайно заявката няма body, връщаме съобщение за грешка. В общи линии сме готови с нашата функция. Нека я изпробваме.

Тестване на функцията за трансформиране на банкови извлечения

Нека стартираме нашата функция използвайки командата func sart. Функцията отново ще бъде достъпна на http://localhost:7071/api/TransformBankStatement, но този път ще ни трябва малко по-сложна заявка, за да тестваме. Тук има много варианти като curl, Postman, или нещо друго. Аз ще ползвам Postman, за да симулирам POST заявка, която изпраща извлечение за трансформиране.

Стъпки за тестване

Ето и примерни данни, с който може да тествате функцията:

datetime,reference,amount,dtkt,trname
11/08/2018 11:01:07,001FTЗЗ182121504,4000.00,K,Получен кредитен превод – Фактура 12345
15/08/2018 00:00:00,001ЗЗMRBGNL55001,0.60,D,Такса за поддръжка на сметка
15/08/2018 00:00:00,001ЗЗMRBGNL55001,1.40,D,Такса за поддръжка на сметка
16/08/2018 12:31:20,001AЗЗF182149938,25.96,D,КТ Плащ.н.Visa Electr-н.POS търг.
18/08/2018 11:46:57,001AЗЗ4182122509,200.00,D,Теглене на АТМ в страната
18/08/2018 11:46:57,001AЗЗ4182122509,1.06,D,Такса теглене на АТМ в страната

Ако всички е наред, би трябвало да получим следния резултат в Postman:

date,amount_signed,reference,details
2018-08-11,4000,001FTЗЗ182121504,Получен кредитен превод – Фактура 12345
2018-08-15,-0.6,001ЗЗMRBGNL55001,Такса за поддръжка на сметка
2018-08-15,-1.4,001ЗЗMRBGNL55001,Такса за поддръжка на сметка
2018-08-16,-25.96,001AЗЗF182149938,КТ Плащ.н.Visa Electr-н.POS търг.
2018-08-18,-200,001AЗЗ4182122509,Теглене на АТМ в страната
2018-08-18,-1.06,001AЗЗ4182122509,Такса теглене на АТМ в страната

Нашата функция е готова. Остава да я публикуваме в облака.

Deployment на решението

За да публикуваме функцията в Microsoft Azure, трябва да се сдобием с достъп до платформата.

Създаване на профил в Microsoft Azure

За да може да продължим нататък ще ни е нужен достъп до Mirosoft Azure. В Ажур се предлагат два типа безплатни акаунти – студентски и стандартен безплатен. Ако за първи път използвате Microsoft Azure, е добре да се запознаете и с порталът през, който се създават и управляват ресурси (Azure Portal). Ето едно кратко, но състоятелно видео – Get Started with Azure Portal.

Съзадаване на Function App

След като имаме достъп, трябва да създадем Function App ресурс, който ще се грижи за изпълняването на нашия код. Ако за първи път се сблъсквате с Azure Functions бих препоръчал тази статия, която описва много добре как може да създадем тъй наречения Function App.

Следкато вече имаме създаден Function App ресурс можем да пристъпим към публикуването на нашия код. Тук отново има много варианти, но аз ще се спра на този, който е най-близо до стандартния работен процес, а именно използването на Git хранилище. За целта вече съм подготвил такова – devbg-serverless-transform-function. То съдържа кода, по който работихме до момента.

Публикуване на кода използвайки Git интеграция

Нека навигираме до Function App, който сме създали в предната стъпка. Трябва да виздаме екран подобен на този:

Function App Home

За да може да свържем Git хранилището с нашия app, трябва да отидем на Platform features. Там ще намерим опция Deployment options. От там може да изберем Setup, за да стартираме процеса по свързване на хранилище.

 

 

 

 

Function App Deployment Setup

Както ще видите има доста възможности за свързване с различни видове хранилища. За да е максимално лесно нека изберем External Repository и въведем адреса https://github.com/milannankov/devbg-serverless-transform-function. След като приемем избора си, ще започне процес на изтегляне на кода и билдването му. Ако всичко е успешно, екранът трябва да изглежда ето така:

Deployment Ready

Вече би трябвало да сме готови да изпробваме кода, който вече върви в облака. Ако се върнем в основния екран на нашата фукнция и отворим Functions от дървовидната структура вляво, ще видим, че нашата функция TransformBankStatement е вече там. За да видим адреса на функцията просто трябва да я изберем и след това да изберем Get function URL. След като имаме адреса, може да тестваме функцията с Postman само като използваме новото URL.

Function Address

Заключение и следващи стъпки

Нека направим обобщение за постигнатото до момента. Създадохме serverless бекенд, който при подадено съдържание на банково извлечение, ще върне обработено такова във формат годен за използване в даден финансов софтуер. Естествено не бихме имали очакваня човекът, който се занимава с финансовите задачи да може да използва нашето serverless API. Затова в следващите статии ще надградим започнатото и използването на нашия бекенд ще става незабележимо за потребителя докато той работи с познати му технологии.

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

Благодаря за вниманието. Ще се радвам да отговоря на всякаки въпроси и коментари.


Автор:

Милан Наков

>>> Милан Нанков е програмист с многогодишен опит в разработването на софтуерни решения и компоненти.
>>> Обича да споделя своя опит в технологиите като говори на конференции и пише статии (nvs, nankov.com).
>>> Организатор е на Azure User Group Bulgaria и преподава в АУБГ (Американски университет в България).
>>> В момента работи в Prevalent, където помага в разработването на платформа за менижиране на риска и киберсигурността.


Стани част от потребителските групи на DEV.BG. Абонирай се и ще ти изпращаме информация за всичко, което предстои в групата.

Визия: Личен архив

Прочети още:
Visual Studio Extensibility
Как можем да използваме Azure WebApps за решаване на проблеми, с които CRM Online не може да се справи

 

 

Share This