% $Id$

% Mise au point
\documentclass[a4,landscape,article]{seminar}

% Impression réelle
%\documentclass[a4,landscape,slidesonly]{seminar}

\usepackage[latin1]{inputenc}
\usepackage{fancybox}
\usepackage{eepic}
\usepackage{latexsym}
\usepackage{bortzmeyer-utils}
\newpagestyle{MH}%
  {\thepage}
  {echoping\hfil}
\slidepagestyle{MH}

\pagestyle{empty}

\title{echoping, mesurer les applications}
\author{Stéphane Bortzmeyer\\
AFNIC\\
\url{<bortz@users.sourceforge.net>}
}
\date{4 octobre 2004}

\begin{document}

\begin{slide}
\maketitle
\addtocounter{slide}{-1}
\slidepagestyle{empty}
\end{slide}

\begin{slide}
\heading{Mesurer les applications}
\begin{itemize}
  \item On mesure souvent le temps de réponse du réseau (RTT) avec ping
\item Mais celui des applications peut être très différent
  \begin{enumerate}
    \item Unix : traitement par le noyau ou par une application qui
    \foreign{swappe}
    \item Délais spécifiques à l'application (contacter la base de
    données\ldots)
    \item Coupe-feux qui bloquent ICMP
    \item \foreign{Layer-4 or Layer-7 switches} qui traitent différemment ICMP et TCP
  \end{enumerate}
\end{itemize}
\end{slide}

