Cíl

Hlavním cílem této úlohy je implementovat jednoduchou serverovou aplikaci a optimalizovat její výkon tak, aby zvládala obsluhu velkého množství klientů a požadavků. Pro implementaci serveru si můžete zvolit jakoukoli platformu (HW, OS, programovací jazyk, framework, …).

Vedlejší cíle jsou naučit se pracovat s dokumentací a zdrojovými kódy použitých platforem (zejména těch založených na open source softwaru), aplikace znalostí nabytých na přednáškách a získání přehledu o výkonnosti jednotlivých platforem.

Zadání úkolu

Vytvořte serverovou aplikaci komunikující protokolem HTTP, která bude sloužit k počítání unikátních slov v datech zaslaných klienty. Na server jsou kladeny následující požadavky:

  • Klienti posílají data pomocí metody POST s cestou /osp/myserver/data. Data jsou ve formátu čistého textu (text/plain) v kódování UTF-8 komprimovaného metodou gzip.
  • Server obsahuje “čítač jedinečných slov”. Při spuštění serveru je tento čítač roven 0.
  • Server si vede evidenci o slovech zaslaných v jednotlivých požadavcích a pro každé nové slovo, které ještě nemá v evidenci zvýší čítač jedinečných slov o jedna.
  • Na požadavek GET s cestou /osp/myserver/count server odpoví aktuální hodnotou čítače jedinečných slov a tento čítač vynuluje. Hodnota se přenáší jako dekadické číslo v UTF-8 kódování.
  • Server musí zvládnou obsluhovat velké množství (cca 100) současně připojených klientů.

Příklad

Předpokládejme, že náš server běží na lokálním počítači (t.j. localhost) na portu 8080. Použijeme program curl k posílání požadavků serveru:

curl localhost:8080/osp/myserver/data --data-binary @<(echo první pokus|gzip)
curl localhost:8080/osp/myserver/data --data-binary @<(echo druhý pokus|gzip)
curl localhost:8080/osp/myserver/count --output -

Výstupem posledního příkazu bude řetězec “3”. Místo posledního příkazu můžete použít i webový prohlížeč nasměrovaný na adresu http://localhost:8000/osp/myserver/count.

Poznámka: Syntaxe <(příkaz...) je tzv. process substitution v interpreteru bash. Jedná se o jeden z možných způsobů předání binárních dat na příkazové řádce.

Výkon serveru

Výkon serveru bude měřen testovacím programem, který bude serveru posílat větší množství dat a poté se zeptá na aktuální hodnotu čítače jedinečných slov. Bude se měřit celkový čas od odeslání prvního požadavku typu POST do příjmu hodnoty čítače jedinečných slov.

Akceptována budou řešení jejichž celkový čas bude dvakrát menší než čas naměřený s níže uvedeným ukázkovým serverem bežícím na školním počítači v laboratoři.

Ukázkový server

Zde uvádíme jednoduchý server napsaný v jazyce Python, který splňuje výše uvedené požadavky (kromě výkonnosti). Můžete ho použít jako referenci či startovací bod pro vaší implementaci.

#!/usr/bin/python3

from http.server import HTTPServer, BaseHTTPRequestHandler
import gzip

words = {}

class OSPHTTPHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        global words
        if self.path == "/osp/myserver/data":
            length = int(self.headers.get('Content-Length'))
            text = gzip.decompress(self.rfile.read(length)).decode("utf-8")
            for word in text.split():
                words[word] = 1;
            self.send_response(204) # No Content
            self.end_headers()
        else:
            self.send_response(404)
            self.end_headers()

    def do_GET(self):
        global words
        if self.path == "/osp/myserver/count":
            self.send_response(200)
            self.send_header("Content-type", "text/plain")
            self.end_headers()
            self.wfile.write(str(len(words)).encode())
            words = {}
        else:
            self.send_response(404)
            self.end_headers()

