ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2009/anyevent.pod
Revision: 1.7
Committed: Sat Jul 18 05:59:11 2009 UTC (17 years, 2 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +1 -1 lines
Log Message:
riddify us of meta.yml garbage in manifest

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 root 1.3 Nun, AnyEvent ist, wie im Namensteil "Event" steht, ein Event-Modul
13 root 1.1 bzw. eine Event-Bibliothek. Event-Module oder -Bibliotheken stellen
14 root 1.3 im allgemeinen Funktionalität bereit, mit der man auf Ereignisse
15 root 1.1 (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 root 1.3 verfügbar ist, eventbasiert programmiert werden kann.
53 root 1.1
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 root 1.6 my $data = $db->view('users/all', { key => 'b' })->recv;
61 root 1.1
62 root 1.3 Obwohl die Abfrage selbst ereignisgesteuert ist, muss man als Benutzer
63 root 1.1 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 root 1.3 Im Code werde die Vorteile sichtbar, wenn man mehrere Abfragen "gleichzeitig"
69 root 1.1 (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 root 1.3 Wie viele andere Bibliotheken auch, benutzt AnyEvent das Konzept eines
107     "Watchers", eines Objekts, das 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 root 1.1
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 root 1.6 warn "Sieben Sekunden sind abgelaufen!";
119 root 1.1 });
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 root 1.3 Das obige Beispiel benutzt eine "condition variable", um mit dem
150     Hauptprogramm zu kommunizieren (mehr Info s.u.).
151 root 1.1
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 root 1.3 richtig tun möchte :), sind Child-Watcher: mit diesen kann man auf das
160 root 1.1 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 root 1.3 das Event-Modul ist klein und wenn man bezahlt nur für das, was man
202 root 1.1 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 root 1.3 Ich gebe zu, das war sicher noch nicht der Brüller, aber sehen wir
235 root 1.1 weiter:
236    
237 root 1.5 =head2 AnyEvent::Util
238 root 1.1
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 root 1.3 keinen Weg gefunden, unter einem native-win32-Perl zu forken und das Kind
257     sauber zu beenden (ich glaube, es gibt keinen...).
258 root 1.1
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 root 1.3 C<tcp_connect> kann aber noch mehr. Z.b. auf Jabber-Server connecten, was
304 root 1.1 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 root 1.3 andere Protokolle unterstützt, z.B. local unix Sockets:
313 root 1.1
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 root 1.3 Komplizierteres ist immer möglich - anders als z.B. mit C<IO::Socket> hat
341 root 1.1 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 root 1.4 Man kann jederzeit eigene Formatierungstypen global für alle Handles
485     hinzufügen. Zusätzlich zu den schon vorgestellten Typen für die
486     Schreibrichtung, die auch für die Leserichtung existieren, gibt es noch:
487 root 1.1
488     $hdl->push_read (line => $eol, $cb); # zeilen
489 root 1.7 $hdl->push_Read (regex => $accept[, $reject[, $skip], $cb);
490 root 1.1
491     =item Pipelining
492    
493     Pipelining bedeutet, daß man auf einer bestehenden Verbindung mehrere
494     Anfragen gleichzeitig losschickt. Die Herausforderung liegt darin, daß
495     man beim Empfang der Antworten flexibel auf Ausnahmen reagieren können
496     muss.
497    
498     Bei HTTP beispielsweise weiß man erst nach Parsen des Headers, wie lang
499     der Body wird.
500    
501     AnyEvent::Handle erledigt dies mit einer Kombination aus C<push_read> und
502     C<unshift_read>:
503    
504     # sende requests
505     for (@urls) {
506     $hdl->push_write ("GET $_ HTTP/1.0\015\012\015\012");
507     }
508    
509     # parse antworten
510     for (@urls) {
511     # lese header
512     $hdl->push_read (line => "\015\012\015\012", sub {
513     my ($hdl, $header) = @_;
514    
515     my $content_length = extract "Content-Length", $header;
516    
517     $hdl->unshift_read (chunk => $content_length, sub {
518     my ($hdl, $body) = @_;
519    
520     # fertig
521     });
522     });
523     }
524    
525     Der springende Punkt ist, daß C<unshift_read> erst I<nach> dem Empfang
526     des Headers ausgeführt wird. Dadurch kann man z.B. verschiedene Arten von
527     Antworten parsen, oder auf unerwartete Fehler reagieren, obwohl vielleicht
528     schon Antworten auf die nächsten Requests empfangen wurden.
529    
530     =item TLS/SSL
531    
532     TLS ist der Horror. Nicht nur, aber vor allem auch wegen der grauenvollen
533     OpenSSL-API (GnuTLS ist geringfügig besser, doch sucht man vergebens nach
534     einem guten Perl-Modul dafür). Der Beweis dafür ist, daß es praktisch
535     kein Modul gibt, daß non-blocking TLS connects korrekt und wirklich
536     non-blocking durchführt.
537    
538     Es hilft auch nicht gerade, daß Net::SSLeay nur einen Bruchteil der
539     OpenSSL-API umsetzt.
540    
541     AnyEvent::Handle (to boldly go...) versucht einen ganz neuen Ansatz für
542     diese Problematik, bei der OpenSSL vom eigentlichen File Handle komplett
543     getrennt wird, d.h. gar keinen Zugriff auf diesen hat. Dadurch wird
544     garantiert, daß OpenSSL auf gar keinen Fall blockieren kann.
545    
546 root 1.2 Ganz wie der Rest von AnyEvent ist einfach einfach: wenn man zu einem
547     TLS-Server connecten möchte, setzt man C<tls> auf C<"connect">, als
548     TLS-Server dagegen setzt man es auf C<"accept">.
549    
550     Hat man kompliziertere Ansprüche, wie Zertifikate oder
551     Verification-Callbacks, so kann man sein eigenes Net::SSLeay::CTX-Objekt
552     oder das Net::SSLeay-Objekt für die Verbindung selbst übergeben.
553    
554     Selbstverständlich kann man den TLS-Handshake zu einem beliebigen
555     Zeitpunkt beginnen, nicht nur am Anfang der Verbindung.
556    
557 root 1.1 =back
558    
559 root 1.2 Mit AnyEvent::Handle wird manches erstaunlich einfach. Hier ist z.B. ein
560     (ganz primitiver) HTTPS-Client (übrigens das komplette Programm):
561 root 1.1
562     use AnyEvent;
563     use AnyEvent::Socket;
564     use AnyEvent::Handle;
565    
566     my $cv = AnyEvent->condvar;
567    
568     tcp_connect "www.google.com", "443", sub {
569     my ($fh) = @_ or die;
570    
571     my $hdl; $hdl = new AnyEvent::Handle
572     fh => $fh,
573     timeout => 60,
574     tls => "connect",
575     on_eof => sub {
576     undef $hdl; # gibt handle frei
577     $cv->send; # isch hab' ferdisch
578     },
579     on_read => sub {
580     my ($hdl) = @_;
581     print $hdl->{rbuf};
582     $hdl->{rbuf} = "";
583     };
584    
585     $hdl->push_write ("GET / HTTP/1.0\015\012\015\012");
586     };
587    
588     $cv->recv;
589    
590 root 1.4 Zuerst zum Einsatz kommt C<tcp_connect>, um den non-blocking Connect
591     durchzuführen. Danach wird das Handle-Objekt erzeugt, konfiguriert,
592     und danach lediglich der Request gesendet, der Rest des Protokolls wird
593     ereignisgesteuert abgehandelt. Der Unterschied zwischen TLS (https) und
594     nicht-TLS (http) besteht lediglich in dem Parameter C<tls => "connect">,
595     der einen sofortigen TLS-Client-Handshake auslöst (will man in der
596     Mitte der Verbindung switchen, z.b. für SMTP, kann man jederzeit die
597     C<starttls>-Methode aufrufen).
598    
599 root 1.2 Darüber hinaus gibt es eine Menge Parameter, mit dem man Verhalten,
600     Fehlerbehandlung, Ressourcenbenutzung auf seine Anforderungen abstimmen
601     kann. Für ganz spezielle Anwendungen kann man von AnyEvent::Handle auch
602     eigene Klassen ableiten, aber in den meisten Fällen ist dies unnötig.
603    
604     Ein Nachteil von AnyEvent::Handle ist allerdings, daß die Abstraktion
605     selbst nicht kostenlos ist: Methodenaufrufe in Perl sind vergleichsweise
606     langsam, und AnyEvent::Handle benutzt sehr viele davon. In den meisten
607     Fällen merkt man davon allerdings nichts, da der Overhead durch
608     AnyEvent::Handle immer noch sehr gering ist, wenn man mit den Daten auch
609     noch etwas tun möchte.
610    
611 root 1.1 =back
612    
613    
614     =head2 Benchmarks
615    
616 root 1.2 Ich bin es gewohnt, meine eigene Lösungen zu schreiben, notfalls immer
617     und immer wieder. Bevor ich eine (hilfreiche) Abstraktion ruhigen
618     Gewissens benutzen kann, muss ich immer erst wissen, wie viel sie kostet,
619     damit ich eine vernünftige Abwägung machen kann.
620    
621     Deshalb habe ich drei Benchmarks durchgeführt, um herauszufinden, wie
622     hoch der Overhead von AnyEvent gegenüber der direkten Benutzung von
623     Event-Bibliotheken ist, und wie verschiedene Event-Bibliotheken bei
624     typischen Server-Situationen skalieren, sowohl für Server mit sehr vielen
625     Verbindungen, als auch für Server mit sehr wenigen.
626    
627     =head3 Benchmark 1: Overhead
628    
629     Um den Overhead von AnyEvent selbst zu testen, erzeugt dieser Benchmark
630     sehr viele Timer (mit einem Time-out von 0 Sekunden) und ebensoviele
631     I/O watcher auf STDOUT (üblicherweise eine tty), der auf den
632     "schreibbar"-Zustand wartet.
633    
634     Dann lässt er alle Watcher genau einmal ihren Callback aufrufen und
635     zerstört die Watcher dann.
636    
637     Gemessen wird die Zeit, die es jeweils braucht, einen Watcher zu erzeugen,
638     den Callback auszuführen und den Watcher wieder zu zerstören.
639    
640     Die Kernel-Schnittstelle sollte einen relativ geringen Einfluss besitzen,
641     sofern die Event-Bibliothek einigermaßen effizient implementiert wurde,
642     da nur ein einziges mal ein einziger File-Descriptor abgefragt werden
643     muss.
644    
645     (Der Benchmark liegt AnyEvent als F<eg/bench> bei).
646    
647     Die Spalten in der Tabelle haben folgende Bedeutung:
648    
649     I<Watcher> ist die Anzahl der erzeugten Watcher-Objekte, d.h. die Anzahl
650     der Timer + I/O-Watcher.
651    
652     I<Bytes> ist die Anzahl der RAM-Bytes, die ein Watcher-Objekt im Schnitt
653     verbraucht. Dabei wird der Perl- und C-Anteil gezählt.
654    
655     I<Create> ist die durchschnittliche Zeit für die Erzeugung eines Watchers
656     in millionstel Sekunden.
657    
658     I<Invoke> ist die Zeit, in millionstel Sekunden, die die Ausführung des
659     Callbacks dauerte. Der Callback selbst zählt lediglich eine Variable
660     herunter.
661    
662     I<Destroy> schließlich ist die durchschnittliche Zeit für das freigeben
663     eines Watcher-Objektes, in millionstel Sekunden.
664    
665     Alle Benchmarks wurden auf einem Core2-Quad/3.6GHz durchgeführt, wobei
666     das Programm mit Echtzeitpriorität auf CPU #3 lief.
667    
668     Name Watcher Bytes Create Invoke Destroy Hinweise
669 root 1.3 /uSec /uSec
670 root 1.2 EV/EV 400000 224 0.47 0.35 0.27 EV direkt
671     EV/Any 100000 224 2.88 0.34 0.27 EV über AnyEvent
672     Perl/Any 100000 452 4.13 0.73 0.95 AnyEvent/pure perl
673     Event/Event 16000 517 32.20 31.80 0.81 Event direkt
674     Event/Any 16000 590 35.85 31.55 1.06 Event über AnyEvent
675     Glib/Any 16000 1357 102.33 12.31 51.00 >quadratisches Wachstum
676     Tk/Any 2000 1860 27.20 66.31 14.00 SEGV bei >> 2000 watchers
677     POE/Event 2000 6328 109.99 751.67 14.02 via POE::Loop::Event
678     POE/Select 2000 6027 94.54 809.13 579.80 via POE::Loop::Select
679    
680     Wie erwähnt, ist der Benchmark so designed, daß das Kernel-Interface
681     (select, epoll etc.) keinen Einfluss hat. Das bedeutet, daß die
682     Skalierbarkeit der Event-Bibliothek hier I<nicht> gemessen wird.
683    
684     Die Anzahl der Watcher wurde so gewählt, daß die Ausführungszeit für
685     jede Event-Bibliothek ähnlich war: würde man mit EV weniger Watcher
686     wählen, bekäme man keine aussagekräftigen Zahlen, würde man mit Tk
687     mehr wählen, würde es crashen, und würde man bei Glib oder POE mehr
688 root 1.3 wählen, würde ich wohl noch nächstes Jahr auf die Ergebnisse
689 root 1.2 warten.
690    
691     Wie man sieht, ist die Ausführung von Callbacks und das Zerstören von Watchern
692     bei EV direkt (ohne AnyEvent) und bei AnyEvent mit EV als backend identisch, was daran liegt, daß AnyEvent keinerlei Overhead hinzufügt.
693    
694     Lediglich beim Erzeugen von Watchern ist AnyEvent+EV deutlich langsamer
695     als EV direkt. Das liegt daran, daß AnyEvent a) einen Methodenaufruf und
696     b) benannte Parameter benutzt. Diese beiden Umstände machen das Erzeugen
697     von Watchern mehr als fünf mal langsamer als die direkte Benutzung von
698     EV.
699    
700     Auch ist der Speicherverbrauch mit durchschnittlich 224 Bytes bei beiden
701     gleich.
702    
703     Sehr erfreulich ist auch, daß die Pure-Perl Event-Implementation nicht
704     viel hinterherhinkt: Erzeugen von Watchern und die Callback-Aufrufe
705     sind ungefähr halb so schnell wie mit der stark optimierten libev
706     C-Bibliothek. Der Speicherverbrauch ist ebenfalls noch im Rahmen und liegt
707     ca. beim doppelten dessen von EV.
708    
709     Etwas enttäuscht hat mich Event: Event war meine Bibliothek der Wahl, ich
710     hielt sie für sehr schnell und korrekt, musste aber im letzten Jahrzehnt
711     einige größere Design-Schwächen erkennen.
712    
713     Überrascht hat mich allerdings, wie viel langsamer Event gegenüber einer
714     Pure-Perl Implementation ist. Tatsächlich habe ich einige Zeit mit dem
715 root 1.3 Quellcode von Event verbracht und musste feststellen,daß Event in der Tat
716 root 1.2 gewaltigen Aufwand beim Aufruf von Callbacks betreibt, was sich in der
717     Zeit niederschlägt. Die langsame Erzeugungszeit liegt dagegen schlicht
718     daran, daß jeder Parameter intern in einen dynamischen Methodenaufruf
719     umgesetzt wird.
720    
721     Wie man am Speicherverbrauch und dem Zeitunterschied sieht, ist die
722     direkte Benutzung von Event etwas effizienter als den Umweg über AnyEvent
723     zu gehen, allerdings ist der Overhead im Vergleich zur Langsamkeit von
724     Event sehr gering.
725    
726     Wie man an den anderen Zeilen sieht, liegt Event allerdings recht
727 root 1.3 gut: Glib ruft Callbacks zwar schneller auf, die anderen Zeiten sind aber grauenhaft.
728 root 1.2
729     Auch Tk (sofern es nicht crasht :) ist nicht wirklich schneller, und POE
730     ist jenseits von Gut und Böse.
731    
732     Tatsächlich ist die Implementation von AnyEvent auf POE nicht sehr
733     effizient, da POE dies ausschließt. Wie der nächste Benchmark beweist,
734     ist POE allerdings unter realistischen Bedingungen genauso langsam.
735    
736     Eine anderen Sicht der obigen Resultate ist, daß die Behandlung
737 root 1.3 eines Ereignisses mit EV ca. 1_600 Taktzyklen, mit AnyEvents Pure Perl
738     Implementation ca. 3_100 Zyklen und mit POE beinahe 3_000_000 Taktzyklen
739     benötigt_.
740 root 1.2
741     =head3 Benchmark 2: ein großer Server
742    
743     Was den AnyEvent-Overhead angeht, reicht mir der obige Benchmark völlig,
744 root 1.4 um mich zu beruhigen: der Overhead von AnyEvent über die Event-Bilbiothek
745     hinaus ist gering, wenn man von EV absieht (was natürlich daran liegt,
746     daß EV so schnell ist).
747 root 1.2
748     Um die Pure-Perl Event-Bibliothek von AnyEvent zu testen, muss aber
749     ein anderer Benchmark her. Außerdem wollte ich unbedingt wissen, wie
750     verschiedene Systeme in der Praxis abschneiden.
751    
752     Um einen großen Server zu simulieren, gibt es ein paar
753     Standardbenchmarks. Einer davon ist es, sehr sehr viele Socketpaare zu
754     erzeugen. Auf der einen Seite jedes Paares ist ein "Server", der ein
755     einzelnes Octet liest, und dieses dann auf eine zufällige andere Socket
756 root 1.3 schreibt. Jedes Socketpaar hat einen assoziierten Timer, der bei jeder
757 root 1.2 Aktivität zurückgesetzt wird.
758    
759     Auf diese Weise wandern die Octets auf einem Teil der Verbindungen hin und
760     her, was in etwa einem realen Server entspricht: sehr viele Verbindungen,
761     aber nur ein kleiner Teil davon ist in jeder Iteration aktiv.
762    
763 root 1.3 Im folgenden werden 10_000 Socketpaare (d.h. 20_000 Sockets) erzeugt, und
764 root 1.2 davon sind jeweils 100 "aktiv".
765    
766     (Der Benchmark liegt AnyEvent als F<eg/bench2> bei).
767    
768     Die Spalten bedeuten im einzelnen:
769    
770     I<Create> ist die Zeit, die es braucht, um ein Socketpaar zu erzeugen und
771     alle Watcher zu registrieren, wieder in millionstel Sekunden.
772    
773     I<Request> ist bei weitem die wichtigste Größe. Sie gibt an, wie lange
774     es im Schnitt dauert, um eine "Anfrage" zu bearbeiten und den Timeout
775     zurückzusetzen.
776    
777     Name Create Request
778 root 1.3 /uSec /uSec
779 root 1.2 EV 69.01 11.16
780     Perl 73.32 35.87
781     Event 212.62 257.32
782     Glib 651.16 1896.30
783     POE 349.67 12317.24 mit POE::Loop::Event
784    
785     Dieser Benchmark misst nun direkt die Skalierbarkeit und die
786     Geschwindigkeit der Event-Bibliothek.
787    
788     EV hat hier einen großen Vorteil, da es epoll, einen weitaus
789     effizienteren Mechanismus als select oder poll, benutzen kann, während
790     alle anderen entweder select oder poll benutzen.
791    
792     Wenig verwunderlich ist EV hier wieder mit Abstand am schnellsten.
793    
794 root 1.3 Sehr erstaunt war ich über das sehr gute Abschneiden der Pure-Perl
795 root 1.2 Implementation. Sie ließ die anderen C-Bibliotheken weit hinter
796     sich. Möglicherweise liegt der Grund hierfür darin, daß AnyEvent
797     ganz ähnliche Algorithmen wie EV benutzt um I/O-Watcher und Timer zu
798     verwalten, und ansonsten sehr abgespeckt ist.
799    
800     Event leidet sicher daran, daß es so teuer ist, Watcher zu erzeugen und
801     upzudaten.
802    
803     Woran Glib leidet, ist schlichtweg unglaubliche Ineffizienz: Alle
804     Watcher werden bei jeder Iteration vielmals angeschaut, teilweise
805     sogar verglichen. Ich glaube nicht, daß man eine derart ineffiziente
806     Event-Bibliothek erhielte, wenn man sich hinsetzte und einfach drauf los
807 root 1.3 schriebe ohne sich Gedanken zu machen. Tatsächlich ist Glib auch nicht
808 root 1.2 dafür gedacht, effizient zu sein oder mehr als einen File Descriptor zu
809     unterstützen (den zum X-Server nämlich).
810    
811     POE ist sicherlich etwas langsamer, als es sein könnte, da für jede
812     Verbindung drei "sessions" eingesetzt wurden, während POE eine Session
813     pro "Verbindung" vorschlägt. Allerdings ist derlei Kritik am Benchmark
814     irrelevant: Auch in einem echten Server würde man für jede Session eine
815     Session benutzen, und selbst wenn POE dreimal schneller würde wäre es
816     immer noch über 100 mal langsamer als die Pure-Perl Event-Implementation
817     von AnyEvent.
818    
819 root 1.3 Im übrigen wurde in diesem Benchmark sogar die Pure-Perl Version von POE durch
820 root 1.2 eine optimierte Variante ersetzt wurde, die das C<Event>-Modul benutzt.
821    
822 root 1.3 =head3 Benchmark 3: ein klitzekleiner Server
823 root 1.2
824     Benchmarks für riesige Systeme sind sicher wichtig, aber wenn man "nur
825 root 1.3 eben" mal AnyEvent benutzt, sollte es auch schnell sein, wenn man nur
826 root 1.2 sehr wenige aktive Verbindungen hat.
827    
828     Im folgenden wurde daher nur acht Socketpaare benutzt, von denen jeweils drei aktiv sind:
829    
830     Name Create Request
831 root 1.3 /uSec /uSec
832 root 1.2 EV 20.00 6.54
833     Perl 25.75 12.62
834     Event 81.27 35.86
835     Glib 32.63 15.48
836     POE 261.87 276.28 mit POE::Loop::Event
837    
838 root 1.3 Wie man sieht, ändert sich nichts drastisch: Glib ist nun so schnell
839 root 1.2 wie die anderen, aber EV und AnyEvents Pure-Perl Implementation sind
840     trotzdem schneller.
841    
842     Während POE weiterhin stark hinterherhinkt, für drei Verbindungen aber
843     absolut adäquat ist :->
844    
845    
846 root 1.1 =head2 Ausblick auf CPAN
847 root 1.2
848     AnyEvent existiert nicht in Isolation: Es gibt inzwischen eine stattliche
849     Anzahl von CPAN-Modulen die AnyEvent und nur AnyEvent als Abhängigkeit
850 root 1.3 besitzen. Für AnyEvent ist es nicht so wichtig wie für andere
851 root 1.2 "Frameworks" (wie POE), viele weitere CPAN-Module zu benutzen, da
852     AnyEvent-Module ja mit anderen Frameworks kombiniert werden können,
853     umgekehrt ist dies allerdings nicht der Fall (AnyEvent + POE Programm
854     geht, POE + Tk-Programm geht nicht).
855    
856     Hier ist eine fast erschöpfende Auswahl von AnyEvent-Modulen auf CPAN:
857    
858     =over 4
859    
860     =item AnyEvent::HTTP
861    
862 root 1.3 Ein ganz einfacher HTTP-Client. Da man mit LWP keine parallelen Abfragen
863 root 1.2 durchführen im selben Prozess kann, ist es recht hilfreich :)
864    
865 root 1.3 =item AnyEvent::AIO
866 root 1.2
867     Integriert IO::AIO transparent in AnyEvent. AnyEvent::AIO ist ein ideales
868 root 1.3 Pendant zu AnyEvent: AnyEvent abstrahiert non-blocking I/O, IO::AIO
869 root 1.2 abstrahiert asynchrones I/O.
870    
871     =item AnyEvent::DBI
872    
873     Langsames, aber asynchrones, DBI-Frontend.
874    
875     =item AnyEvent::CouchDB
876    
877     Eine Schnittstelle zur CouchDB. Ein must have!
878    
879     =item AnyEvent::BDB
880    
881     Asynchrone Schnittstelle zur guten alten BerkelyDB.
882    
883     =item AnyEvent::IRC
884    
885     Event basiertes IRC.
886    
887     =item AnyEvent::XMPP
888    
889     Alternative zum eigenen Parser für Jabber-Pseudo-XML.
890    
891     =item AnyEvent::FastPing
892    
893     Wenn man mal eine Million Ping-Pakete pro Sekunde verschicken will. Eignet
894     sich ideal um Firewalls abzuschießen :)
895    
896     =item AnyEvent::Mojo
897    
898     Wenn ich's bloß wüsste...
899    
900     =item AnyEvent::HTTPD
901    
902     Ein einfacher Webserver zum Einbetten in die eigene Applikation.
903    
904     =item Coro::AnyEvent
905    
906     Die Kombination von Coro-Threads und AnyEvent ist ideal - komplexe Logik
907     kann man bequem per Thread implementieren, Low-Level Event-Handling geht
908     meist per AnyEvent angenehmer.
909    
910     =back