ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2009/anyevent.pod
Revision: 1.2
Committed: Thu Jan 15 04:13:05 2009 UTC (17 years, 9 months ago) by root
Branch: MAIN
Changes since 1.1: +315 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =encoding utf-8
2    
3     =head1 AnyEvent - Eine Welt ohne Religion
4    
5     In diesem Vortrag möchte ich die neuesten Entwicklungen in Sachen
6     AnyEvent vorstellen (asynchrones IPv4/IPv6, asynchrones DNS, TLS uvm.), sowie
7     einige Hintergrundinformationen zu bestehenden Event-Modulen auf CPAN,
8     sowie Benchmarks, vorstellen.
9    
10     Doch zuerst: der Titel klingt sicherlich etwas seltsam - was bedeutet er?
11    
12     Nun, AnyEvent ist, wie im Namensteil "Event" steht, ein Event-Model
13     bzw. eine Event-Bibliothek. Event-Module oder -Bibliotheken stellen
14     im allgemeinen Funktionalität bereit, mit derer man auf Ereignisse
15     (Events), warten kann, speziell Ereignisse der Art "Zeitpunkt soundso
16     ist erreicht" und "File Descriptor soundso kann jetzt nichtblockierend
17     gelesen/geschrieben werden."
18    
19     Derartige Event-Bibliotheken gibt es zuhauf (Tk, Glib, Event, EV uvm.),
20     doch trotz der offensichtlichen Vorteile Event-basierter Programmierung
21     (z.B. beinahe automatische Parallelisierbarkeit) werden sie kaum in
22     CPAN-Modulen eingesetzt.
23    
24     Meiner Meinung nach liegt der Grund schlicht darin, daß alle diese
25     Event-Bibliotheken exklusiv sind: sie dulden niemanden neben sich. Wie
26     bei den meisten Religionen auch, muss man sich einem dieser Modelle
27     ausliefern. Konkret bedeutet dies für Modul-Autoren: benutzt man
28     z.B. Glib in seinem Modul, muss auch jeder Benutzer dieses Modules Glib
29     benutzen, was natürlich eine starke Einschränkung darstellt, vor allem,
30     wenn das Modul selbst eigentlich nur "irgendwelche" Events benötigt, die
31     im Prinzip jede beliebige Event-Bibliothek liefert.
32    
33     Einige Module auf CPAN haben versucht, aus dieser Not eine Tugend zu
34     machen: POE z.B. kann andere Event-Module als Implementation benutzen (in
35     der Praxis funktioniert das zwar nur mit einigen wenigen, aber die Idee
36     zählt). Lieder verschlimmert dies das Problem nur: POE z.B. verlangt
37     beinahe religiöse Glaubensbekenntnisse und ist kein bisschen kompatibler,
38     im Gegenteil: obwohl POE Backends für Gtk+ und Event besitzt, kann man
39     POE-Module nicht in einem Gtk+ oder Event-basiertem Programm benutzen:
40     setzt man POE in seinem Modul ein, so muss auch jeder Benutzer des Moduls
41     POE benutzen, sowie auch das Hauptprogramm selbst.
42    
43     AnyEvent dagegen ist I<grundsätzlich> anders: Im Stile von anderen
44     C<Any*>-Modulen ist es lediglich eine Schnittstelle zu diesen. Dabei passt
45     es sich an jedes unterstützte Event-Modell an, ohne daß sich die API
46     ändert. Das bedeutet, daß man getrost Module benutzen kann, die AnyEvent
47     benötigen und intern auch benutzen, aber der Benutzer des Moduls sieht
48     davon erstmal nichts und kann jede beliebige Event-Bibliothek benutzen.
49    
50     AnyEvent ist 100% Pure-Perl, und kommt mit eigener, schneller,
51     Event-Bibliothek, so daß auch auf Systemen, wo kein anderes Event-Modell
52     verfügbar ist eventbasiert Programmiert werden kann.
53    
54     =head2 AnyEvent am Beispiel AnyEvent::CouchDB
55    
56     Ein gutes Beispiel dafür ist C<AnyEvent::CouchDB>. Außer im Namen,
57     kommt AnyEvent in der API dieses Moduls nicht vor. Eine einfache
58     Datenbankabfrage sieht dementsprechend auch ganz langweilig aus:
59    
60     my $data = $db->view('users/all', { key => 'b' })->recv
61    
62     Obwohl die Abfrage selbst Ereignisgesteuert ist, muss man als Benutzer
63     des Moduls kaum darunter leiden, lediglich die Zweiteilung der Aufgabe in
64     "Start-Phase" (C<view>-Methode) und "Resultat-Phase" (C<recv>-Methode) ist
65     typisch. Daß intern AnyEvent werkelt, fällt nicht auf, außer, daß die
66     Abfrage in einem laufenden Tk/Gtk usf.-Programm dieses nicht anhält.
67    
68     Die Vorteile erscheinen, wenn man mehrere Abfragen "gleichzeitig"
69     (genauer: miteinander verflochten) ausführt:
70    
71     my @data = map $_->recv,
72     map $db->view ('users/al', { key => $_ }),
73     qw(key1 key2 key3 key4);
74    
75     Auch hierbei muss man nicht darauf achten, welches Event-Modul benutzt
76     wird (oder ob man überhaupt ein spezielles benutzt) - es funktioniert
77     einfach.
78    
79     Richtig Spaß macht es, wenn man realisiert, daß man praktisch alle
80     AnyEvent-benutzenden Module beliebig kombinieren kann, und Aufgaben
81     quasi "im Hintergrund" erledigen kann, z.B. mit C<AnyEvent::CouchDB> und
82     C<AnyEvent::HTTP>:
83    
84     $db->view('users/all', { key => 'b' })->cb (sub {
85     my $data = shift->revc;
86     # daten erhalten
87     });
88    
89     AnyEvent::HTTP::http_get "http://www.porttracker.co.uk", sub {
90     my $html = $_[1];
91     # daten erhalten
92     };
93    
94     # hier kann man weitere Dinge erledigen
95    
96     Und all das kann man in den eigenen Modulen nutzen, ohne sich irgendwie
97     auf ein bestimmtes Event-Modell festzulegen.
98    
99    
100     =head2 AnyEvent - Grundlegendes
101    
102     AnyEvent selbst wurde letztes Jahr an dieser Stelle ausführlich
103     vorgestellt, daher möchte ich hier nur eine kurze Übersicht
104     bzw. Einführung in AnyEvent als rein Event-Bibliothek geben:
105    
106     Wie viele anderen Bibliotheken auch, benutzt AnyEvent das Konzept eines
107     "Watchers", einem Objekt, daß wie ein Wachhund auf ein bestimmtes
108     Ereignis reagiert (watch/watcher = Wache/Beobachter) und bei eintreten
109     eine Aktion auslöst, z.B. aufrufen eines Callbacks.
110    
111     Diese Watcher gibt es für die folgenden Ereignistypen:
112    
113     =over 4
114    
115     =item Zeit - timer
116    
117     my $timer = AnyEvent->timer (after => 7, cb => sub {
118     warn "Sieben Sekundne sind abgelaufen!";
119     });
120    
121     Timer können nach einer gewissen Zeit ablaufen, oder wiederholt (z.B.
122     alle 3s) Ereignisse auslösen und Callbacks aufrufen.
123    
124     =item I/O auf File Handles - io
125    
126     my $watcher = AnyEvent->io (fh => *STDIN, poll => 'r', cb => sub {
127     my $line = <STDIN>;
128     # zeile von stdin gelesen
129     });
130    
131     I/O-Watcher beobachten einen File Handle und können einen Callback
132     aufrufen, wenn gelesen oder geschrieben werden kann.
133    
134     =item Signale - signal
135    
136     my $quit = AnyEvent->condvar;
137    
138     my $term = AnyEvent->signal (signal => "TERM", cb => sub {
139     $quit->send;
140     });
141    
142     ...
143    
144     $quit->recv
145    
146     Mit Signal-Watchers kann man synchron auf das Auftreten von Signalen
147     warten.
148    
149     Das obige Beispiel benutzt eine "condition variable" um mit dem
150     Hauptprogramm zu kommunizieren (mehr info s.u.).
151    
152     =item Kindprozesse sterben sehen - child
153    
154     my $w = AnyEvent->child (pid => $pid, cb => sub {
155     warn "pid $pid hat sich beendet\n";
156     });
157    
158     Eher selten benötigt, aber sehr schwer zu implementieren (wenn man es
159     richtig tun möchte :) sind Child-Watcher: mit diesen kann man auf das
160     Beenden von ge-fork-ten Prozessen warten.
161    
162     =back
163    
164     =head3 Wenn man mal nichts tun möchte
165    
166     Event-basierte APIs haben eines gemein: Im allgemeinen werden Vorgänge
167     nur gestartet und laufen dann quasi-parallel im Hintergrund ab.
168    
169     Aber wenn man nun genügend solche Vorgänge gestartet hat, möchte man ja
170     irgendwann auch mal auf die Ergebnisse warten.
171    
172     Dies erledigt entweder das Hauptprogramm, indem es die entsprechenden
173     Funktionen der Event-Bibliothek aufruft (z.B. C<Event::loop> oder C<main
174     Gtk>), oder man benutzt sogenannte "condition variables", mit denen man
175     auf das eintreten eines bestimmten Zustands warten kann.
176    
177     "Condition Variables" sind so etwas wie "Rendezvouspunkte" zwischen dem
178     Erzeuger von Daten oder einem Ereignis (z.B. C<AnyEvent::CouchDB->view>
179     oder C<AnyEvent::HTTP::http_get>, aber auch genauso C<< AnyEvent->timer
180     >>) und dem Konsumenten (der Benutzer dieser Funktionen, der die Daten
181     haben oder einfach auf das Ereignis warten möchte).
182    
183     =head1 Neues!
184    
185     Auf zu neuen Ufern - im letzten Jahr hat sich viel getan, sowohl in
186     AnyEvent selbst, als auch in Sachen "andere Module die AnyEvent benutzen".
187    
188     =head2 Altes!
189    
190     Die wichtigsten Eigenschaften von AnyEvent sind allerdings beim
191     alten geblieben:
192    
193     =over 4
194    
195     =item * Die API hat sich kaum verändert, bzw. ist 100%
196     rückwärtskompatibel.
197    
198     =item * AnyEvent ist nach wie vor "Pure-Perl".
199    
200     =item * Der Event-Teil ist nach wie vor getrennt von den anderen Teilen,
201     daß Event-Modul ist klein und wenn man bezahlt nur für daß, was man
202     benutzt.
203    
204     =back
205    
206     Aber nun zu den Neuigkeiten:
207    
208    
209     =head2 AnyEvent::Strict
210    
211     Aus Geschwindigkeitsgründen macht AnyEvent selbst keine
212     Parameterprüfung, ganz einfach deshalb, weil die Prüfung meistens mehr
213     Zeit in Anspruch nimmt als der Rest der Funktion.
214    
215     Für einen erfahrenen AnyEvent-Benutzer ist das in der Praxis kein
216     Problem, aber wenn man die API noch nicht genau kennt, können sich so
217     Fehler einschleichen (z.B. alte Event-Hasen benutzen gerne C<fd> statt
218     C<fh> um einen I/O-Watcher zu erzeugen).
219    
220     Daher bietet AnyEvent optional eine strenge Prüfung aller
221     Parameter an. Die kann man ganz einfach aktivieren, in dem man die
222     Environment-Variable C<PERL_ANYEVENT_STRICT> auf C<1> setzt, was auf allen
223     meinen Entwicklungsrechnern der Fall ist.
224    
225     Falls man diese Prüfung grundsätzlich wünscht (was ich ganz dringend
226     I<nicht> empfehle, siehe aber den Punkt "keine Religion"...), kann man diese
227     auch immer aktivieren:
228    
229     use AnyEvent;
230     use AnyEvent::Strict;
231    
232     # jetzt wird brutal geprüft.
233    
234     Ich gebe zu, daß war sicher noch nicht der Brüller, aber sehen wir
235     weiter:
236    
237     =head2 Anyevent::Util
238    
239     Dies ist meine Grabbelkiste für nützliche aber eklige Funktionen:
240    
241     =over 4
242    
243     =item fork_call BLOCK $callback
244    
245     Führt den angegebenen BLOCK in einem separaten Prozess aus und ruft
246     danach den $callback mit den Resultatwerten auf. Ist ideal, um lange
247     Berechnungen in einen separaten Prozess zu verlagern:
248    
249     fork_call {
250     find_primes_till 1e9
251     } sub {
252     warn "alle primzahen bis 10**9: ", join " ", @_;
253     };
254    
255     Die Funktion leaked allerdings unter Windows, aber ich habe bisher noch
256     keinen weg gefunden, unter einem native-win32-Perl zu forken und das Kind
257     sauber zu beenden (ich glaube, es gibt keinen)...
258    
259     =item my $guard = guard BLOCK
260    
261     Führt den angegebenen BLOCK aus, wenn C<$guard> zerstört wird. Ist
262     bei ereignisgesteuerter Programmierung total hilfreich, um Sachen
263     aufzuräumen.
264    
265     Wenn es vorhanden ist, benutzt AnyEvent das C<Guard>-Modul (ja, das ist
266     Schleichwerbung).
267    
268     =item fh_nonblocking $fh, $nonblocking
269    
270     Einen File Handle non-blocking zu machen, ist nicht ganz einfach (Windows,
271     Windows, kaputt, kaputt...). C<AnyEvent::Util> erledigt dies mit
272     furchtbaren Hacks unter Windows und elegant überall sonst.
273    
274     =back
275    
276     Immer noch nicht überzeugt? Ok, dann machen wir mal mit
277     Netzwerkprogrammierung weiter:
278    
279    
280     =head2 AnyEvent::Socket
281    
282     Sockets in Perl haben ein paar gravierende Nachteile: non-blocking
283     connects sind extrem umständlich, IPv6 und IPv4 brauchen völlig
284     inkompatible APIs, DNS blockiert den gesamtem Prozess und liefert darüber
285     hinaus auch nur altmodische IP-Adressen.
286    
287     Anders mit AnyEvent::Socket:
288    
289     tcp_connect "www.google.com", "80", sub {
290     my ($fh) = @_
291     or die "www.google.com: $!";
292    
293     ...
294     };
295    
296     Dieser Aufruf löst zuerst C<www.google.com> auf - im Hintergrund, ohne
297     das Programm anzuhalten - und baut dann, ebenfalls im Hintergrund, eine
298     TCP-Verbindung dorthin auf.
299    
300     Es versteht sich von selbst, daß Multi-Homed Hosts genauso unterstützt
301     werden wie IPv6, und das ohne zusätzliche XS-Module.
302    
303     C<tcp_connect> kann aber noch mehr. Z.b. auf Jabber-server connecten, was
304     mit Perl alleine fast unmöglich ist, da man mit Perl keine SRV-Records
305     auflösen kann:
306    
307     tcp_connect "jabber.org", "xmpp-server=5269", sub {
308     # Die pseudo-XML-Kacke parsed ihr bitte selbst...
309     }, 60; # <- timeout
310    
311     Der Name C<tcp_connect> ist leider etwas naiv, tatsächlich werden auch
312     andere Protokolle unterstützt, z.B. local unix sockets:
313    
314     tcp_connect "unix/", "/tmp/.X11-unix/X0", sub { ...
315    
316     Listening-Sockets funktionieren prinzipiell genauso einfach, z.B. hier
317     für einen TCPv6-Port:
318    
319     tcp_server "::", 80, sub {
320     my ($fh, $host, $port) = @_;
321    
322     # jede neue Verbindung führt zu einem Aufruf dieses Callbacks
323     };
324    
325     Oder einen beliebigen TCPv4-Port:
326    
327     tcp_server "0", undef, sub {
328     my ($fh, $host, $port) = @_;
329     ...
330     }, sub {
331     my ($thishost, $thisport) = @_;
332    
333     warn "bound to port $thisport\n";
334     };
335    
336     Leider muss man sich selbst darum kümmern, ob IPv6-Sockets auch auf IPv4
337     hören - üblicherweise ja, aber die BSDs haben natürlich mal wieder
338     verbockt und halten sich nicht ans RFC.
339    
340     Komplizierteres ist immer möglich - anderes als z.B. C<IO::Socket> hat
341     man volle Kontrolle über die eigentliche Socket und braucht nicht für
342     jeden etwas spezielleren Wunsch extra Support.
343    
344     Und anders als bei anderen Lösungen funktionieren diese Funktionen auch
345     unter Windows korrekt (modulo Tk, daß wie üblich zu kaputt ist, um
346     non-blocking connects stabil zu kriegen, aber AnyEvent arbeitet auch um
347     diese Bugs herum).
348    
349     Neben diesen beiden Funktionen gibt es in AnyEvent::Socket eine Unmenge an
350     Utility-Funktionen zum parsen/anzeigen von IP-Adressen, Socket-Adressen
351     und DNS:
352    
353     $ipn = parse_ipv4 $dotted_quad
354     $ipn = parse_ipv6 $textual_ipv6_address
355     $ipn = parse_address $text
356     $text = AnyEvent::Socket::aton $ipn
357     ($host, $service) = parse_hostport $string[, $default_service]
358     $sa_family = address_family $ipn
359     $text = format_address $ipn
360     $text = AnyEvent::Socket::ntoa $ipn
361     inet_aton $name_or_address, $cb->(@addresses)
362     $sa = AnyEvent::Socket::pack_sockaddr $service, $host
363     ($service, $host) = AnyEvent::Socket::unpack_sockaddr $sa
364     resolve_sockaddr $node, $service, $proto, $family, $type, $cb->([$family, $type, $proto, $sockaddr], ...)
365    
366     Hier verweise ich auf die Dokumentation. Einzig C<parse_hostport>
367     möchte ich genauer erklären: Selbst die Aufgabe, einen Hostnamen und
368     einen Port anzugeben, ist nicht ganz einfach wenn man es richtig machen
369     will. C<parse_hostport> nimmt ein oder zwei Strings und zerlegt diesen in
370     Host und Port, z.B. diese:
371    
372     www.linux.org
373     www.x.de:443
374     www.x.de:https=443
375     127.1:22
376     ::1
377     affe::1
378     [10.0.1]:80
379     [www.x.org] 17
380     10.0.0.1 smtp
381    
382     Richtig, IPv6 macht das ganze deutlich komplexer. Und IPv6 ist die
383     Zukunft, ob man das nun gut findet oder nicht :/
384    
385     Ach ja, Stichwort IPv6 - es kann auch furchtbar nervig sein, wenn
386     Programme grundsätzlich die IPv6-Adresse bevorzugen, die gerade nicht
387     erreichbar ist. Der Standard bei AnyEvent ist zur Zeit IPv4 den
388     Vorzug zu geben, was sich allerdings über die Environment-Variable
389     C<PERL_ANYEVENT_PROTOCOLS> beeinflussen lässt.
390    
391    
392     =head2 AnyEvent::DNS
393    
394     Nur am Rande möchte ich AnyEvent::DNS erwähnen. Ursprünglich war es nur
395     dazu gedacht, die Adressen für C<AnyEvent::Socket> zu resolven. Das Modul
396     ist aber ein kompletter Stub-Resolver, der beliebige DNS-Record-Typen,
397     EDNS0, IPv6 und virtual circuit mode supported.
398    
399     Das Modul ist in der Praxis ca. halb so schnell wie z.b. EV::ADNS (braucht
400     natürlich viel mehr Speicher, blockiert aber im Gegensatz zu EV::ADNS
401     nie).
402    
403     Es gibt Hilfsunktionen (hier nur eine Auswahl):
404    
405     AnyEvent::DNS::a $domain, $cb->(@addrs)
406     AnyEvent::DNS::mx $domain, $cb->(@hostnames)
407     AnyEvent::DNS::srv $service, $proto, $domain, $cb->(@srv_rr)
408     AnyEvent::DNS::ptr $domain, $cb->(@hostnames)
409     AnyEvent::DNS::reverse_lookup $ipv4_or_6, $cb->(@hostnames)
410     AnyEvent::DNS::reverse_verify $ipv4_or_6, $cb->(@hostnames)
411    
412     Und eine Resolver-Klasse:
413    
414     use Data::Dumper;
415     use AnyEvent::DNS;
416     AnyEvent::DNS::resolver->resolve (
417     "google.com", "*", my $cv = AnyEvent->condvar);
418     warn Dumper [$cv->recv];
419    
420     # gekürztes Ergebnis:
421     # [
422     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
423     # 2008052701, 7200, 1800, 1209600, 300 ],
424     # [
425     # 'google.com', 'txt', 'in',
426     # 'v=spf1 include:_netblocks.google.com ~all'
427     # ],
428     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
429     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
430     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
431     # ]
432    
433    
434     =head2 AnyEvent::Handle
435    
436     Nun zum ehrgeizigsten Teil der Neuerungen: C<AnyEvent::Handle>.
437    
438     Die Probleme, die dieses Modul lösen möchte, kommen in der Praxis
439     häufig vor: Formatted-I/O, Pipelining und TLS-Verschlüsselung.
440    
441     Früher habe ich immer ad-hoc Lösungen für diese Probleme implementiert,
442     da mir schlicht die Erfahrung gefehlt hat, wie man alle diese Features in
443     ein allgemeines Perl-Modul "gießt".
444    
445     C<AnyEvent::Handle> versucht diese Lösung zu
446     sein: AnyEvent::Handle-Objekte sind Wrapper um existierende File
447     Handles. Im folgenden beschreibe ich die Lösung, die AnyEvent::Handle
448     für die oben beschriebenen Probleme bietet:
449    
450     =over 4
451    
452     =item Formatted I/O
453    
454     Um auf ein AnyEvent::Handle-Objekt zu schreiben, benutzt man
455     C<push_write>. Das C<push> deutet darauf hin, daß es einen Puffer für
456     die Daten gibt, und C<push_write> hängt die Daten einfach an diesen an:
457    
458     $hdl->push_write ("GET / HTTP/1.0\015\012\015\012");
459    
460     Mit mehr als einem Argument fordert man zusätzliche Formatierungen an,
461     die meisten dieser Formatierungen gibt es sowohl für die Schreib- als
462     auch die Leseseite:
463    
464     $hdl->push_write (netstring => "xyz"); # djb netsrings
465     $hdl->push_write (packstring => "w", "data"); # benutzt pack()
466     $hdl->push_write (json => [1, 2, 3, 4]); # benutzt JSON
467     $hdl->push_write (storable => $ref); # benutzt Storable
468    
469     Schreiben ist einfach, Lesen ist schwieriger. Anders als beim Schreiben
470     enthält der Puffer keine Daten, sondern die Callbacks, die der Reihe nach
471     aufgerufen werden, wenn Daten eintreffen.
472    
473     Die Flexibilität entsteht dadurch, daß man Callbacks ans Ende des Puffers anhängen kann:
474    
475     $hdl->push_read (json => sub { my $data = $_[1] });
476    
477     Aber auch vor dem Anfang einschieben kann:
478    
479     $hdl->unshift_read (json => sub { my $data = $_[1] });
480    
481     Interessant ist dies vor allem, weil man hierdurch recht einfach auch
482     komplexe Protokolle mit Pipelining implementieren kann.
483    
484     Man kann jederzeit eigene Typen global für alle Handles hinzufügen, die
485     existierenden Typen sind neben denselben wie für die Schreibrichtung:
486    
487     $hdl->push_read (line => $eol, $cb); # zeilen
488     $hdl->push_Read (regex => $accept[, $reject[, $skip]); # uiuiuiui
489    
490     =item Pipelining
491    
492     Pipelining bedeutet, daß man auf einer bestehenden Verbindung mehrere
493     Anfragen gleichzeitig losschickt. Die Herausforderung liegt darin, daß
494     man beim Empfang der Antworten flexibel auf Ausnahmen reagieren können
495     muss.
496    
497     Bei HTTP beispielsweise weiß man erst nach Parsen des Headers, wie lang
498     der Body wird.
499    
500     AnyEvent::Handle erledigt dies mit einer Kombination aus C<push_read> und
501     C<unshift_read>:
502    
503     # sende requests
504     for (@urls) {
505     $hdl->push_write ("GET $_ HTTP/1.0\015\012\015\012");
506     }
507    
508     # parse antworten
509     for (@urls) {
510     # lese header
511     $hdl->push_read (line => "\015\012\015\012", sub {
512     my ($hdl, $header) = @_;
513    
514     my $content_length = extract "Content-Length", $header;
515    
516     $hdl->unshift_read (chunk => $content_length, sub {
517     my ($hdl, $body) = @_;
518    
519     # fertig
520     });
521     });
522     }
523    
524     Der springende Punkt ist, daß C<unshift_read> erst I<nach> dem Empfang
525     des Headers ausgeführt wird. Dadurch kann man z.B. verschiedene Arten von
526     Antworten parsen, oder auf unerwartete Fehler reagieren, obwohl vielleicht
527     schon Antworten auf die nächsten Requests empfangen wurden.
528    
529     =item TLS/SSL
530    
531     TLS ist der Horror. Nicht nur, aber vor allem auch wegen der grauenvollen
532     OpenSSL-API (GnuTLS ist geringfügig besser, doch sucht man vergebens nach
533     einem guten Perl-Modul dafür). Der Beweis dafür ist, daß es praktisch
534     kein Modul gibt, daß non-blocking TLS connects korrekt und wirklich
535     non-blocking durchführt.
536    
537     Es hilft auch nicht gerade, daß Net::SSLeay nur einen Bruchteil der
538     OpenSSL-API umsetzt.
539    
540     AnyEvent::Handle (to boldly go...) versucht einen ganz neuen Ansatz für
541     diese Problematik, bei der OpenSSL vom eigentlichen File Handle komplett
542     getrennt wird, d.h. gar keinen Zugriff auf diesen hat. Dadurch wird
543     garantiert, daß OpenSSL auf gar keinen Fall blockieren kann.
544    
545 root 1.2 Ganz wie der Rest von AnyEvent ist einfach einfach: wenn man zu einem
546     TLS-Server connecten möchte, setzt man C<tls> auf C<"connect">, als
547     TLS-Server dagegen setzt man es auf C<"accept">.
548    
549     Hat man kompliziertere Ansprüche, wie Zertifikate oder
550     Verification-Callbacks, so kann man sein eigenes Net::SSLeay::CTX-Objekt
551     oder das Net::SSLeay-Objekt für die Verbindung selbst übergeben.
552    
553     Selbstverständlich kann man den TLS-Handshake zu einem beliebigen
554     Zeitpunkt beginnen, nicht nur am Anfang der Verbindung.
555    
556 root 1.1 =back
557    
558 root 1.2 Mit AnyEvent::Handle wird manches erstaunlich einfach. Hier ist z.B. ein
559     (ganz primitiver) HTTPS-Client (übrigens das komplette Programm):
560 root 1.1
561     use AnyEvent;
562     use AnyEvent::Socket;
563     use AnyEvent::Handle;
564    
565     my $cv = AnyEvent->condvar;
566    
567     tcp_connect "www.google.com", "443", sub {
568     my ($fh) = @_ or die;
569    
570     my $hdl; $hdl = new AnyEvent::Handle
571     fh => $fh,
572     timeout => 60,
573     tls => "connect",
574     on_eof => sub {
575     undef $hdl; # gibt handle frei
576     $cv->send; # isch hab' ferdisch
577     },
578     on_read => sub {
579     my ($hdl) = @_;
580     print $hdl->{rbuf};
581     $hdl->{rbuf} = "";
582     };
583    
584     $hdl->push_write ("GET / HTTP/1.0\015\012\015\012");
585     };
586    
587     $cv->recv;
588    
589 root 1.2 Darüber hinaus gibt es eine Menge Parameter, mit dem man Verhalten,
590     Fehlerbehandlung, Ressourcenbenutzung auf seine Anforderungen abstimmen
591     kann. Für ganz spezielle Anwendungen kann man von AnyEvent::Handle auch
592     eigene Klassen ableiten, aber in den meisten Fällen ist dies unnötig.
593    
594     Ein Nachteil von AnyEvent::Handle ist allerdings, daß die Abstraktion
595     selbst nicht kostenlos ist: Methodenaufrufe in Perl sind vergleichsweise
596     langsam, und AnyEvent::Handle benutzt sehr viele davon. In den meisten
597     Fällen merkt man davon allerdings nichts, da der Overhead durch
598     AnyEvent::Handle immer noch sehr gering ist, wenn man mit den Daten auch
599     noch etwas tun möchte.
600    
601 root 1.1 =back
602    
603    
604     =head2 Benchmarks
605    
606 root 1.2 Ich bin es gewohnt, meine eigene Lösungen zu schreiben, notfalls immer
607     und immer wieder. Bevor ich eine (hilfreiche) Abstraktion ruhigen
608     Gewissens benutzen kann, muss ich immer erst wissen, wie viel sie kostet,
609     damit ich eine vernünftige Abwägung machen kann.
610    
611     Deshalb habe ich drei Benchmarks durchgeführt, um herauszufinden, wie
612     hoch der Overhead von AnyEvent gegenüber der direkten Benutzung von
613     Event-Bibliotheken ist, und wie verschiedene Event-Bibliotheken bei
614     typischen Server-Situationen skalieren, sowohl für Server mit sehr vielen
615     Verbindungen, als auch für Server mit sehr wenigen.
616    
617     =head3 Benchmark 1: Overhead
618    
619     Um den Overhead von AnyEvent selbst zu testen, erzeugt dieser Benchmark
620     sehr viele Timer (mit einem Time-out von 0 Sekunden) und ebensoviele
621     I/O watcher auf STDOUT (üblicherweise eine tty), der auf den
622     "schreibbar"-Zustand wartet.
623    
624     Dann lässt er alle Watcher genau einmal ihren Callback aufrufen und
625     zerstört die Watcher dann.
626    
627     Gemessen wird die Zeit, die es jeweils braucht, einen Watcher zu erzeugen,
628     den Callback auszuführen und den Watcher wieder zu zerstören.
629    
630     Die Kernel-Schnittstelle sollte einen relativ geringen Einfluss besitzen,
631     sofern die Event-Bibliothek einigermaßen effizient implementiert wurde,
632     da nur ein einziges mal ein einziger File-Descriptor abgefragt werden
633     muss.
634    
635     (Der Benchmark liegt AnyEvent als F<eg/bench> bei).
636    
637     Die Spalten in der Tabelle haben folgende Bedeutung:
638    
639     I<Watcher> ist die Anzahl der erzeugten Watcher-Objekte, d.h. die Anzahl
640     der Timer + I/O-Watcher.
641    
642     I<Bytes> ist die Anzahl der RAM-Bytes, die ein Watcher-Objekt im Schnitt
643     verbraucht. Dabei wird der Perl- und C-Anteil gezählt.
644    
645     I<Create> ist die durchschnittliche Zeit für die Erzeugung eines Watchers
646     in millionstel Sekunden.
647    
648     I<Invoke> ist die Zeit, in millionstel Sekunden, die die Ausführung des
649     Callbacks dauerte. Der Callback selbst zählt lediglich eine Variable
650     herunter.
651    
652     I<Destroy> schließlich ist die durchschnittliche Zeit für das freigeben
653     eines Watcher-Objektes, in millionstel Sekunden.
654    
655     Alle Benchmarks wurden auf einem Core2-Quad/3.6GHz durchgeführt, wobei
656     das Programm mit Echtzeitpriorität auf CPU #3 lief.
657    
658     Name Watcher Bytes Create Invoke Destroy Hinweise
659     EV/EV 400000 224 0.47 0.35 0.27 EV direkt
660     EV/Any 100000 224 2.88 0.34 0.27 EV über AnyEvent
661     Perl/Any 100000 452 4.13 0.73 0.95 AnyEvent/pure perl
662     Event/Event 16000 517 32.20 31.80 0.81 Event direkt
663     Event/Any 16000 590 35.85 31.55 1.06 Event über AnyEvent
664     Glib/Any 16000 1357 102.33 12.31 51.00 >quadratisches Wachstum
665     Tk/Any 2000 1860 27.20 66.31 14.00 SEGV bei >> 2000 watchers
666     POE/Event 2000 6328 109.99 751.67 14.02 via POE::Loop::Event
667     POE/Select 2000 6027 94.54 809.13 579.80 via POE::Loop::Select
668    
669     Wie erwähnt, ist der Benchmark so designed, daß das Kernel-Interface
670     (select, epoll etc.) keinen Einfluss hat. Das bedeutet, daß die
671     Skalierbarkeit der Event-Bibliothek hier I<nicht> gemessen wird.
672    
673     Die Anzahl der Watcher wurde so gewählt, daß die Ausführungszeit für
674     jede Event-Bibliothek ähnlich war: würde man mit EV weniger Watcher
675     wählen, bekäme man keine aussagekräftigen Zahlen, würde man mit Tk
676     mehr wählen, würde es crashen, und würde man bei Glib oder POE mehr
677     wählen, würde ich wohl heute noch nächstes Jahr auf die Ergebnisse
678     warten.
679    
680     Wie man sieht, ist die Ausführung von Callbacks und das Zerstören von Watchern
681     bei EV direkt (ohne AnyEvent) und bei AnyEvent mit EV als backend identisch, was daran liegt, daß AnyEvent keinerlei Overhead hinzufügt.
682    
683     Lediglich beim Erzeugen von Watchern ist AnyEvent+EV deutlich langsamer
684     als EV direkt. Das liegt daran, daß AnyEvent a) einen Methodenaufruf und
685     b) benannte Parameter benutzt. Diese beiden Umstände machen das Erzeugen
686     von Watchern mehr als fünf mal langsamer als die direkte Benutzung von
687     EV.
688    
689     Auch ist der Speicherverbrauch mit durchschnittlich 224 Bytes bei beiden
690     gleich.
691    
692     Sehr erfreulich ist auch, daß die Pure-Perl Event-Implementation nicht
693     viel hinterherhinkt: Erzeugen von Watchern und die Callback-Aufrufe
694     sind ungefähr halb so schnell wie mit der stark optimierten libev
695     C-Bibliothek. Der Speicherverbrauch ist ebenfalls noch im Rahmen und liegt
696     ca. beim doppelten dessen von EV.
697    
698     Etwas enttäuscht hat mich Event: Event war meine Bibliothek der Wahl, ich
699     hielt sie für sehr schnell und korrekt, musste aber im letzten Jahrzehnt
700     einige größere Design-Schwächen erkennen.
701    
702     Überrascht hat mich allerdings, wie viel langsamer Event gegenüber einer
703     Pure-Perl Implementation ist. Tatsächlich habe ich einige Zeit mit dem
704     Quellcode von Event verbracht und musste feststellen,daß Event in der tat
705     gewaltigen Aufwand beim Aufruf von Callbacks betreibt, was sich in der
706     Zeit niederschlägt. Die langsame Erzeugungszeit liegt dagegen schlicht
707     daran, daß jeder Parameter intern in einen dynamischen Methodenaufruf
708     umgesetzt wird.
709    
710     Wie man am Speicherverbrauch und dem Zeitunterschied sieht, ist die
711     direkte Benutzung von Event etwas effizienter als den Umweg über AnyEvent
712     zu gehen, allerdings ist der Overhead im Vergleich zur Langsamkeit von
713     Event sehr gering.
714    
715     Wie man an den anderen Zeilen sieht, liegt Event allerdings recht
716     gut: Glib ruft Callbacks zwar schneller auf, die anderen Zeiten sind aber graunhaft.
717    
718     Auch Tk (sofern es nicht crasht :) ist nicht wirklich schneller, und POE
719     ist jenseits von Gut und Böse.
720    
721     Tatsächlich ist die Implementation von AnyEvent auf POE nicht sehr
722     effizient, da POE dies ausschließt. Wie der nächste Benchmark beweist,
723     ist POE allerdings unter realistischen Bedingungen genauso langsam.
724    
725     Eine anderen Sicht der obigen Resultate ist, daß die Behandlung
726     eines Ereignisses mit EV ca. 1600 Taktzyklen, mit AnyEvents Pure Perl
727     Implementation ca. 3100 Zyklen und mit POE beinahe 3000000 Taktzyklen
728     benötigt.
729    
730     =head3 Benchmark 2: ein großer Server
731    
732     Was den AnyEvent-Overhead angeht, reicht mir der obige Benchmark völlig,
733     um mich zu beruhigen: der Overhead ist, abgesehen von der schnellsten
734     Event-Bibliothek, gering.
735    
736     Um die Pure-Perl Event-Bibliothek von AnyEvent zu testen, muss aber
737     ein anderer Benchmark her. Außerdem wollte ich unbedingt wissen, wie
738     verschiedene Systeme in der Praxis abschneiden.
739    
740     Um einen großen Server zu simulieren, gibt es ein paar
741     Standardbenchmarks. Einer davon ist es, sehr sehr viele Socketpaare zu
742     erzeugen. Auf der einen Seite jedes Paares ist ein "Server", der ein
743     einzelnes Octet liest, und dieses dann auf eine zufällige andere Socket
744     schreibt. Jedes Socketpaar hat einen asoziierten Timer, der bei jeder
745     Aktivität zurückgesetzt wird.
746    
747     Auf diese Weise wandern die Octets auf einem Teil der Verbindungen hin und
748     her, was in etwa einem realen Server entspricht: sehr viele Verbindungen,
749     aber nur ein kleiner Teil davon ist in jeder Iteration aktiv.
750    
751     Im folgenden werden 10000 Socketpaare (d.H. 20000 Sockets) erzeugt, und
752     davon sind jeweils 100 "aktiv".
753    
754     (Der Benchmark liegt AnyEvent als F<eg/bench2> bei).
755    
756     Die Spalten bedeuten im einzelnen:
757    
758     I<Create> ist die Zeit, die es braucht, um ein Socketpaar zu erzeugen und
759     alle Watcher zu registrieren, wieder in millionstel Sekunden.
760    
761     I<Request> ist bei weitem die wichtigste Größe. Sie gibt an, wie lange
762     es im Schnitt dauert, um eine "Anfrage" zu bearbeiten und den Timeout
763     zurückzusetzen.
764    
765     Name Create Request
766     EV 69.01 11.16
767     Perl 73.32 35.87
768     Event 212.62 257.32
769     Glib 651.16 1896.30
770     POE 349.67 12317.24 mit POE::Loop::Event
771    
772     Dieser Benchmark misst nun direkt die Skalierbarkeit und die
773     Geschwindigkeit der Event-Bibliothek.
774    
775     EV hat hier einen großen Vorteil, da es epoll, einen weitaus
776     effizienteren Mechanismus als select oder poll, benutzen kann, während
777     alle anderen entweder select oder poll benutzen.
778    
779     Wenig verwunderlich ist EV hier wieder mit Abstand am schnellsten.
780    
781     Sehr erstaunt war ich über das sehr gut Abschneiden der Pure-Perl
782     Implementation. Sie ließ die anderen C-Bibliotheken weit hinter
783     sich. Möglicherweise liegt der Grund hierfür darin, daß AnyEvent
784     ganz ähnliche Algorithmen wie EV benutzt um I/O-Watcher und Timer zu
785     verwalten, und ansonsten sehr abgespeckt ist.
786    
787     Event leidet sicher daran, daß es so teuer ist, Watcher zu erzeugen und
788     upzudaten.
789    
790     Woran Glib leidet, ist schlichtweg unglaubliche Ineffizienz: Alle
791     Watcher werden bei jeder Iteration vielmals angeschaut, teilweise
792     sogar verglichen. Ich glaube nicht, daß man eine derart ineffiziente
793     Event-Bibliothek erhielte, wenn man sich hinsetzte und einfach drauf los
794     schrieben ohne sich Gedanken zu machen. Tatsächlich ist Glib auch nicht
795     dafür gedacht, effizient zu sein oder mehr als einen File Descriptor zu
796     unterstützen (den zum X-Server nämlich).
797    
798     POE ist sicherlich etwas langsamer, als es sein könnte, da für jede
799     Verbindung drei "sessions" eingesetzt wurden, während POE eine Session
800     pro "Verbindung" vorschlägt. Allerdings ist derlei Kritik am Benchmark
801     irrelevant: Auch in einem echten Server würde man für jede Session eine
802     Session benutzen, und selbst wenn POE dreimal schneller würde wäre es
803     immer noch über 100 mal langsamer als die Pure-Perl Event-Implementation
804     von AnyEvent.
805    
806     Und das, obwohl in diesem Benchmark die Pure-Perl Version von POE durch
807     eine optimierte Variante ersetzt wurde, die das C<Event>-Modul benutzt.
808    
809     =head3 Benchmark 2: ein klitzekleiner Server
810    
811     Benchmarks für riesige Systeme sind sicher wichtig, aber wenn man "nur
812     eben" mal AnyEvent benutzt, so sollte es auch schnell sein, wenn man nur
813     sehr wenige aktive Verbindungen hat.
814    
815     Im folgenden wurde daher nur acht Socketpaare benutzt, von denen jeweils drei aktiv sind:
816    
817     Name Create Request
818     EV 20.00 6.54
819     Perl 25.75 12.62
820     Event 81.27 35.86
821     Glib 32.63 15.48
822     POE 261.87 276.28 mit POE::Loop::Event
823    
824     Wie man sieht, ändert sich nichts drastisches: Glib ist nun so schnell
825     wie die anderen, aber EV und AnyEvents Pure-Perl Implementation sind
826     trotzdem schneller.
827    
828     Während POE weiterhin stark hinterherhinkt, für drei Verbindungen aber
829     absolut adäquat ist :->
830    
831    
832 root 1.1 =head2 Ausblick auf CPAN
833 root 1.2
834     AnyEvent existiert nicht in Isolation: Es gibt inzwischen eine stattliche
835     Anzahl von CPAN-Modulen die AnyEvent und nur AnyEvent als Abhängigkeit
836     besitzen. Für AnyEvent ist es nicht so wichtig für für andere
837     "Frameworks" (wie POE), viele weitere CPAN-Module zu benutzen, da
838     AnyEvent-Module ja mit anderen Frameworks kombiniert werden können,
839     umgekehrt ist dies allerdings nicht der Fall (AnyEvent + POE Programm
840     geht, POE + Tk-Programm geht nicht).
841    
842     Hier ist eine fast erschöpfende Auswahl von AnyEvent-Modulen auf CPAN:
843    
844     =over 4
845    
846     =item AnyEvent::HTTP
847    
848     Ein ganz einfacher HTTP-Client, da man mit LWP keine parallelen Abfragen
849     durchführen im selben Prozess kann, ist es recht hilfreich :)
850    
851     =item Anyevent::AIO
852    
853     Integriert IO::AIO transparent in AnyEvent. AnyEvent::AIO ist ein ideales
854     Pendant zu AnyEvent: AnyEvent abstrahiert non-blocking I/O, AnyEvent::AIO
855     abstrahiert asynchrones I/O.
856    
857     =item AnyEvent::DBI
858    
859     Langsames, aber asynchrones, DBI-Frontend.
860    
861     =item AnyEvent::CouchDB
862    
863     Eine Schnittstelle zur CouchDB. Ein must have!
864    
865     =item AnyEvent::BDB
866    
867     Asynchrone Schnittstelle zur guten alten BerkelyDB.
868    
869     =item AnyEvent::IRC
870    
871     Event basiertes IRC.
872    
873     =item AnyEvent::XMPP
874    
875     Alternative zum eigenen Parser für Jabber-Pseudo-XML.
876    
877     =item AnyEvent::FastPing
878    
879     Wenn man mal eine Million Ping-Pakete pro Sekunde verschicken will. Eignet
880     sich ideal um Firewalls abzuschießen :)
881    
882     =item AnyEvent::Mojo
883    
884     Wenn ich's bloß wüsste...
885    
886     =item AnyEvent::HTTPD
887    
888     Ein einfacher Webserver zum Einbetten in die eigene Applikation.
889    
890     =item Coro::AnyEvent
891    
892     Die Kombination von Coro-Threads und AnyEvent ist ideal - komplexe Logik
893     kann man bequem per Thread implementieren, Low-Level Event-Handling geht
894     meist per AnyEvent angenehmer.
895    
896     =back