class HTTPServerIPv6(HTTPServer):
    import socket
    address_family = socket.AF_INET6

# httpd = HTTPServer(('', 8080), OSPHTTPHandler) # Use if your system uses IPv4 by default
httpd = HTTPServerIPv6(('', 8080), OSPHTTPHandler) # Use if your system uses IPv6 by default
print("Listening on port", httpd.server_port)
httpd.serve_forever()

Pokud se k tomuto ukázkovému serveru připojí mnoho klientů, bude “přetížen” a čas od času bude klienty odmítat. Takže prvním krokem vašeho řešení může být zjištění příčiny tohoto chování a její napravení.

Testování a měření výkonu

Pro testování použijte odevzdávací systém, kam zadáte informace o vašem serveru a můžete ho nechat otestovat. Pět nejlepších studentů dostane 1 až 5 bonusových bodů.

Odevzdávací systém běží momentálně v testovacím provozu. Je možné, že naměřené hodnoty budou horší, než jaké lze z vašeho serveru “vymáčknout”.

Jak je definováno unikátní slovo vzhledem k velkým a malým písmenům, diakritice a interpunkci? Jsou interpunkční znaménka samostatné slovo?
Comment by kurkavo1 So 28. březen 2015, 15:14:33 CET

Po zavolani osp-server-tester localhost 8000 —more mi testovaci script vyhodi hlasku:

shutdown(sfd, SHUT_WR) line 101: Transport endpoint is not connected

nema nekdo podobnou zkusenost, pridane radu?

Comment by janatjak So 28. březen 2015, 18:13:00 CET

Jak je definováno unikátní slovo vzhledem k velkým a malým písmenům, diakritice a interpunkci? Jsou interpunkční znaménka samostatné slovo?

Unikátní slovo je definováno tak, jak je to naimplementováno v ukázkovém serveru, t.j. rozlišuje se velikost písmen, diakritika i interpunkce. Jednotlivá slova jsou oddělena jedním nebo více bílými znaky (mezera, tabulátor, CR, LF). Viz implementace str.split() v Pythonu.

Comment by sojkam1 So 28. březen 2015, 21:34:39 CET

Po zavolani osp-server-tester localhost 8000 —more mi testovaci script vyhodi hlasku:

shutdown(sfd, SHUT_WR) line 101: Transport endpoint is not connected

Co je na druhé straně za server? Ten ukázkový z této stránky, nebo nějaký jiný? Na jakém systému to spouštíte? Nezavíráte na serveru spojení dřív, než přijdou všechna data?

Doporučuji přesunout tuto diskusi na osp@rtime.felk.cvut.cz.

Comment by sojkam1 So 28. březen 2015, 21:52:57 CET

Vzhledem k

Pro implementaci serveru si můžete zvolit jakoukoli platformu (HW, OS, programovací jazyk, framework, …)

To znamena ze muzu pouzit, napriklad, Ngynx + napsat fastcgi modul k nemu? Estli chci pouzit Windows, jak bude probihat testovani? Jaka je konfigurace HW?

Comment by toporal1 Po 30. březen 2015, 10:36:41 CEST

To znamena ze muzu pouzit, napriklad, Ngynx + napsat fastcgi modul k nemu? Estli chci pouzit Windows, jak bude probihat testovani? Jaka je konfigurace HW?

Můžete použít libovolnou platformu. Testování bude probíhat tak, že do formuláře odevzdávacího systému zadáte IP adresu Vašeho řešení, systém bude posílat requesty stejně jako to dělá aktuální testovací program a bude se měřit a zaznamenávat doba běhu.

Serverová část poběží na HW podle Vašeho výběru, klientská testovací část poběží na školním počítači.

Comment by hornmich Po 30. březen 2015, 11:09:17 CEST

Mám rovněž problém s hláškou:

