Ispod haube Tradecorea — šta je sve u našem tech stacku i zašto

Jedna od najvažnijih stvari za mnoge startape u ranoj fazi, poput nas, je sposobnost brzog prilagođavanja zahtevima tržišta. Ovo je bio najvažniji faktor u našem izboru tehnologija koje ćemo koristiti za razvoj naših proizvoda, pored činjenice da smo od starta distribuiran tim i toga da su među našim najbitnijim klijentima finansijske institucije. U ovom članku

Bojan Jovanović
23/12/2014

Jedna od najvažnijih stvari za mnoge startape u ranoj fazi, poput nas, je sposobnost brzog prilagođavanja zahtevima tržišta. Ovo je bio najvažniji faktor u našem izboru tehnologija koje ćemo koristiti za razvoj naših proizvoda, pored činjenice da smo od starta distribuiran tim i toga da su među našim najbitnijim klijentima finansijske institucije.

U ovom članku ću vam predstaviti naš tech stack i razloge zašto smo izabrali koji njegov deo, uz nadu da će vam možda neke od odluka, rezonovanja iza njih i grešaka koje smo napravili pomoći da, kada budete u sličnoj situaciji, izaberete najbolje alate za vaše potrebe.

Ko smo i šta pravimo

Pre nego što zađemo u tehnologiju, bilo bi korisno da pružim malo konteksta oko toga šta mi radimo. Mi smo dakle mladi beogradski startap koji za cilj ima kreiranje inovativnih digitalnih fintech proizvoda i uspešnih biznisa zasnovanih na njima.

Smatramo da smo izuzetno ambiciozni i u skladu s tim razmatramo veliki broj prilika za razvoj biznisa i realizujemo najveće od njih. Ipak, bez obzira na različite mogućnosti, u srcu svih naših proizvoda stoji platforma koju smo izgradili, koja deli ime sa firmom — TRADECORE.

tradecore

TRADECORE je svojevrsan švajcarski vojnički nož — čini ga set biblioteka i modula za online trejdovanje, kojima se mogu praviti različite vrste finansijskih proizvoda za brokere ili trejdere. Primeri ovih biblioteka su: registracioni moduli za nove korisnike, verifikacija identiteta korisnika, integracija sa globalnim pejment sistemima, behavioural marketing, risk management, servisi za konekciju sa različitim liquidity providers preko Financial Information eXchange (FIX) protokola, itd.

TRADECORE je u isto vreme i ime našeg glavnog proizvoda, profitabilne B2B SaaS aplikacije za upravljanje brokerskim kućama. Putem njega naši klijenti mogu u svakom trenutku da vide najrazličitije potrebne statistike i informacije o njihovim klijenatima i njihovim aktivnostima, i da prema njima optimizuju svoje poslovanje. Za one koji su culi za poznati alat za Saas aplikacije Intercom bi mogao da povučem paralelu da je TRADECORE, izmedju ostalog, i Intercom za brokerske kuće.

U planu imamo i dva B2C proizvoda, koje je teže razviti na masovnoj skali (kako je neophodno da bi biznisi funkcionisali) ali mogu imati i dosta veliki poslovni potencijal.

Prvi od njih je Tradecrowd, koji je neka vrsta društvene mreže za trejdere — možete pratiti interesantne trejdere i njihova ulaganja, kopirati ulaganja onih koje smatrate uspešnim, razmenjivati informacije i komunicirati sa drugim članovima.

Drugi je Lovestocks, mobile only aplikacija za ulaganje na berzi, koja beskrajno olakšava kupoprodaju akcija, izbacujući iz procesa brokere, uklanjajući raznorazna ograničenja i novčane nadoknade.

Nakon ovog uvoda, sada možemo da pređemo na zabavne stvari — na tehnologiju.

Version Control

Naš VCS je GIT čiji smo veliki fanovi, a “gitujemo” ga na BitBucketu zbog kompatibilinosti sa (isto) Attlassianovom JIRom. Koristimo git-flow model za razvijanje koda, ne pratimo u potpunosti releasing grane ali generalna struktura Master/Develop grana i feature/bugfix je tu.

