Vjerojatno nije iznenađenje da je prošla godina bila godina velikih promjena za Apache Hadoop. Tijekom prošle godine došlo je do spajanja Cloudera i Hortonworks (u suštini, preuzimanje potonjeg), dok je Mapr, zbog ozbiljnih financijskih problema, prodan Hewlett Packardu. Ako smo nekoliko godina ranije imali izbor između Cloudera i Hortonworks za on-premises instalacije, danas, nažalost, tog izbora više nema. Iznenađenje je bila i odluka Cloudera da od veljače ove godine prestane ispuštati binarne verzije svoje distribucije u javni repozitorij, a sada su dostupne samo uz plaćenu pretplatu. Naravno, još uvijek postoji mogućnost preuzimanja posljednjih verzija CDH i HDP objavljenih do kraja 2019. godine, a podrška za njih predviđena je u narednih godinu do dvije. No, što dalje? Za one koji su ranije plaćali pretplatu, ništa se nije promijenilo. A za one koji ne žele prijeći na plaćenu verziju distribucije, a žele imati mogućnost preuzimanja novih verzija komponenti klastera, zakrpa i druge nadogradnje, pripremili smo ovaj članak. U njemu ćemo razmotriti moguće opcije izlaska iz ove situacije.
Članak je više pregledan. U njemu neće biti usporedbe distribucija niti detaljnog razrađivanja, niti recepata za njihovu instalaciju i konfiguraciju. A što će biti? Ukratko ćemo predstaviti distribuciju Arenadata Hadoop, koja zaslužuje našu pažnju zbog svoje dostupnosti, što danas predstavlja veliku rijetkost. Nakon toga ćemo razgovarati o Vanilla Hadoopu, uglavnom o tome kako ga možete 'pripremiti' pomoću Apache Bigtopa. Spremni? Onda dobrodošli ispod.
Arenadata Hadoop

To je potpuno nova i, za sada, malo poznata distribucija domaće izrade. Nažalost, trenutno postoje samo .
O detaljnijim informacijama možete pronaći na službenoj projekta. Posljednje verzije distribucije bazirane su na Hadoop 3.1.2 za 3. verziju, i 2.8.5 za 2. verziju.
Informacije o roadmapu možete pronaći .

Ssučelje Arenadata Cluster Manager
Ključni proizvod Arenadata je , koji se koristi za instalaciju, postavljanje i nadzor raznih softverskih rješenja tvrtke. ADCM se distribuira besplatno, a njegova funkcionalnost se proširuje dodavanjem bundle-a, koji predstavljaju skup ansible-playbooka. Bundle-i su podijeljeni u dvije vrste: enterprise i community. Potonje su dostupne za besplatno preuzimanje s web stranice Arenadata. Također postoji mogućnost izrade vlastitog bundle-a i povezivanja s ADCM.
Za deployment i upravljanje Hadoop 3 nudi se community verzija bundle-a u kombinaciji s ADCM, dok za Hadoop 2 postoji samo kao alternativa. Što se tiče repozitorija s paketima, oni su otvoreni za javni pristup, mogu se preuzeti i instalirati na uobičajen način za sve komponente klastera. Ukupno, distribucija izgleda prilično zanimljivo. Siguran sam da će biti onih koji su navikli na rješenja poput Cloudera Manager i Ambari, i kojima će se ADCM svidjeti. Za nekoga će biti veliki plus i to što distribucija za zamjenu uvoza.
Ako govorimo o minusima, oni će biti isti kao i za sve ostale distribucije Hadoopa. Naime:
- Tzv. «vendor lock-in». Na primjer, Cloudera i Hortonworks već su pokazali da uvijek postoji rizik od promjene politike tvrtke.
- Značajno kašnjenje u odnosu na upstream Apache.
Vanilla Hadoop