shutdown(sfd, SHUT_WR) line 101: Transport endpoint is not connected Implementaci mám v javě 1.7, server běží na jednom počítači a snažím se k němu připojit z druhého - ve stejné LAN - s parametrem —more. Pokud je klient spuštěn na stejném počítači jako server, problém se nevyskytuje.

len = read(sfd, response, sizeof(response)-1) line 102: Connection reset by peer Tato hláška se rovněž zobrazuje pokud je klient spuštěn na jiném počítači než server.

Pokud k otestování použiji curl, tak vše proběhne korektně.

Ještě bych měl dotaz k dělení slov. Používám standardní funkci split od java Stringu zprava.trim().split("\\s+|\\t+")), který rozdělí slova podle bílých znaků a pro jistotu ještě kontroluji, zda délka Stringu není 0, avšak stále dostávám o 4 slova více než ukázkový skript. Je to velký problém?

Comment by kurkavo1 Čt 2. duben 2015, 19:50:11 CEST
Vy, kdož máte problémy s chybou „shutdown„, nepíšete na jakém OS běží váš server. Na Linuxu se mi problém nevyskytuje. Můžete někdo potvrdit, že se to vyskytuje na Windows?
Comment by sojkam1 Čt 2. duben 2015, 21:44:24 CEST
Nainstaloval jsem novou verzi nástroje osp-server-tester, která už negeneruje problematická slova, takže dobrat se správného počtu slov by mělo být jednodušší. Také jsem se pokoušel opravit problém s shutdown(), ale nevím, jestli se to povedlo, protože ho neumím zreprodukovat.
Comment by sojkam1 Pá 3. duben 2015, 17:02:13 CEST

Byl zprovozněn odevzdávací systém. Momentálně je v testovacím provozu což znamená, že výkon testeru ještě není optimálně vyladěn. Pokud se vám zdá, že váš server plně nevytížíme, ještě se to zlepší.

Comment by sojkam1 Pá 3. duben 2015, 21:31:19 CEST

Od nové verze mi to přestalo házet chybu s shutdown (provozováno mezi Mint a Debian) a spravil se i celkový počet slov. Problém s

len = write(sfd, data, remaining) line 102: Connection reset by peer

však zůstává. K odesílání se používá pouze jedno TCP spojení? Po zpracování jednoho požadavku totiž ukončím spojení a toto chování by se tím mohlo vysvětlit.

Comment by kurkavo1 So 4. duben 2015, 13:42:41 CEST
Dobrý den, mohl bych prosím vědět jak poznám, zda jsem úlohu splnil nebo ne? Nemůžu zde najít žádný referenční čas.
Comment by kalivpe1 Ne 5. duben 2015, 17:49:25 CEST
V úterý zaměříme čas ukázkového serveru na školním počítači a pak stanovíme který čas splňuje zadání. Očekávám, že na splnění bude stačit čas okolo 10 sekund.
Comment by sojkam1 Ne 5. duben 2015, 17:58:33 CEST

Pokud někde nemám chybu, tester při testu pošle na server přes 350 MB dat.

To ale znamená, že test bude na 100Mb lince trvat minimálně cca 30 s, na 1Gb lince pak 3 s. Na localhostu se dostanu až pod 2 s, když notebook připojím na kabel ve studovně, test trvá 30 s (asi 100Mb linka), zatížení CPU je zanedbatelné.

Bude na cvičení možnost připojit se na 1Gb linku, aby člověk vůbec měl šanci překonat těch 20 s? (Kvůli závislostem na knihovnách mi nejspíš nepůjde umístit server na postel.felk.cvut.cz.)

Comment by hellemar Út 7. duben 2015, 14:27:46 CEST

Bude na cvičení možnost připojit se na 1Gb linku, aby člověk vůbec měl šanci překonat těch 20 s? (Kvůli závislostem na knihovnách mi nejspíš nepůjde umístit server na postel.felk.cvut.cz.)

V laboratoři KN:E-s109 jsou všechny počítače připojené 1 Gb linkou. V současné době už tam tester funguje, stejně jako na serveru postel.felk.cvut.cz.

