Category: Programování

Implementace distribuovaného zámku využívající Redis databáze


Redis databáze není jen tak ledasjaká obyčejná věc, dá se využít k implementaci distribuovaného zámku.

O jednu takovou jsem se pokusil v knihovně https://github.com/abelaska/jedis-lock.

Základem je využití vlastnosti funkce SETNX a tou je SET IF NOT EXISTS, tzn. že uloží hodnotu do požadovaného klíče pouze za podmínky, že klíč v daný moment v databázi neexistuje. Využívá se faktu, že Redis funkce jsou atomické.

Postup pro získání zámku je následující:

  1. SETNX lock.name <aktuální Unix timestamp + lock timeout + 1>, pokud je návratová hodnota 1 byl zámek úspěšně získán, v opačném případě se pokračuje dalším krokem.
  2. GET lock.name, provede se kontrola expirace zámku porovnáním hodnoty klíče zámku s aktuálním časem, tzn. že pokud je hodnota klíče zámku menší než aktuální čas je zámek expirovaný a pokračuje se dalším krokem. Pokud zámek expirovaný není pokračuje se krokem 4.
  3. GETSET lock.name <aktuální Unix timestamp + lock timeout + 1>, pokud funkce navrátí stejnou hodnotu jaká byla získaná v předchozím kroku, byl zámek úspěšně získán a zároveň nastaven nový korektní čas expirace. Pokud zámek nebyl získán pokračuje se následujícím krokem.
  4. Funkce počká 100 milisekund a poté pokračuje 1. krokem. Kroky se opakují dokud neuplyne timeout pro získání zámku (defaultní hodnota je 10 sekund).

Nevýhodné je tohle řešení ve chvíli kdy proces alokuje zámek a potom je ukončen aniž zámek uvolní. V tomto případě ostatní procesy zbytečně dlouho čekají než zámek expiruje. Jeden se s tím musí naučit žít.

Pokud používáte Apache Maven postačí do projektu doplnit novou závislost.

<dependency>
    <groupId>com.github.jedis-lock</groupId>
    <artifactId>jedis-lock</artifactId>
    <version>1.0.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

V příkladu je získán a následně uvolněn zámek s názvem lock.name. Timeout pro získání zámku nastaven na 10 sekund a expirace zámku na 30 sekund.

Jedis jedis = new Jedis("localhost");
JedisLock lock = new JedisLock(jedis, "lock.name", 10000, 30000);
lock.acquire();
try {
  // do some stuff
}
finally {
  lock.release();
}

A nakonec jsem využil https://oss.sonatype.org Maven repositář pro deploy knihovny do Maven Central repositáře. A to přesně podle postupu uvedeném na stránkách Sonatype OSS Maven Repository Usage Guide.

No a to je asi tak všechno. Enjoy 😉

Jak na privátní vzdálený Git repositář zadarmiko


V životě programátorském občas vyvstane potřeba vlastního vzdáleného Git repositáře. Pokud není vyžadován privátní repositář a postačí 300MB dostupného prostor, je možno zdarma využít hostingu na http://github.com/. Tento projekt nabízí potřebnou infrastrukturu pro vedení projektu, jako je wiki, issuer tracker a webové rozhraní Git repositáře. Za mírný poplatek nabízí i privátní repositáře a více dostupného místa.

Já na druhou stranu řešil problém privátního Git repositáře a pokud možno bez nutnosti finančních investice. Nabízela se možnost využití Dropbox, který má v základním programu 2GB prostoru zdarma se zabezpečeným přístupem. Podporované platformy jsou Linux, Windows, MacOS, iPhone, IPad a Android (přibýt má i podpora pro Blackberry), takže ve výsledku je možno data sdílet i mezi odlišnými platformami.

Dropbox je taky možno nahradit za produkt https://www.jungledisk.com/, postup pro použití je shodný, jen JungleDisk nenabízí žádný diskový prostor zdarma.

Dropbox synchronizuje vámi vybraný lokální adresář s vlastním úložným prostorem (je hostován na Amazon). V tomto případě je možno využít klonování lokálně uloženého Git repositáře.