Volimo ga zbog disposeable grana, zbog odličnog merge algoritma, i zbog toga što implementacija git flow modela može solidno da skrati vreme osobi koja je zadužena za mergeovanje jer mu daje bolji overview procesa razvijanja aplikacije.

Python

 

Ono što stoji u version controlu je Python kod. Sad, zašto smo izabrali dinamički jezik i zašto baš Python?

Kada pokrećete tehnološki startap, firmu koja po jednoj jezgrovitoj definiciji pokušava da otkrije šta gradi, za koga, i kako će da zarađuje, morate imati mogućnost da se brzo prilagodjavate zahtevima tržišta, da pravite niz modifikacija, ispravljate greške u dizajnu… Jedan od boljih, ako ne i jedini način, je da se okrenete ka dinamičkim jezicima.

Dinamički jezici su pre svega skript jezici, što znači da se njihovo kompajliranje stavlja u run-time programa, nasuprot statičkim koje kompajler prvo pretvara u binarni kod pre nego što može da se izvrši.

Laički rečeno, pruža nam mogućnost da u runtimeu kreiramo strukture i klase potpuno dinamički, što nije izvodljivo sa statičkim jezicima. Ovo nam donosi novi nivo apstrakcije i nove metode za rešavanje nekih problema koji su sa statičnim jezicima najblaže rečeno kompleksni, ako ne i neizvodljivi.

Imajući sve navedeno u vidu, izbor za našu backbone aplikaciju se manje više sveo na dva najzastupljenija dinamička jezika — Ruby i Python.

U našem slučaju smo se okrenuli Pythonu — naprosto zbog toga što smo već imali predznanje u njemu.

To nije bio jedini razlog, smatramo da nam je to i vrlo pametan izbor zato što planiramo da u budućnosti koristimo neke od njegovih naprednih matematičkih biblioteka, kao što su numpy, pandas i Scikit Learn.

Drugi razlog što smo se okrenuli Pythonu je to što je postoje wrapperi za poznatu biblioteku napisanu u C++ koja se zove QuickFix, koja je implementacija pomenutog FIX protokola koji koristimo za komunikaciju sa brokerskim kućama. Budući da je ta biblioteka za trenutne potrebe preterani bloatware, za sada nam je jednostavnije da osnovnu implementaciju FIXa napravimo direktno u Pythonu.

Sve skupa, Python bih preporučio za situacije kada imate potrebu da se fokusirate na to da se stvari zapravo završe na vreme i kada nemate vremena da se bavite konvencijama i ispravnošću sintakse.

Django

Naredni nivo apstrakcije nam je Django. To je web framework koji čini srž biznis logike našeg aplikacionog servera. Djangove aplikacije koristimo da bi izdelili naše module, a njegov templating system i MVC pattern smo do sada koristili da bi generisali naš ceo front end (iako odatle polako odlazimo).

Kada Django nadgradimo Django-Rest-Framework-om, dobijamo zapravo naš B2B proizvod — full stack application server koji vam pruža mogućnost da u potpunosti izopštite generisanje statičnog backenda i da sa rest API pozivima zamenimo sve forme koje imamo i izložimo sve metode i funkcionalnosti.

Celery

Ako nije i jedini, Celery je svakako najrazvijeniji distributed task queue system za Python, sa podrškom za Django. Koristimo ga za pokretanje pozadinskih (long running) taskova, rutinske analize podataka, sanity check-ovi, slanje mejlova itd.

Uprkos tome što je RabbitMQ preporučeno message backend rešenje za Celery, u te svrhe koristimo Redis zbog jednog baga koji smo imali na produkciji sa Rabbitom zbog koga nismo hteli da rizikujemo dodatni downtime. Bilo nam je potrebno brzo rešenje, prebacili smo backend na Redis, i tako je ostalo od tada.

PubSubHub

Pubsubhub je naša implementacija “publish subscribe” patterna u Python. Koristimo Pubsub za “non-blocking” komunikaciju sa svim servisima vezanim za trejding.

