1 [[!meta title="Obsluha mnoha klientů"]]
8 Hlavním cílem této úlohy je implementovat jednoduchou serverovou
9 aplikaci a optimalizovat její výkon tak, aby zvládala obsluhu velkého
10 množství klientů a požadavků. **Pro implementaci serveru si můžete
11 zvolit jakoukoli platformu** (HW, OS, programovací jazyk, framework,
14 Vedlejší cíle jsou naučit se pracovat s dokumentací a zdrojovými kódy
15 použitých platforem (zejména těch založených na open source softwaru),
16 aplikace znalostí nabytých na přednáškách a získání přehledu o
17 výkonnosti jednotlivých platforem.
22 Vytvořte serverovou aplikaci komunikující protokolem [HTTP][], která
23 bude sloužit k počítání unikátních slov v datech zaslaných klienty. Na
24 server jsou kladeny následující požadavky:
26 - Klienti posílají data pomocí [metody POST][POST] s cestou
27 `/osp/myserver/data`. Data jsou ve formátu čistého textu
28 (text/plain) v kódování UTF-8 komprimovaného metodou [gzip][gzip].
29 - Server obsahuje "čítač jedinečných slov". Při spuštění serveru je
31 - Server si vede evidenci o slovech zaslaných v jednotlivých
32 požadavcích a pro každé nové slovo, které ještě nemá v evidenci
33 zvýší čítač jedinečných slov o jedna.
34 - Na požadavek [GET][] s cestou `/osp/myserver/count` server odpoví
35 aktuální hodnotou čítače jedinečných slov a tento čítač vynuluje.
36 Hodnota se přenáší jako dekadické číslo v UTF-8 kódování.
37 - Server musí zvládnou obsluhovat velké množství (cca 100) současně
40 [HTTP]: http://tools.ietf.org/html/rfc2616
41 [POST]: http://tools.ietf.org/html/rfc2616#section-9.5
42 [GET]: http://tools.ietf.org/html/rfc2616#section-9.3
43 [gzip]: https://tools.ietf.org/html/rfc1952
48 Předpokládejme, že náš server běží na lokálním počítači (t.j.
49 localhost) na portu 8080. Použijeme program `curl` k posílání
52 curl localhost:8080/osp/myserver/data --data-binary @<(echo první pokus|gzip)
53 curl localhost:8080/osp/myserver/data --data-binary @<(echo druhý pokus|gzip)
54 curl localhost:8080/osp/myserver/count --output -
56 Výstupem posledního příkazu bude řetězec "3". Místo posledního příkazu
57 můžete použít i webový prohlížeč nasměrovaný na adresu
58 <http://localhost:8000/osp/myserver/count>.
60 *Poznámka:* Syntaxe `<(příkaz...)` je tzv. *process substitution* v
61 interpreteru `bash`. Jedná se o jeden z možných způsobů předání
62 binárních dat na příkazové řádce.
67 Výkon serveru bude měřen testovacím programem, který bude serveru
68 posílat větší množství dat a poté se zeptá na aktuální hodnotu čítače
69 jedinečných slov. Bude se měřit celkový čas od odeslání prvního
70 požadavku typu POST do příjmu hodnoty čítače jedinečných slov.
72 Akceptována budou řešení jejichž **celkový čas bude dvakrát menší**
73 než čas naměřený s níže uvedeným ukázkovým serverem bežícím na školním
74 počítači v laboratoři.
79 Zde uvádíme jednoduchý server napsaný v jazyce Python, který splňuje
80 výše uvedené požadavky (kromě výkonnosti). Můžete ho použít jako
81 referenci či startovací bod pro vaší implementaci.
86 from http.server import HTTPServer, BaseHTTPRequestHandler
91 class OSPHTTPHandler(BaseHTTPRequestHandler):
94 if self.path == "/osp/myserver/data":
95 length = int(self.headers.get('Content-Length'))
96 text = gzip.decompress(self.rfile.read(length)).decode("utf-8")
97 for word in text.split():
99 self.send_response(204) # No Content
102 self.send_response(404)
107 if self.path == "/osp/myserver/count":
108 self.send_response(200)
109 self.send_header("Content-type", "text/plain")
111 self.wfile.write(str(len(words)).encode())
114 self.send_response(404)
117 class HTTPServerIPv6(HTTPServer):
119 address_family = socket.AF_INET6
121 # httpd = HTTPServer(('', 8080), OSPHTTPHandler) # Use if your system uses IPv4 by default
122 httpd = HTTPServerIPv6(('', 8080), OSPHTTPHandler) # Use if your system uses IPv6 by default
123 print("Listening on port", httpd.server_port)
124 httpd.serve_forever()
127 Pokud se k tomuto ukázkovému serveru připojí mnoho klientů, bude
128 "přetížen" a čas od času bude klienty odmítat. Takže prvním krokem
129 vašeho řešení může být zjištění příčiny tohoto chování a její
132 Testování a měření výkonu
133 =========================
135 Pro testování použijte
136 [odevzdávací systém](https://rtime.felk.cvut.cz/osp/cviceni/server/tester/),
137 kam zadáte informace o vašem serveru a můžete ho nechat otestovat. Pět
138 nejlepších studentů dostane 1 až 5 bonusových bodů.
140 **Odevzdávací systém běží momentálně v testovacím provozu.** Je možné,
141 že naměřené hodnoty budou horší, než jaké lze z vašeho serveru