Comment by sojkam1 Út 7. duben 2015, 15:24:35 CEST

V laboratoři KN:E-s109 jsou všechny počítače připojené 1 Gb linkou. V současné době už tam tester funguje, stejně jako na serveru postel.felk.cvut.cz.

Děkuji za odpověď. Jednodušší než zprovozňovat server na školním počítači by pro mě bylo připojit vlastní stroj. Je to možné?

A ještě bych se rád zeptal, jak se bude postupovat při vyhodnocování, když rychlost bude omezena rychlostí linky. Bude to loterie, nebo to bude nějak ošetřeno?

Comment by hellemar Út 7. duben 2015, 16:16:30 CEST

Děkuji za odpověď. Jednodušší než zprovozňovat server na školním počítači by pro mě bylo připojit vlastní stroj. Je to možné?

Ano, ale pro všechny nebude dost volných Ethernetových zásuvek, tak s tím počítejte.

A ještě bych se rád zeptal, jak se bude postupovat při vyhodnocování, když rychlost bude omezena rychlostí linky. Bude to loterie, nebo to bude nějak ošetřeno?

Máte kolik pokusů chcete. Pokud se vám bude zdát síť přetížená, přijďte například ráno nebo večer, kdy (snad) nebude takový provoz.

Comment by sojkam1 Út 7. duben 2015, 16:50:31 CEST

Dobrý den, po spuštění testu se objeví Error s kódem -13. Nevím, co se skrýváý pod tímto kódem za problém. Server se tváří, že požadavky zpracovává, tak jak má. Potřeboval bych nějakou menší nápovědu na co se zaměřit při hledání chyby.

Děkuji za pomoc.

Comment by dyrcifil Út 7. duben 2015, 18:03:03 CEST

Dobrý den, po spuštění testu se objeví Error s kódem -13. Nevím, co se skrýváý pod tímto kódem za problém. Server se tváří, že požadavky zpracovává, tak jak má. Potřeboval bych nějakou menší nápovědu na co se zaměřit při hledání chyby.

To znamená, že testovací program byl ukončen signálem 13. V manuálové stránce signal(7) se píše:

SIGPIPE      13       Term    Broken pipe: write to pipe with no readers.

Buďto je to tím, že jste ukončil spojení před tím, než testovací program odeslal všechna data, nebo to může být i problém komunikaci testovacího programu s vyhodnocovacím serverem. Kdyžtak přijďte na IRC ať to můžeme řešit interaktivně.

Comment by sojkam1 Út 7. duben 2015, 18:42:16 CEST

Pokud někde nemám chybu, tester při testu pošle na server přes 350 MB dat.

Chápu to tedy správně, že v podstatě nemá absolutně žádný smysl optimalizovat klienta pro rychlost/paralelní zpracování, když hrdlem testu je stejně přenosová rychlost? Pokud platí výše uvedené a na své 60 MB lince jsem naměřil 47.7s, strávil jsem při 100% využití sítě minimálně 46.6 vteřiny stahováním dat.

Celkově metodika vyhodnocení tohoto úkolu je poněkud nešťastná - vzhledem k omezení z hlediska rychlosti připojení, ale „volné ruce ve výběru platformy„ může dojít k situaci, kdy vyhrává jednoduše ten s nejsilnějším železem, nejrychlejší linkou, nebo ideálně obojím, a to už je v podstatě pay-to-win koncept.

Comment by kalivpe1 St 8. duben 2015, 01:42:59 CEST

Chápu to tedy správně, že v podstatě nemá absolutně žádný smysl optimalizovat klienta pro rychlost/paralelní zpracování, když hrdlem testu je stejně přenosová rychlost?

Ne. V případě ukázkového serveru v Pythonu je nejslabším místem využití procesorového výkonu.