Prethodno pominjani Financial Infromation eXchange ) protokol, FIX, može da se opiše i kao XML za brokere. Jedan od servisa konstantno sedi na Pubsubu i komunicira sa brokerom, od koga dobija mnoštvo informacija — od promena na berzi u realnom vremenu pa do informacija o tome kada je neki korisnik izvršio određenu transakciju.

PostgreSQL

Naš izbor relacione baze podataka nam je vrlo lako bio sveden na Postgres, jer je odlična, stabilna baza i najbolja stvar nakon Oraclea.

Koristimo Postgres u Master Slave replication modu, što pruža solidnu stabilnost, i daje garanciju da će nam podaci preživeti sem ako nas ne zadesi zombi apokalipsa, a možda i tad.

Iako se MySQL dosta popravlja u poslednje vreme, jednostavno od samog početka smo odlucili da idemo sa Postgresom i ne planiramo da ga menjamo. Treba imati u vidu i kritičan bag MySQL gde bilo koja migracija zaključa tabelu dok se god ne završi table change, pri čemu je nemoguće znati koliko će isto trajati i može prouzrokovati nepredvidive exceptione.

MongoDB

Vrlo verovatno da ne postoji pravi izbor NoSQL baze, jer sada postoji toliko raznih vrsta i varijanti NoSQL baza da sam prilično siguran da ne mogu da kažem zašto smo izabrali baš Mongo od svih ponuđenih opcija, niti bi mogao da kažem šta je konkretno bolje kod njega.

Stabilan je, nismo imali nikakvih problema sa njim na produkciji, Python ima odličnu implementaciju, jako se lako replikuje, kopira, bekapuje… Zaista nemamo razlog da kucamo na neka druga vrata.

Mongo koristimo za dve jako bitne stvari.

a) Svi communication logovi, requestovi i responsevi sa bilo kojih 3rd party API-a se loguju na mongoDB-u, i nakon toga se generišu reporti na osnovu njih. U našem slučaju sve radi jako brzo i efikasno.

b) Za agregaciju podataka sa berzi — na svakih 5/15/30minuta se radi snapshot agregiranih podataka koje dobijamo iz strima u realnom vremenu, kako bi mogli da na frontendu prikažemo razlicite zoom nivoe grafika koje prikazuju oscilacije cene određenog finansijskog instrumenta kroz vreme.

Redis

Na poslednjem mestu u grupaciji podataka bih stavio Redis kao cache server. Zanimljiva stvar sa Redisom je to što kada ga jednom instalirate, počinjete da ga koristite za razne taskove jer je tako neverovatno brz.

Tako kod nas Redis služi za:

Snapshot cena finansijskih instrumenata na tržištu

• Message Broker

• Database query cache

• Session store

TradeCrowd V1

Django-Forms + WebSockets/JQuery/Backbone 

Prelazimo lagano na frontend. Za početak bi imalo smisla da kažem nešto o legacy verziji koja je trenutno i produkciona verzija ranije pomenutog proizvoda TradeCrowd, naš frontend 1.0.

Zasnovana je na Django forms i templejt endžinu, ceo HTML i renderovanje stranica se izvršava na aplikacionom serveru

Koristimo Socket.io implementaciju websocketa na frontendu za promene cena finansijskih instrumenata u realnom vremenu, JQuery za dinamiku i backbone za data binding.

TradeCrowd V2

Static AngularJS + WebSockets

Pošto smo odlucili da ćemo da otvorimo API radi interfejsa ka mobilnoj platformi, razuman sled okolnosti je da ceo frontend koristi iste te pozive kako bi generisao potpuno dinamičku verziju sajta — naš frontend 2.0.

Stoga uvodimo statički AngularJS i sa nativnom podrškom za websockete elimnišemo ogromnu sklopku oko implementacije padataka sa berze, a unapređujemo i brzinu aplikacije odnosno kvalitet korisničkog iskustva.

Nginx/wsgi

Nginx je event-driven webserver, jedini razuman izbor za hosting Django aplikacija zbog stabilnosti i performansi. Main http entry-point sa multiple load balanced upstreams koji nam dozvoljavaju da imamo staging environment i time skratimo downtime prilikom deploymenta.