$ git clone file:///home/abelaska/Dropbox/projekt.git

Tímto způsobem je projekt naklonován a je možno jej lokálně modifikovat.

$ cd projekt
$ touch README.txt
$ git add README.txt
$ git commit -m "Přidán prázdný soubor pro popis projektu"
$ git push origin master

V tomto momentě Git uloží změny do pro něj vzdáleného repositáře origin (file:///home/abelaska/Dropbox/projekt.git) a Dropbox pak následně nahraje změněné soubory ve sdíleném adresáři do svého úložiště, odkud si je můžeme stáhnou na jiném počítači, případně s někým sdílet.

Na dalším počítači zase Dropbox adresář sesynchronizuje a pak je na nás abychom si zaktualizovali projekt:

$ git pull origin master

Jednoduché a funkční řešení.

Učím se 3


Jak už to tak bývá, člověk když dlouho nad něčím přemýšlí, tak přijde na to jak udělat věci tak nějak jinak 🙂 A já jsem měl o vánočních svátcích na přemýšlení času dost.

Postupem času, jak jsem víc a víc pracoval s Google App Enginem jsem se začal potýkat s problémy a omezeními. Mezi největší překážku bych řadil persistenci, která je i při využití JPA zbytečně kompilovaná, časově náročná a v mnoha případech složitější dotazy nelze provést. Pro práci s kombinací Grails a GAE neexistuje rozumná podpora ve vývojových prostředích. A hlavně, vývoj aplikací pro GAE je natolik svazující, že hrozba vendor lock-in vám neustále stojí za zády.

Takže pro teď sbohem GAE.

Když už nejsem svázaný řetězy, mohu celou architekturu navrhnout volněji a s větším ohledem na klienty a jejich možnosti. Už delší dobu se pohrávám s myšlenkou využití Amazon EC2. Zatím se to zdá být pro startup ideální prostředí a proto budu navrhovat hostování aplikace tímto směrem.

V hrubých nástinech se mi již v poznámkách rýsuje nová podoba eshopu. I nadále je ve hře oddělená architektura skládající se z klientského frontendu a serverového backendu postaveného na modelu Software-as-a-Service (SaaS).

Či-li hlavní myšlenkou je poskytovat klientům služby eshopu prostřednictvím REST servisů s bohatou nabídkou podporovaných formátů (JSON, XML, HTML), umožňující klientovy vývoj frontendu za použití jak klasických technologií (PHP, Java, ..), tak i čím dál populárnějších RIA technologií (AJAX) nebo jejich kombinací.

Na tento model lze aplikovat koncept „platíš co použiješ“, jehož nesporná výhoda je snížení nákladů klienta na provoz eshopu a uvolněné prostředky může využít pro svůj další rozvoj. Klientovi je ponechána plná volnost ve tvorbě frontendu a platí pouze za použité služby poskytované backendem.

Příště zabrousím do větších detailů.

Učím se 2


Cílem je vytvořit elektronický obchod skládajícího se ze zákaznického frontendu a administrátorského backendu.

K finální verzi se chci dopracovat po sérii verzí implementujících vždy malou skupinu vlastností. Pro jednoho je snesitelnější postupovat k cíli po malých krůčcích.

Seznam vlastností pro první verzi eShops Engine bude vypadat následovně.

Úkoly pro frontend:

  1. vytvoření základního designu
  2. při prvním načtení stránky, kdy není vybraná žádná kategorie sortimentu, se zobrazí prázdný seznam sortimentu, později se zobrazí seznam sortimentu skládající se z akčního a zlevněného zboží
  3. výběr kategorie sortimentu
  4. procházení sortimentu
    1. stránkování seznamu sortimentu vybrané kategorie
    2. třídění seznamu podle ceny, názvu
Návrh designu frontendu

Návrh základního designu frontendu

Navržený design není ničím převratný, ale pro začátek postačí. Později bude možno přidat různé fičury.

Úkoly pro backend:

  1. vytvoření základního designu pro administrační rozhraní v ExtJS
  2. administrace sortimentu
    1. vlastnost sortimentu je název, cena, popis a obrázek (plná velikost, náhled a miniatura)
    2. přidávání sortimentu
    3. odebírání sortimentu
    4. editace sortimentu
      1. editace názvu, popisu, ceny
      2. změna obrázku
  3. administrace stromové struktury kategorií sortimentu
    1. vlastností kategorie sortimentu je název a seznam sortimentu patřícího do dané kategorie (vazba)
    2. přehled stromové struktury kategorií zahrnující drag and drop (DND) organizaci stromové struktury
    3. přidávání kategorie
    4. odebírání kategorie
    5. přidávání a odebírání sortimentu do kategorie (DND)

Java způsob získání statistiky aplikace v App Engine


Jak jsem psal v předchozím příspěvku, pracoval jsem na knihovně, která stáhne z Google App Engine detaily kvót a limitů pro sledování aplikace.

Dnes jsem tuto knihovnu pojmenovanou jako gae-app-manager dokončil a udělal release ve verzi 0.0.1.

Můžete ji najít na http://sourceforge.net/projects/gae-app-manager/

Vydal jsem ji i jako utilitu pro použití v konzole (http://sourceforge.net/projects/gae-app-manager/files/0.0.1/net.sf.gae-app-manager-0.0.1-jar-with-dependencies.jar/download).

Návod pro kompilaci utility http://gae-app-manager.sourceforge.net/.

Enjoy.

$ java -jar net.sf.gae-app-manager-0.0.1-jar-with-dependencies.jar
Usage: java -jar gae-app-manager.jar [full gmail address] [account password] [appspot application name]

Ex.:
java -jar gae-app-manager.jar alois.belaska@gmail.com heslo eshopsengine

$ java -jar target/net.sf.gae-app-manager-0.0.1-SNAPSHOT-jar-with-dependencies.jar alois.belaska@gmail.com ****** eshopsengine
Quotas are reset every 24 hours. Next reset: 19 hours
REQUESTS_CPU_TIME[0.00/6.50 (0%) CPU hours,OKAY]
REQUESTS_COUNT[2/1333328 (0%),OKAY]
REQUESTS_OUTGOING_BANDWIDTH[0.00/1.00 (0%) GBytes,OKAY]
REQUESTS_INCOMING_BANDWIDTH[0.00/1.00 (0%) GBytes,OKAY]
REQUESTS_SECURE_COUNT[0/1333328 (0%),OKAY]
REQUESTS_SECURE_OUTGOING_BANDWIDTH[0.00/1.00 (0%) GBytes,OKAY]
REQUESTS_SECURE_INCOMING_BANDWIDTH[0.00/1.00 (0%) GBytes,OKAY]
STORAGE_DATASTORE_API_CALLS[0/10368000 (0%),OKAY]
STORAGE_BLOBSTORE_API_CALLS[0/10368000 (0%),OKAY]
STORAGE_TOTAL_STORED_DATA[0.00/1.00 (0%) GBytes,OKAY]
STORAGE_BLOBSTORE_STORED_DATA[0.00/1.00 (0%) GBytes,OKAY]
STORAGE_DATA_SENT_TO_DATASTORE_API[0.00/12.00 (0%) GBytes,OKAY]
STORAGE_DATA_RECEIVED_FROM_DATASTORE_API[0.00/116.00 (0%) GBytes,OKAY]
STORAGE_DATASTORE_CPU_TIME[0.00/62.11 (0%) CPU hours,OKAY]
MAIL_MAIL_API_CALLS[0/7000 (0%),OKAY]
MAIL_RECIPIENTS_EMAILED[0/2000 (0%),OKAY]
MAIL_ADMINS_EMAILED[0/5000 (0%),OKAY]
MAIL_MESSAGE_BODY_DATA_SENT[0.00/0.06 (0%) GBytes,OKAY]
MAIL_ATTACHMENTS_SENT[0/2000 (0%),OKAY]
MAIL_ATTACHMENT_DATA_SENT[0.00/0.10 (0%) GBytes,OKAY]
URLFETCH_API_CALLS[0/657084 (0%),OKAY]
URLFETCH_DATA_SENT[0.00/4.00 (0%) GBytes,OKAY]
URLFETCH_DATA_RECEIVED[0.00/4.00 (0%) GBytes,OKAY]
IMAGEMANIPULATION_API_CALLS[0/864000 (0%),OKAY]
IMAGEMANIPULATION_DATA_SENT_TO_API[0.00/1.00 (0%) GBytes,OKAY]
IMAGEMANIPULATION_DATA_RECEIVED_FROM_API[0.00/5.00 (0%) GBytes,OKAY]
IMAGEMANIPULATION_TRANSFORMATIONS_EXECUTED[0/2592000 (0%),OKAY]
MEMCACHE_API_CALLS[0/8640000 (0%),OKAY]
MEMCACHE_DATA_SENT_TO_API[0.00/1.00 (0%) GBytes,OKAY]
MEMCACHE_DATA_RECEIVED_FROM_API[0.00/5.00 (0%) GBytes,OKAY]
XMPP_API_CALLS[0/657084 (0%),OKAY]
XMPP_DATA_SENT[0.00/4.00 (0%) GBytes,OKAY]
XMPP_RECIPIENTS_MESSAGED[0/657084 (0%),OKAY]
XMPP_INVITATIONS_SENT[0/1000 (0%),OKAY]
TASKQUEUE_API_CALLS[0/100000 (0%),OKAY]
DEPLOYMENTS_COUNT[0/1000 (0%),OKAY]

Získání stránky se statistikou aplikace v App Engine přes curl


Při řešení problému dohledování aplikací běžících v Google App Engine jsem narazil na problém chybějícího API pro získání limitů a kvót.

Tak mě napadlo, skriptuj. Chvíli to trvalo, ale nakonec jsem se dopracoval k funkčnímu řešení, které se přihlásí přes google account do administračního rozhraní App Engine a stáhne stránku „Quota Details“ vybrané aplikace.

#!/bin/sh
#
email="vas.email@gmail.com"
password="vase heslo"
application="nazev vasi aplikace"
sourceid="$application-WatchDog"

auth=`curl -s https://www.google.com/accounts/ClientLogin -d "Email=$email" -d "Passwd=$password" -d accountType=GOOGLE -d "source=$sourceid" -d service="ah" | grep 'Auth' | cut -d '=' -f 2`

cookie=`mktemp /tmp/cookie.eshops.XXXX`

curl -s -L -c "$cookie" "https://appengine.google.com/_ah/login?&amp;auth=$auth"

ACSID=`grep ACSID $cookie | sed -e "s/.*ACSID\t\(.*\)/\1/"`

rm -f "$cookie"

curl -s -H "Cookie: ACSID=$ACSID" "https://appengine.google.com/dashboard/quotadetails?&amp;app_id=$application"

Další rozparsování této stránky už ponechám na vás.

Momentálně pracuju na totožné implementaci v Javě. Tam bude navíc i rozparsování údajů ze stažené stránky.

Uživatel s vypnutou podporou Javascript?


Četl sem pár článků o tom jaké procento uživatelů má vypnutou podporu Javascript. Házely čísly přibližne do 7%. Co za lidi vypne podporu Javascript? To by mě zajímalo jak to je.

Má smysl v dnešní době interakticního webu vůbec brát v potaz možnost vypnuté podpory Javascript v prohlížeči? Investovat nemalé množství času, a potažmo peněz, do podpory takové skupiny uživatelů?

Může si architekt webové aplikace dovolit ignorovat uživatele s vypnutým Javascriptem?

Myslím, že si to dovolit může. Podmínkou by ovšem mělo být upozornění uživatele na fakt, že pokud mají vypnutý Javascript nebude jim aplikace fungovat na 100%, pokud vůbec. A nabídnou jim řešení této situace.

A jaký je váš názor?