Celkově metodika vyhodnocení tohoto úkolu je poněkud nešťastná - vzhledem k omezení z hlediska rychlosti připojení, ale „volné ruce ve výběru platformy„ může dojít k situaci, kdy vyhrává jednoduše ten s nejsilnějším železem, nejrychlejší linkou, nebo ideálně obojím, a to už je v podstatě pay-to-win koncept.

Jde o úhel pohledu. Všechny informace o úloze jste měli od začátku, zejména tu, že budete poměřovat výkon se školním počítačem. Udělat před řešením úlohy správnou analýzu problému je základ inženýrské práce. Uznávám, že zmínka o možnosti použití cloudu byl z naší strany trochu chyták, nicméně určitě se dá najít i cloud, který je se školou propojen 1Gb linkou. Kapacita připojení školní sítě do Internetu je na to dostatečná. Nevím teď přesně jak je to se školní konektivitou, ale minimálně přes IPv6 dosáhnete 1 Gb se na spoustu míst (serverů) na světě.

Comment by sojkam1 St 8. duben 2015, 06:57:00 CEST
Rozhodli jsme se, že deadline na odevzdání této úlohy posuneme o týden na 16. 4. 2015, 18:00 CEST. Nezapomeňte ale, že 16. 4. se na cvičení bude psát test („teorie„ + Git).
Comment by sojkam1 St 8. duben 2015, 10:20:31 CEST

Musím uznat, že připojení je na této úloze asi ten hlavní problém. Sám jsem to nasadil do MS Azure, do západní evropy, což bylo nejbližší datacentrum a nejsem schopný se dostat pod 10s. Výpočetního výkonu má stroj dostatek. Zajímalo by mne zda jsou některé úspěšné výsledky mimo „lokální„ síť ČVUT, případně Cesnetu.

Comment by pychaja1 St 8. duben 2015, 11:06:55 CEST

Dobrý den,

testovací skript mi vrací „Error: fgets(response, sizeof(response), f) line 243„. Hlavičku i body v případě GETu si myslím, že vracím správně a socket taky zavírám až když vše pošlu. Bylo by možné mi pomoci s debuggingem?

Předem díky.

Comment by flektoma St 8. duben 2015, 14:58:01 CEST
S příkazem curl vám to funguje? Pokud ano, ozvěte se přes IRC, nick wentasah.
Comment by sojkam1 St 8. duben 2015, 15:30:00 CEST

Vyresil jste nekdo problem s timto? Server mam napsany v JAVA a vubec netusim, cim to muze byt…

len = write(sfd, data, remaining) line 102: Connection reset by peer

Comment by hejdujir Čt 9. duben 2015, 17:48:36 CEST

Nevim co se stalo s testerom, ale dnes nefunguje co fungovalo v sobotu a nedeli. Chyba testeru:

osp-server-tester.cc:207: fgets(POST_response): Unexpected end of stream
osp-server-tester.cc:200: write(sfd, data, remaining): Bad address
Comment by toporal1 Po 13. duben 2015, 15:21:37 CEST
Omlouvám se, ale při pokusu opravit potenciální chybu, která se možná projevovala u vašeho kolegy, jsem do testeru zanesl jinou chybu. Už by to mělo být opraveno. Děkuji panu Dendisovi za pomoc s hledáním příčiny této nové chyby.
Comment by sojkam1 Po 13. duben 2015, 17:10:05 CEST
Dobry den. Je mozne pouzivat testovaci server po deadline bez anulovani vysledku mimo soutez? (Funkcni reseni jiz odevzdano drive. Mam jeste napad jak reseni vylepsit.) Diky. Joel Matejka.
Comment by matejjoe Čt 16. duben 2015, 18:29:46 CEST
Ano, možné to je. Teď už se ale výsledky nepromítají do celkového pořadí. Taky je možné, že se časem testovací program trochu změní, protože ho chci upravit pro příští ročník.
Comment by sojkam1 Čt 16. duben 2015, 23:37:14 CEST