Jenkins

Naš server za kontinualnu integraciju — integrišemo kod na ne-developerskoj mašini čim neko gurne izmenu koda na repozitorijum. Ovde nam je bitno da odmah saznamo kada je nečiji kod uništio build proceduru, jer što pre detektujemo problem u buildovanju koda, brže ćemo pronaći i rešiti tu grešku.

Jenkins je defakto standard za integracije, deployment procedure, environment testing, štagodhoćeš. Koristimo ga za deployment, releasing, building, testing i task execution.

AWS

Svi naši klijentski produkcioni serveri se hostuju na Amazonovim EC2 instancama zbog sigurnosti i skalabilnosti okruženja koje Amazon pruža. Development / UAT i operacije stoje na Digital Oceanovim “dropletima”. AWS poseduje naprednu Compliance sertifikaciju, koja je od posebnog znacaja za nase B2B korisnike.

Sentry

Sentry je realtime event logger i platforma za agregaciju grešaka. Koristimo ga na svim produkcijskim i UAT instancama.

New Relic

Od svih servisa koji pruzaju usluge metrike, monitoringa i “early warning-a”, stavka  po kojoj se new relic odvaja od ostalih je “application monitor”. Application monitor se kaci direktno u nase Python servise i pruza nam direktnu informaciju o functionalnosti nasih servisa.

Ostalo

SendGrid — koristimo ga za slanje transakcionih mejlova

Intercom — koristimo ga na TradeCrowdu za segmentiranje i komunikaciju sa korisnicima

Google Apps — korpo mejl i ostalo

Transifex — platforma za prevodjenje aplikacija

JIRA — issue tracking i hostovanje repozitorijuma

Asana — project menadžment (kao što primećujete ne bežimo od korišćenja više različitih a sličnih alata, sve prema konkretnim potrebama ljudi i vrste informacija koje treba da pohranjujemo u njima; ume biti preplavljujuće ali za sada nam radi posao)

Balsamiq — koristimo ga za pravljenje interaktivnih mokapa interfejsa

Invision — pohranjujemo i kolaboriramo na inspiraciji za dizajn i praćenje konkurencije

Slack — timska komunikacija i kolaboracija, lično ga prezirem zbog bedne Android aplikacije

Optimizely — A/B optimizacija i conversion rate optimisation

***

Nadam se da ste iz ovog (podužeg) članka mogli da dobijete neku vrednost oko toga šta možete raditi (ili šta da ne radite) na nekom vašem narednom projektu. Iako nije savršen, naš stack nam dobro radi posao za sada. Ako imate bilo koje komentare ili pitanja slobodno ih ostavite ispod, a ako ste stigli već do kraja teksta javite nam se, uvek tražimo nove kolege.

Bojan Jovanović

Objavio/la članak.

utorak, 23. Decembar, 2014.

IT Industrija

🔥 Najčitanije

Petar Ilic

ponedeljak, 29. Decembar, 2014.

Bojane, veliko hvala na iscrpnom odgovoru.... Takodjer, hvala i na email-u ako zatreba pomoc... Sve najbolje! Petar

Bojan Jovanovic

nedelja, 28. Decembar, 2014.

@Manca — hvala! 1) Potpuno bih se slozio sa vama, bitbucket ne samo sto ima problem sto resenje nije self-hosted, vec kod relativno velikih projekata sa puno modula, pocne da bude guzva i jako brzo se gubi organizacija gde su biblioteke gde su environmenti. To nam nije pre pravilo problem kada smo imali cca 5-10 modula, ali sada vec pocinje polako da nam smeta. Razmisljali smo o gitlab-u kao self hosted resenju, jer stash izadje na cak 3.300$ na 50 user-a, sto mislim da je malo overkill. 2) Da skoro 100% koda nam je python, a ono sto nije je wrappovana C/CPP biblioteka u python. Pozdrav, Bojan

Bojan Jovanovic

nedelja, 28. Decembar, 2014.