Kao što znate, Hadoop nije monolitni proizvod, nego u suštini čitava plejada servisa oko njegove distribuirane datotečne sistema HDFS. Malo tko će biti zadovoljan samo jednim datotečnim klasterom. Nečemu je potreban Hive, drugome Presto, a tu su još i HBase i Phoenix, dok se Spark sve više koristi. Za orkestraciju i učitavanje podataka ponekad se koriste Oozie, Sqoop i Flume. A kada se postavi pitanje sigurnosti, odmah se sjeti Kerberos u kombinaciji s Rangerom.
Binarnu verzije Hadoop komponenti dostupne su na stranicama svakog od projekata ekosustava u obliku tarball-a. Mogu ih se preuzeti i započeti instalacija, ali s jednim uvjetom: osim samostalne izgradnje paketa iz "sirovih" binarnih datoteka, za što vjerojatno želite, nećete imati nikakvu sigurnost u kompatibilnost preuzetih verzija komponenti međusobno. Preferabilnija opcija je izgradnja uz pomoć Apache Bigtopa. Bigtop omogućuje izgradnju iz Apache maven repozitorija, pokretanje testova i izgradnju paketa. No, što je za nas vrlo važno, Bigtop će sastaviti verzije komponenti koje će biti međusobno kompatibilne. O tome ćemo detaljnije govoriti u nastavku.
Apache Bigtop

