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“.