@Petar Ilic Pozdrav Petre, u nasem projektu mi smo koristili tri tipa baza, i njihove egzaktne primene smo vec naveli u tekstu, ali bih ukratko napisao generalne razlike i primere nekih implementacija. 1. Relational Databases ( Oracle/MySQL/Postgresql .. ) Sluze za kompleksne hierarhijske strukture tabela, poseduju funkcije za indeksiranje unique keys, razne funkcije za pretragu organizovanih kompleksnih struktura. Primer user information, date of birth, lokacjia 2. No-SQL Databases ( CouchDB/mongoDB ... ) NoSQL baze su dizajnirane za veliku kolicinu podataka daleko su prostije od relacionih, mi ih koristimo za pretragu i organizaciju komunikacionih logova recimo, ali se mogu koristiti za svaku primenu koja zahteva brzu pretragu po nekom kljucu. Jako su proste i mogu da se horizontalno skaliraju. 3. Cache backend ( Redis/Memcached ) Key value pair baza, drzi sve informacije u memoriji izuzetno je brza za pretragu, koristi se za podatke koji se cesto menjaju radi brzog pristupa. Koriste se za keshirane SQL Query-e koji se cesto pozivaju recimo, ili za cak iscrtavanje pre-renderovanih celih stranica web sajta. Znam da je ovo jako prost opis baza podataka koje koristimo, mnogo vise informacija mozete naci na wikipediji o ove tri tehnologije: http://en.wikipedia.org/wiki/Relational_database http://en.wikipedia.org/wiki/NoSQL#Document_store http://en.wikipedia.org/wiki/Redis a za bilo koja detaljnija pitanja mozete mi proslediti email: [email protected]

Manca

nedelja, 28. Decembar, 2014.

Odlican tekst i super izbor za ceo stack. Svaka cast! Ne znam da li ceo kod hostujete na BitBucketu, ali Atlassian isto ima Stash koji je serversko resenje gde su svi GIT repozitorijumi kod vas. Kod nas je politika da sav kod bude kod nas u kontrolisanim uslovima, mada ja licno nemam nista protiv BitBucketa ;) P.S Jel iz Pythona direktno komunicirate sa 3rd party API-jima?

Petar Ilic

subota, 27. Decembar, 2014.

Pozdrav! Po profesiji nisam programer, ali sam nesto zadnjih dana zapeo da pogledam o razlikama sa DB-ovima. U toj pretrazi sam pronasao i ovaj clanak koji me je dosta zaintrigirao s obzirom da ste koristili vise razlicitih DB-a. S obzirom da nisam programerski "nastrojen", zanima me zbog cega ste koristili vise DB-a, tj. tehnologija? Kao primer, ako nije problem, da mi kazete sta se nalazi na svakoj od njih. Naravno, ne bukvalno vec samo kao primer da bih mogao da shvatim "raspodelu duznosti" unutar sistema. Shvatam da na dosta sistema postoji jedna DB, dok ste vi ovde koristili i relacione i ne-relacione baze, pa se rodilo pitanje - zasto? Nadam se da sam bio koliko-toliko "razumljiv" u pitanju. Hvala! Petar

Drasko

četvrtak, 25. Decembar, 2014.

@Bojan Jovanovic Hvala za opsiran odgovor, sve jasno. Nama je takodje RabbitMQ pucao na velikom opterecenju sa Erlang 14 verzijom. Pre oko godinu dana prelaskom na Erlang 16 taj problem je nestao i od tada RabbitMQ nam besprekorno. Pozdrav

Bojan Jovanovic

četvrtak, 25. Decembar, 2014.