Apache Bigtop je alat za izgradnju, pakiranje i testiranje niza
open source projekata, poput Hadoop-a i Greenplum-a. Bigtop ima mnoštvo
izdanja. U trenutku pisanja ovog članka, posljednje stabilno izdanje bila je verzija 1.4,
dok je u masteru bila 1.5. U različitim verzijama izdanja koriste se različite verzije
komponenti. Na primjer, za 1.4 core-komponente Hadoop imaju verziju 2.8.5, dok u masteru
2.10.0. Također se mijenja sastav podržanih komponenti. Nešto zastarjelo i
neobnavljano se uklanja, a na njegovo mjesto dolazi nešto novo, traženije, i
ne mora nužno biti iz obitelji Apache.
Osim toga, Bigtop ima mnoštvo .
Kada smo se počeli upoznavati s Bigtop-om, prvo što nas iznenadilo bila je njegova skromna, u usporedbi s drugim Apache projektima, rasprostranjenost i prepoznatljivost, kao i vrlo mala zajednica. Iz toga slijedi da je informacija o proizvodu minimalna, a pronalaženje rješenja nastalih problema po forumima i mailing listama možda neće dati ništa. U početku nam je bila teška zadaća izvršiti punu izgradnju distribucije zbog osobitosti samog alata, ali o tome ćemo malo kasnije.
Kao teaser - onima kojima su u svoje vrijeme bili zanimljivi projekti Linux svemira, poput Gentoo-a i LFS-a, možda će biti nostalgija raditi s ovom stvari i prisjetiti se tih "bajkovitih" vremena kada smo sami tražili (ili pisali) ebuild-ove i redovito ih ponovno gradili s novim zakrpama za Mozillu.
Velika prednost Bigtopa je otvorenost i univerzalnost alata na kojima se temelji. U njegovoj osnovi su Gradle i Apache Maven. Gradle je dobro poznati alat koji Google koristi za izgradnju Androida. Fleksibilan je i, kako se kaže, „proveren u praksi“. Maven je standardni alat za izgradnju projekata unutar Apachea, i pošto se većina njegovih proizvoda proizvodi upravo preko Mavena, nije moglo proći bez njega. Treba obratiti pažnju na POM (model objekta projekta) – „fundamentalna“ xml-datoteka koja opisuje sve što je potrebno za rad Mavena s vašim projektom, oko koje se odvija sav rad. Tačno u
delu Mavena javljaju se neki problemi na koje obično naiđu oni koji se prvi put susreću s Bigtopom.
Praksa
Pa, odakle da počnemo? Idemo na stranicu za preuzimanje i skidamo najnoviju stabilnu verziju u obliku arhive. Tamo se mogu naći i binarni artefakti koje je skupio Bigtop. Usput, među poznatim upraviteljima paketa podržani su YUM i APT.
Alternativno, možete preuzeti najnoviju stabilnu verziju direktno s
github:
$ git clone --branch branch-1.4 https://github.com/apache/bigtop.gitKloni u „bigtop“...
remote: Nabrajanje objekata: 46, završeno.
remote: Brojanje objekata: 100% (46/46), završeno.
remote: Kompresija objekata: 100% (41/41), završeno.
remote: Ukupno 40217 (delta 14), ponovo korišćeno 10 (delta 1), pakovanje ponovo korišćenih 40171
Preuzimanje objekata: 100% (40217/40217), 43.54 MiB | 1.05 MiB/s, završeno.
Određivanje promena: 100% (20503/20503), završeno.
Ažuriranje datoteka: 100% (1998/1998), završeno.Izgleda da je rezultat u direktoriju ./bigtop otprilike ovakav:
./bigtop-bigpetstore — demonstracione aplikacije, sintetički primeri
./bigtop-ci — CI alati, jenkins
./bigtop-data-generators — generisanje podataka, sintetika, za smoke testove itd.
./bigtop-deploy — alati za implementaciju
./bigtop-packages — konfiguracije, skripte, zakrpe za izgradnju, glavna komponenta alata
./bigtop-test-framework — framework za testiranje
./bigtop-tests — stvarni testovi, opterećenja i smoke
./bigtop_toolchain — okruženje za izgradnju, priprema okruženja za rad alata
./build — radni katalog za izgradnju
./dl — katalog za preuzete izvore
./docker — izgradnja u docker slikama, testiranje
./gradle — gradle konfiguracija
./output — katalog u koji dolaze artefakti izgradnje
./provisioner — provizijoning
Najzanimljivije u ovom trenutku za nas je glavna konfiguracija ./bigtop/bigtop.bom, u kojem vidimo sve podržane komponente s verzijama. Ovdje možemo odabrati drugu verziju proizvoda (ako želimo isprobati neku drugu) ili verziju izgradnje (ako smo, na primjer, dodali značajan patch).
Također, velika pozornost se posvećuje poddirektoriju .\/bigtop\/bigtop-packages, koji ima izravnu povezanost s procesom izgradnje komponenti i paketa s njima.
Dakle, skinuli smo arhivu, raspakirali je ili napravili klon s github-a, možemo li početi s izgradnjom?
Ne, prvo ćemo pripremiti okruženje.
Priprema okruženja
I ovdje treba malo skrenuti pažnju. Za izgradnju praktično bilo kojeg složenijeg proizvoda potrebno je određeno okruženje — u našem slučaju to je JDK, iste dijeljene biblioteke, zaglavlja itd., alati poput ant, ivy2 i još mnogo toga. Jedna od opcija za dobivanje potrebnog Bigtop okruženja je instalacija potrebnih komponenti na host koji gradi. Mogu se zabavljati u kronologiji, ali izgleda da je s verzijom 1.0 također došla opcija izgradnje u unaprijed konfiguriranim i dostupnim docker slikama, s kojima se može upoznati ovdje.
Što se tiče pripreme okruženja, postoji pomagač — Puppet.
Možete koristiti sljedeće komande, izvođenje se vrši iz korijenskog direktorija
alata, .\/bigtop:
.\/gradlew toolchain\n.\/gradlew toolchain-devtools\n.\/gradlew toolchain-puppetmodules
Ili izravno preko puppeta:
puppet apply --modulepath=<path_to_bigtop> -e "include bigtop_toolchain::installer"\npuppet apply --modulepath=<path_to_bigtop> -e "include bigtop_toolchain::deployment-tools"\npuppet apply --modulepath=<path_to_bigtop> -e "include bigtop_toolchain::development-tools"Nažalost, već u ovoj fazi mogu nastati poteškoće. Opći savjet ovdje je – koristiti podržanu distribuciju, u aktualnom stanju na hostu za izgradnju ili isprobati put s docker-om.
Izgradnja
Što možemo pokušati izgraditi? Odgovor na to pitanje dat će ishod komande
.\/gradlew tasks U odjeljku Package tasks postoji niz proizvoda koji su konačni artefakti Bigtop-a.
Mogu se odrediti po sufiksu -rpm ili -pkg-ind (u slučaju izgradnje
u docker-u). U našem slučaju najzanimljiviji je Hadoop.
Pokušajmo izvršiti izgradnju u okruženju našeg build servera:
.\/gradlew hadoop-rpmBigtop će automatski preuzeti potrebne izvore potrebne za određenu komponentu i započeti izgradnju. Tako su rad alata vezani uz Maven repozitorije i druge izvore, što znači da mu je potrebna internetska povezanost.
Tijekom rada generira se standardni izlaz. Ponekad se iz njega i iz poruka o greškama može shvatiti što nije u redu. A ponekad je potrebno dobiti dodatne informacije. U tom slučaju treba dodati argumente --info ili --debug, a također može biti korisno –stacktrace. Postoji jednostavan način za oblikovanje skupa podataka za kasnije slanje na mailing liste, ključ --scan.
Pomoću njega bigtop će prikupiti sve informacije i objaviti ih u gradle, nakon čega će dati vezu,
putem koje kompetentna osoba može shvatiti zašto izgradnja nije uspjela.
Treba imati na umu da ova opcija može javno prikazati nepoželjne informacije, poput imena korisnika, nodova, varijabli okruženja itd., stoga budite oprezni.
Često su greške rezultat nemogućnosti dobivanja potrebnih komponenti za izgradnju. Obično se problem može riješiti stvaranjem zakrpe za ispravku nečega u izvorima, na primjer, adrese u pom.xml u korijenskom katalogu izvora. To se radi stvaranjem i postavljanjem u odgovarajući katalog .\/bigtop\/bigtop-packages\/src\/common\/oozie\/ zakrpe, na primjer, u obliku patch2-fix.diff.
--- a\/pom.xml
+++ b\/pom.xml
@@ -136,7 +136,7 @@
central
- http:\/\/repo1.maven.org\/maven2
+ https:\/\/repo1.maven.org\/maven2
false
Vjerojatno, u trenutku kada čitate ovaj članak, nećete morati sami napraviti gore navedenu ispravku.
Pri implementaciji bilo kakvih zakrpa i izmjena u mehanizmu izgradnje može biti potrebno "očistiti" izgradnju putem naredbe čišćenja:
.\/gradlew hadoop-clean
> Task :hadoop_vardefines
> Task :hadoop-clean
BUILD SUCCESSFUL in 5s
2 actionable tasks: 2 executedOva operacija će vratiti sve izmjene u izgradnji ove komponente, nakon čega će se izgradnja izvršiti ponovo. Ovaj put probajmo izgraditi projekt u docker slici:
.\/gradlew -POS=centos-7 -Pprefix=1.2.1 hadoop-pkg-ind
> Task :hadoop-pkg-ind
Gradi 1.2.1 hadoop-pkg na centos-7 u Dockeru...
+++ dirname .\/bigtop-ci\/build.sh
++ cd .\/bigtop-ci\/..
++ pwd
+ BIGTOP_HOME=\/tmp\/bigtop
+ '[' 6 -eq 0 ']'
+ [[ 6 -gt 0 ]]
+ key=--prefix
+ case $key in
+ PREFIX=1.2.1
+ shift
+ shift
+ [[ 4 -gt 0 ]]
+ key=--os
+ case $key in
+ OS=centos-7
+ shift
+ shift
+ [[ 2 -gt 0 ]]
+ key=--target
+ case $key in
+ TARGET=hadoop-pkg
+ shift
+ shift
+ [[ 0 -gt 0 ]]
+ '[' -z x ']'
+ '[' -z x ']'
+ '[' '' == true ']'
+ IMAGE_NAME=bigtop\/slaves:1.2.1-centos-7
++ uname -m
+ ARCH=x86_64
+ '[' x86_64 '!=' x86_64 ']'
++ docker run -d bigtop\/slaves:1.2.1-centos-7 \/sbin\/init
+
CONTAINER_ID=0ce5ac5ca955b822a3e6c5eb3f477f0a152cd27d5487680f77e33fbe66b5bed8
+ trap 'docker rm -f
0ce5ac5ca955b822a3e6c5eb3f477f0a152cd27d5487680f77e33fbe66b5bed8' EXIT
....
velik broj izlaznih podataka
....
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-yarn-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-mapreduce-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-namenode-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-secondarynamenode-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-zkfc-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-journalnode-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-datanode-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-httpfs-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-yarn-resourcemanager-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-yarn-nodemanager-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-yarn-proxyserver-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-yarn-timelineserver-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-mapreduce-historyserver-2.8.5-
1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-client-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-conf-pseudo-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-doc-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-libhdfs-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-libhdfs-devel-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-hdfs-fuse-2.8.5-1.el7.x86_64.rpm
Zapisano: \/bigtop\/build\/hadoop\/rpm\/RPMS\/x86_64\/hadoop-debuginfo-2.8.5-1.el7.x86_64.rpm
+ umask 022
+ cd \/bigtop\/build\/hadoop\/rpm\/\/BUILD
+ cd hadoop-2.8.5-src
+ \/usr\/bin\/rm -rf \/bigtop\/build\/hadoop\/rpm\/BUILDROOT\/hadoop-2.8.5-1.el7.x86_64
Izvršavanje(%clean): \/bin\/sh -e \/var\/tmp\/rpm-tmp.uQ2FCn
+ exit 0
+ umask 022
Izvršavanje(--clean): \/bin\/sh -e \/var\/tmp\/rpm-tmp.CwDb22
+ cd \/bigtop\/build\/hadoop\/rpm\/\/BUILD
+ rm -rf hadoop-2.8.5-src
+ exit 0
[ant:touch] Kreiranje \/bigtop\/build\/hadoop\/.rpm
:hadoop-rpm (Thread[Task worker for ':',5,main]) završeno. Trajalo je 38 min 1.151 sek.
:hadoop-pkg (Thread[Task worker for ':',5,main]) započeto.
> Task :hadoop-pkg
Zadatak ':hadoop-pkg' nije ažuriran jer:
Zadatak nije izjavio nikakve izlaze unatoč izvršavanju akcija.
:hadoop-pkg (Thread[Task worker for ':',5,main]) završeno. Trajalo je 0.0 sek.
IZGRADNJA USPJEŠNA u 40m 37s
6 akcijskih zadataka: 6 izvršeno
+ RESULT=0
+ mkdir -p output
+ docker cp
ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb:\/bigtop\/build .
+ docker cp
ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb:\/bigtop\/output .
+ docker rm -f ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb
ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb
+ '[' 0 -ne 0 ']'
+ docker rm -f ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb
Greška: Nema takvog kontejnera:
ac46014fd9501bdc86b6c67d08789fbdc6ee46a2645550ff6b6712f7d02ffebb
IZGRADNJA USPJEŠNA u 41m 24s
1 akcijski zadatak: 1 izvršenIzgradnja je izvršena na CentOS-u, ali se može izvršiti i na Ubuntu-u:
.\/gradlew -POS=ubuntu-16.04 -Pprefix=1.2.1 hadoop-pkg-indOsim izgradnje paketa za različite Linux distribucije, alat može formirati repozitorij s izgrađenim paketima, na primjer:
.\/gradlew yumTakođer se može posjetiti i smoke testove i implementaciju u docker.
Stvoriti klaster od tri čvora:
.\/gradlew -Pnum_instances=3 docker-provisionerPokrenuti smoke testove u klasteru od tri čvora:
.\/gradlew -Pnum_instances=3 -Prun_smoke_tests docker-provisionerIzbrisati klaster:
.\/gradlew docker-provisioner-destroyDobiti naredbe za povezivanje unutar docker kontejnera:
.\/gradlew docker-provisioner-sshPrikazati stanje:
.\/gradlew docker-provisioner-statusDetaljnije o Deployment tasks možete pročitati u dokumentaciji.
Što se tiče testova, postoji prilično velik broj, pretežno smoke i integracijskih. Njihova analiza izlazi iz okvira ovog članka. Mogu reći samo da izgradnja distribucije nije toliko složen zadatak koliko se na prvi pogled čini. Sve komponente koje koristimo u našoj produkciji uspješno su izgrađene i prošle su testove, a također nismo imali problema s njihovim uvođenjem i izvršavanjem osnovnih operacija u testnom okruženju.
Osim postojećih komponenti u Bigtop-u, postoji mogućnost dodavanja još nečega, čak i vlastitog softverskog razvoja. Sve se to odlično automatizira i uklapa u koncept CI/CD.
Zaključak
Očigledno je da izgrađena distribucija ovako ne bi trebala odmah ići u produkciju. Treba razumjeti da ako postoji stvarna potreba za izgradnjom i podrškom vlastite distribucije, u to treba uložiti financijski i vremenski.
Ipak, uz pravi pristup i profesionalni tim, može se proći i bez komercijalnih rješenja.
Važno je napomenuti da sam projekt Bigtop treba razvoj i izgleda da se trenutačno ne odvija aktivni razvoj. Također nije jasno kada će se pojaviti Hadoop 3. Uzgred, ako imate stvarnu potrebu za izgradnjom Hadoop 3, možete pogledati od Arenadata, koji osim standardnih
komponenti nudi još čitav niz dodatnih (Ranger, Knox, NiFi).
Što se tiče Rostelecom-a, za nas je Bigtop jedna od razmatranih opcija danas. Hoćemo li se odlučiti za njega ili ne, pokazat će vrijeme.
Dodatak
Da biste uključili novu komponentu u gradnju, potrebno je dodati njezin opis u bigtop.bom i ./bigtop-packages. Možete pokušati učiniti to prema postojećim komponentama. Pokušajte se snaći. Nije tako teško kao što izgleda na prvi pogled.
Što vi mislite? Radujemo se vidjeti vaše mišljenje u komentarima i hvala na pažnji!
Članak je pripremila ekipa za upravljanje podacima «Rostelekoma»
Izvor: habr.com