\begin{slide}
\heading{Limite des outils classiques}
Certains outils n'ont pas de mesure du RTT : on les emballe avec
\computer{time}. Inconvénients :
\begin{enumerate}
  \item On mesure le temps de résolution DNS, 
  \item On mesure le temps de lancement du
  programme (s'il est en Perl, cela fausse tout)\ldots
\end{enumerate}

Certains outils ont la mesure de RTT (\computer{dig}). Mais pas de
possibilité de répéter le test donc, il faut utiliser \computer{awk}
si on veut des statistiques.
\end{slide}

Exemple avec dig, le script qtest, qui détermine le serveur le plus
rapide (BIND utilise un algorithme analogue pour savoir quel serveur
d'un domaine interroger).
\begin{info}
#!/bin/sh
#
# From: Joe Abley <jabley@isc.org>

query=$1; shift
#
[ -z "$*" ] && echo "Syntax: $0 query server..." && exit 1
#
for i in 0 1 2; do
   for server in $*; do
     dig @${server} ${query};
   done
done | \
   awk '/^;; Query time:/ { query_time = $4; } \
     /^;; SERVER: / { sum[$3] += query_time; num[$3]++; } \
     END { for (server in sum) { print int(sum[server]/num[server]), server; } }' | \
   sort -n | head -1
\end{info}

\begin{slide}
  \heading{echoping}
\url{http://echoping.sourceforge.net/}

9 ans d'utilisation aujourd'hui.

A surtout décollé dans le cadre du projet Renater-Cache (mesurer le
temps de réponse du cache national, par exemple avant et après un réglage).

Mesurer le RTT d'une requête applicative. Le chrono est lancé
\emph{après} la résolution DNS. 

Tourne sur tout Unix, en ligne de commandes, pour utilisation par des
scripts (mon, Nagios, MRTG, Smokeping).

Smokeping (\url{http://www.smokeping.org/}) est de loin le plus gros
utilisateur d'echoping.
\end{slide}

\begin{slide}
\heading{Protocoles utilisés}
\begin{enumerate}
  \item Au début, echo, discard et chargen
 \item Puis HTTP (Renater-Cache), toujours le plus utilisé
  \item Demain, DNS, whois, PostgreSQL, LDAP\ldots
\end{enumerate}

\end{slide}

\begin{slide}
  \heading{Répétition des tests}

Comme ping, on peut répéter les tests et avoir des statistiques.
  \begin{info}
% echoping -h 10 -h / webmail.nic.af
...
Minimum time: 1.799637 seconds (142 bytes per sec.)
Maximum time: 16.494219 seconds (16 bytes per sec.)
Average time: 3.356738 seconds (76 bytes per sec.)
Standard deviation: 3.730219
Median time: 2.003397 seconds (128 bytes per sec.)
  \end{info}
\end{slide}

\begin{slide}
  \heading{Moyenne et médiane}
Sur l'Internet, ou sur un serveur chargé, la moyenne est peu
significative : un seul test très lent la change beaucoup.

La médiane est en général plus informative.

\begin{info}
Elapsed time: 3.030966 seconds
Elapsed time: 122.533918 seconds
Elapsed time: 2.394198 seconds
Elapsed time: 2.012312 seconds
Elapsed time: 1.432407 seconds
...
---
Minimum time: 1.432407 seconds (179 bytes per sec.)
Maximum time: 122.533918 seconds (2 bytes per sec.)
Average time: 11.393709 seconds (22 bytes per sec.)
Standard deviation: 26.072556
Median time: 2.712582 seconds (94 bytes per sec.)
\end{info}
\end{slide}

%\begin{slide}
%  \heading{Les temps de réponse et leur variation}
%\input{whois-ripe.epic}
%\end{slide}

\begin{slide}
\heading{Les greffons}  
Beaucoup d'utilisateurs réclamaient le support de tel ou tel
protocole. 

Souvent, ils envoyaient le \foreign{patch}.

Le code devenait de plus en plus complexe. Et dépendant de
bibliothèques extérieures.

echoping 6 introduira donc les greffons (\foreign{plug-ins}), écrits à
part et chargés dynamiquement.

\end{slide}

\begin{slide}
  \heading{Utiliser le greffon DNS}
  \begin{info}
% echoping -v -m dns ns2.nic.fr -t NS nic.fr
This is echoping, version 6.0-BETA.

Running start() for the plugin dns.so...
Trying to call plugin dns.so for internet address 192.134.0.4 53...
Elapsed time: 0.001717 seconds
  \end{info}
\end{slide}

\begin{slide}
  \heading{Utiliser le greffon PostgreSQL}
  \begin{info}
% echoping -v -m postgresql localhost -c 'dbname=essais' \
        'SELECT * FROM Foobar'

This is echoping, version 6.0-BETA.

Running start() for the plugin postgresql.so...
Trying to call plugin postgresql.so...
3 tuples returned
Elapsed time: 0.058392 seconds
  \end{info}
\end{slide}

\begin{slide}
  \heading{API des greffons}
Les greffons se programment en C
\begin{itemize}
\item \computer{char * init (const int argc, const char **argv, const echoping\_options options)} Initialise
\item \computer{void start (struct addrinfo *res)} Se connecte
\item \computer{int execute ()} Le chronomètre est lancé juste avant
\item \computer{void terminate ()}
\end{itemize}
\end{slide}

Exemple avec le greffon whois, le plus simple vue la simplicité du
protocole (\rfc{3912}) :
\begin{info}
char *
init (const int argc, const char **argv, echoping_options global_options)
{
  /* Analyse les arguments */
  return "nicname";
}

void
start (struct addrinfo *res)
{
  whois_server = *res;
}

int
execute ()
{
  int nr = 0;
  char recvline[MAX_LINE + 1];
  char complete_request[MAX_REQUEST];
  if ((sockfd =
       socket (whois_server.ai_family, whois_server.ai_socktype,
	       whois_server.ai_protocol)) < 0)
    err_sys ("Can't open socket");
  if (connect (sockfd, whois_server.ai_addr, whois_server.ai_addrlen) < 0)
    err_sys ("Can't connect to server");
  if ((files = fdopen (sockfd, "r")) == NULL)
    err_sys ("Cannot fdopen");
  sprintf (complete_request, "%s\r\n", request);
  n = strlen (complete_request);
  if (writen (sockfd, complete_request, n) != n)
    err_sys ("writen error on socket");
  /* Read from the server */
  while ((nr = readline (files, recvline, MAX_LINE, 0)) > 0)
    if (dump)
      printf ("%s", recvline);
  if (dump)
    printf ("\n");
  close (sockfd);
  return 1;
}

void
terminate ()
{
}
\end{info}

\end{document}