@Drasko Python 2.7 naravno, nazalost 3+ ne podrzavaju zilion biblioteka od krucialnog znacaja i jelte niko nece da se igra sa time da dodje u situaciju da mora da portuje nesto na 3+ nedaj boze vezano za gevente ili slicno. Hah, this time next year precicemo na RabbitMQ :) sve mi je jasno, hocu zelim znam da je bolje, znam da ne bih nikada koristio redis, hocu precicemo. Ali problem je bio sto je kod malo stariji i koriscene su stare celery biblioteke kada se taj issue raisovao moguce je da je u medju vremenu nesto resilo problem jedino sto nismo imali tada vremena jer je bilo od krucialnog znacaja da nam MQ radi, ali u trenutku issue-a kad se rasieovao erlang je pucao na 100% proc iz nepoznatih razloga i morali smo brzo da odreagujemo. Bilo je ono menjaj ne zanima me, zamenili smo i nismo istrazivali mnogo uzroke jer eto... this works ( ali potrudicemo se da promenimo, obecavam ). Sto se tice WSGI-a, koristimo gunicorn koj komunicira preko wsgi protokola, pogresno sam se izrazio verovatno u tekstu i nisam ga naveo, znam za uWSGI pricaju da je bolja varijanta u poslednje vreme, mozda i jeste ali jos uvek nismo dosli do tog nivoa optimizacije da nam gunicorn pravi bottleneck. Zao mi je sto ne mogu da izadjem u susret sa tacnim podatkom sta nam je zapravo napravilo issue sa MQ ne znamo ni mi, niti smo mogli da replikujemo ponovo sem tada u produkciji. Takodje, sve pohvale za komentar! pozdrav, Bojan

Drasko

četvrtak, 25. Decembar, 2014.

@Bojan Jovanovic Par pitanja: Python 2 ili Python 3? U firmi u kojoj ja radim vise smo nego zadovoljni sa RabbitMQ, ja licno ne bi ni mogao da ga poredim sa Redisom kada je u pitanju message queueing, pogotovo kada je rec o HA resenju. Koji to RabbitMQ bag Vas je preusmerio ka Redisu? Nginx/WSGI ili Nginx/uWSGI? Ako nije typeo greska zasto bas WSGI, a ne uWSGI? Sve pohvale za text.

Mihailo Joksimovic

sreda, 24. Decembar, 2014.

Dugo nisam procitao zanimljiviji tekst! Sve pohvale autoru.

Nikola

sreda, 24. Decembar, 2014.

Odlican clanak , tech stack sta reci :) , pun pogodak.

milos

utorak, 23. Decembar, 2014.

Odlican izbor. Nisam skoro procitao nesto razumnije i pametnije. nije mi jasno zasto neki i dalje imaju averziju prema Pythonu iako ima definitivno najcitljiviju sintaksu. A za slack ima dostanzamena. Jel ima jos nesto sto bi ste mi gospodine Jovanovicu preporuciki za hostovanje repozitorijuma? Jedva cekam odgovor, hvala.

Bojan Jovanovic

utorak, 23. Decembar, 2014.

@AgroAgro, Siguran sam da postoji gomilu tekstova na netu koje pisu o PHP vs. Python razlikama kao sto sam siguran da skoro na sve ima neko resenje za problem u PHP-u od wrapovanja Cpp biblioteke do dependancy injection-a. Ali kao sto "svaka rupa ima svoju zakrpu", tako da bez daljnjeg da ako budem hteo blog da napravim necu ga sigurno raditi u pythonu nego cu podici wordpress instancu. Svaki kompleksniji potpuno custom modularni projekat koj obuhvata sve od socket management i custom protocol implementacije do simple MVC prezentacije, i naravno podrazumeva da morate da imate minimalni downtime zahteva da radite u jednom od objektnih staticnih mature jezika. Mi smo se odlucili za Pyhon zbog deficita ljudskih resursa i zbog jako tesnih deadline-ova zrtvovali smo "strict"-nost staticnih jezika zarad vece fleksibilnosti i ugodnosti da radimo sa skript jezikom. Python je modularan objektno orijentisan dinamicki jezik, jako je citljiva sintaksa, ima repozitorijum sa izuzetno mnogo ozbiljnih biblioteka, definitivno nam PHP nije bio uopste u razmatranju za implementaciju naseg software-a. A za pros cons quick google mi je nasao ovaj link: https://wiki.python.org/moin/PythonVsPhp

AgroAgro

utorak, 23. Decembar, 2014.

Zasto ne PHP?