Postfix: Démons et gestion des files d'attente
Table des matières
Dans l’article précédent, nous posions des bases et habitudes courantes pour se débrouiller avec Postfix quand on débute dans ce genre de pratique.
Aujourd’hui, on continue de parler de Postfix mais cette fois-ci nous abordons des notions un peu plus poussées, comme les démons et les files d’attente. Accrochez vous, c’est parti !
Comment ça fonctionne ?
Avant de s’amuser à traiter des files d’attente, il serait bon de comprendre comment sont orchestrées ces files et par qui.
Déjà, pour qu’on parle tous le même langage, je vous mets à disposition un diagramme des composants de Postfix et montrant leur manière de communiquer. On y retrouve le workflow presque complet. Presque, dans le sens où on a uniquement le service Postfix et pas de services secondaires comme un anti-spam ou un anti-virus:
Les rectangles bleus sont les services (ou démons), et les boites les files d’attente, au nombre de 5: hold, maildrop, deferred, active et incoming (non, on ne compte pas corrupt).
Globalement, ça se passe comme ça:
- Le script
/usr/bin/postfix
start lance le serveur. - Puis le script lance /usr/libexec/postfix/master`, lui c’est le patron et il lancera les autres démons, uniquement si nécessaire.
- Les démons se terminent dès qu’ils ont fini ce qu’il ont à faire, sauf
/usr/libexec/postfix/qmgr
qui lui, reste actif tout le temps, il gère les différentes files d’attente.
On s’arrête un peu sur le patron de la file d’attente et les démons associés, j’ai nommé qmgr
pour queue manager. Son patron à lui, c’est master
, qui coordonne tous les démons de Postfix, il attend qu’une tâche arrive et les donne aux processus concernés, aussi, il effectue un contrôle sur le nombre d’instances qui s’exécutent concurremment (on revient sur la concurrence plus loin dans l’article).
Le démon qmgr
Le gardien des couloirs de Postfix. Il gère toutes les files d’attente de Postfix et orchestre le travail de chacun et notamment des démons local
, smtp
, lmtp
et pipe
en veillant à diverses choses comme la préservation des ressources et au maintien de la stabilité du système.
Par exemple, sur des messages dont le traitement n’aboutit pas, qmgr
ordonne de placer ledit message dans la file deferred
. Ainsi, en utilisant une file séparée, cela évite les incidences sur la file de délivrance des messages.
Le démon pickup
Il est responsable de la récupération des courriers locaux. En gros, sendmail
pose les messages dans la file maildrop
et pickup
les récupère, effectue quelques vérifications et passe le message au démon cleanup
.
Attention, pickup
est mono-thread, il ne peut donc que livrer un message à la fois et sa vitesse se limite aux capacités de lecture/écriture du disque.
Le démon cleanup
Il fait les derniers traitements sur les messages, comme ajouter des entêtes manquants nécessaires, assurer les réécritures de l’enveloppe et des entêtes. Une fois fait, il met le résultat de tout ça dans la file incoming
et indique au démon qmgr
l’arrivée de nouveaux messages.
Les démons bouce et deferred
Eux, ils interviennent sur les messages qui n’ont pas pu être délivrés pour deux raisons possibles: une erreur non récupérable ou une destination inaccessible (même temporairement). Comme indiqué plus haut, ces erreurs sont reçues par qmgr
qui ordonne par la suite le démon bounce
et le démon defer
(à ne pas confondre avec la liste !).
On va s’arrêter là pour les démons, ça devrait nous suffire pour comprendre la suite de l’article. Maintenant, on passe aux différentes files d’attente et ensuite on verra comment assurer la gestion de ces files via quelques outils.
La file Maildrop
Plus haut, nous avons parlé de pickup
, ce gentil démon qui récupère les messages de la file maildrop
pour les passer à son pote démon cleanup
. Et bien la file maildrop
sert à ça, elle met en attente les message soumis via sendmail
mais pas encore déposés dans la file d’attente principale par pickup
.
Si on regarde le diagramme plus haut, on voit qu’entre sendmail
et maildrop
, il y a postdrop
. Il permet à n’importe quel utilisateur du système de soumettre un message dans la file d’attente maildrop
, traité indifféremment des autres par pickup
.
Si ça ne vous plait pas plus que ça, vous pouvez restreindre ce comportement grâce à une ligne de configuration nommée
authorized_submit_users
dans le fichier de configuration/etc/postfix/main.cf
car par défaut, la valeur est àstatic:anyone
.
Des messages peuvent être ajoutés à cette file même si Postfix ne fonctionne pas, il seront tout simplement pris en charge au prochain démarrage de Postfix.
La file active
En vert sur le diagramme plus haut. Accrochez vous, ça risque de piquer un peu !
La file active stocke les messages qui sont prêts à être envoyés. C’est qmgr
qui gère la chose encore une fois. Seul un nombre réduit de messages est autorisé à entrer dans cette file par qmgr
pour garder un taux de livraison stable. C’est l’algorithme du seau percé (leaky bucket en anglais) qui est appliqué pour garder ce taux constant. Son fonctionnement est très simple, surtout via cette analogie (d’où le nom de l’algorithme):
- On considère un seau d’un volume quelconque (réduit, en ce qui concerne la file
active
) - La taille du seau correspond à la taille totale des informations qu’il peut contenir
- Si le volume d’information dépasse la taille totale du seau, l’information en trop est rejetée (ça déborde). Dans notre cas,
qmgr
passera le message à l* file d’attentedeferred
Forcément, si on remplit le seau autant qu’il se vide, c’est juste parfait, et le taux restera constant. Par contre, si on a une destination d’un message qui est considérée comme morte, et que la file s’allonge beaucoup trop (ce qu’on nomme congestion), qmgr
enlèvera de la file tous les message ayant cette destination. Si cette destination est juste ralentie, qmgr
garde les mails, mais la file se remplira plus vite qu’elle ne se vide. Dans ce cas, la seule manière de décongestionner la file est soit de réduire ce qui entre dans la file, soit d’accélérer ce qui en sort en agissant sur la latence (donc on a un peu de mal à agir dessus) ou en agissant sur la concurrence.
Pour faire simple, la concurrence c’est quand plusieurs entités souhaitent accéder à une ressource unique. En informatique générale c’est quand plusieurs processus souhaitent accéder à une ressource en même temps, le principe de l’exclusion mutuelle permet d’éviter de mettre des processus en concurrence via différents moyens, comme des verrous sur les ressources utilisées par exemple.
Pour Postfix, la concurrence se règle dans les fichiers de configuration. Par exemple (et je n’en donnerais qu’un car il y a énormément de paramétrages de ce type dans Postfix) la ligne de configuration local_destination_concurrency_limit
qui est fixée par défaut à 2
indique le nombre maximum de livraisons parallèles via le transport local au même destinataire ou le nombre maximum de livraisons parallèles au même domaine local si la ligne local_destination_recipient_limit
est supérieur à 1
(1
par défaut).
Ça va, ça suit ?
La file incoming (entrante)
Aussi nommée file entrante. On l’a rapidement abordé quand on parlait du démon cleanup
, il réécrit ce qu’il faut (enveloppe et entêtes) et transmet à la file entrante. Le fichier est créé par l’utilisateur postfix
(utilisateur système hein) avec des droits d’accès 0600
, cleanup
fait son boulot, et quand c’est prêt, il change les droits en 0700
et dit à son patron qmgr
qu’il y a un nouveau venu dans la file incoming
. Tant que les droits du fichier ne sont pas à 0700
, qmgr
, borné, part du principe que le fichier est encore en traitement par cleanup
et par conséquent ne s’en occupe pas.
qmgr
garde un oeil sur la file entrante et transmet les nouveaux messages à la file active uniquement si la limite de la file active n’est pas dépassée (20k messages). Si toutefois qmgr
a trop de boulot, cleanup
attendra la valeur du paramètre in_flow_delay
dont la valeur par défaut est 1
. Pour la désactiver il faut indiquer 0
. Vous pouvez monter jusqu’à 10
secondes si vraiment la situation est mauvaise.
La file deferred (retardée)
Si à un instant T la livraison échoue pour une raison temporaire, le message est placé dans la file deferred
. Cette file est guettée relativement souvent par qmgr
. Quand je dis «souvent» c’est relatif, mais surtout lié au paramètre queue_run_relay
initialisé à 300
s par défaut (1000
dans Postfix 2.4).
Si toutefois qmgr
est amené à scruter la file incoming
et la file deferred
en même temps, il respecte son principe d’économie de ressources mais d’efficacité, il scrute les deux en appliquant l’algorithme d’ordonnancement round-robin.
Le round-robin est un algorithme d’ordonnancement sans priorité.
qmgr
s’occupera de la fileincoming
pendant N temps puis de la filedeferred
pendant N temps et ainsi de suite, sans appliquer aucune priorité ou distinction.
Aussi, vous pouvez jouer avec le paramètre maximal_backoff_time
qui, par défaut, attend 4000
s entre deux tentatives de livraison d’un message présent dans la file deferred
.
La file hold
Celle ci est un peu particulière dans le sens où c’est vous qui positionnez les messages dedans en mettant en place dans votre configuration de Postfix différentes politiques d’accès ou d’examens supplémentaire des entêtes ou du corps des messages par cleanup
.
Cette file est un peu particulière car elle ne sera pas examinée pour essayer de livrer les messages qu’elle contient. Il faut que ça soit obligatoirement l’administrateur qui traite ces messages.
Bon, maintenant qu’on sait ce que sont les files d’attente, on va voir divers outils et commandes pour les traiter !
Commandes de traitement des files
Elles sont logiques, donc je ne vais pas lister tous les cas de figures, mais vous montrer des exemples que vous pouvez adapter simplement pour trouver ce que vous voulez:
Pour compter le nombre de mails dans la file active, on préférera utiliser la commande find
, couplée à un wc
comme ceci (à lancer en root):
find /var/spool/postfix/active -type f | wc -l
Pour compter deux files, comme la deferred
et la hold
, il suffit de cumuler les emplacements dans la commande comme ceci:
find /var/spool/postfix/deferred /var/spool/postfix/hold -type f | wc -l
L’outil Qshape
Inutile de le chercher, cet outil vient en installant Postfix. Cet outil montre une vue de la file d’attente sous forme de tableau (le temps en horizontal et les domaines de destination en vertical (ou les domaines d’expédition avec l’option -s
)) et dispose de quelques options.
Pour voir le tableau de la file active:
qshape active
Je vous conseille de piper ces commandes avec des head
(qui affiche 10 entrées par défaut) ou less
. Par exemple, pour les 10 premières entrées de la file deferred
, c’est comme ça:
qshape deferred | head
Postfix permet de base de visualiser la file d’attente via cette commande:
postqueue -e
L’avantage, c’est qu’elle vous donne l’ID des mails utilisé dans les commandes suivantes.
Postsuper
Lui, il gère les files d’attentes et peut interagir sur un mail en utilisant son ID de queue. Quelques exemples:
Effacer un mail actuellement dans une des queues:
postsuper -d ID_DU_MAIL
Déplacer un mail dans la file hold
:
postsuper -h ID_DU_MAIL
Supprimer tous les mails de toutes les files d’attente (utilisé très rarement, tous les mails seront perdus définitivement).
postsuper -d ALL
Fin
Voilà en ce qui concerne les démons et les files d’attente ! J’espère que vous y voyez plus clairs dans le grand centre de distribution du courrier qu’est Postfix !