2016-10-06 1 views
1

Context

Lieber Knot Resolver Benutzer, ich habe eine module that hooks into Knot'sfinish Phase,Knoten Resolver: paralelism und Parallelität in Module

static knot_layer_api_t _layer = { 
    .finish = &collect, 
}; 

der Zweck der collect Funktion static int collect(knot_layer_t *ctx) { ist eine externe oraculum über ein fragen, REST API, ob eine bestimmte Domain zur Aufnahme einer Malware- oder Phishing-Kampagne aufgeführt ist und ob sie aufgelöst oder versenkt werden sollte.

Es funktioniert gut, solange Knot Resolver nicht mit Hunderten von gleichzeitigen DNS-Anforderungen ausgerichtet ist. Wenn dies passiert, beginnen die Clients aufgrund der Tatsache, dass die API-Reaktionszeit des Orakulums schwankt und manchmal bis zu mehreren hundert Millisekunden reicht, sehr lange Antwortzeiten von Knot Resolver, die das festgelegte harte Zeitlimit weit überschreiten Kommunikation zu Oraculums API.

Mögliches Problem

Ich denke, dass das scaling-with-processes tatsächlich das Modul sehr ineffizient implementiert macht, da Abfragen von Modul eins nach dem anderen (in einem bestimmten Prozess) der Warteschlange und verarbeitet werden. Das heißt, wenn n Abfragen fast-Treffer Oraculum API-Timeout-Limit t, der Client , die seine n+1 Abfrage an diesen bestimmten Kresd-Prozess gesendet hat, wird eine sehr lange Reaktionszeit von akkumulierten wahrnehmen.

Oder würde es? Bin ich komplett ausgeschaltet?

Als ich ähnliche Funktionalität in GoDNS mit goroutines Prototyping, GoDNS-Server (auf Kosten der scheußlichen CPU-Nutzung) ließ zahlreiche Anfragen der DNS-Clients mit dem Orakulum sprechen und an Clients "gleichzeitig" zurück.

Frage

  • Ist es O.K. Apache Portable Runtime-Threading oder OpenMP-Threading zu verwenden und die Reaktionszeit der API im Modul zu verbergen? Ist es nicht ein komplettes Knot Resolver Antipattern?
  • Ich Caching Oraculum API-Antworten in einem einfachen im Speicher ephemeren LRU-Cache, der in jedem Kresd-Prozess befindet. Wäre es möglich, stattdessen Kresds eigenen MVCC-Cache für meine willkürliche Struktur zu verwenden?
  • Ist es möglich, dass das Problem anderswo ist, zum Beispiel, dass Knot Resolver keine Sperrverzögerung in finish Ebene erwartet und somit einige Netzwerkwarteschlange gefüllt ist und nachfolgende DNS-Abfragen abgelehnt und/oder untragbar verzögert werden?

Dank für Zeiger (pun intended) hier

Antwort

1

A Knot Resolver Entwickler hier :-) (ich wiederhole auch einige von Jan beantwortet Dinge schon.)

  • Scaling-mit-Prozesse der Lage ist, gut zu funktionieren. Warten auf Antworten von Nameservern erfolgt über libuv (über Event-Loop und Callbacks, alle innerhalb eines Threads).
  • Aufgrund des Single-Thread-Stils sollte keine Layer-Funktion blockiert werden (auf I/O), da dies alles blockieren würde. AFAIK ist derzeit der einzige Fall, in dem dies wirklich passieren kann, wenn (teilweise) der Cache ausgelagert wird.
  • Es gibt den YIELD-Status http://knot-resolver.readthedocs.io/en/latest/lib.html?highlight=yield Es wird verwendet, wenn eine Unteranforderung erforderlich ist, bevor die Verarbeitung der Schicht fortgesetzt werden kann, aber ich weiß derzeit nicht, Details der Arbeit. Ich denke nicht, dass es direkt anwendbar ist, denn das Wiederaufnehmen der Ebenen scheint momentan nur durch eine Unteranfragenbearbeitung ausgelöst zu werden.
  • Cache: Wenn Sie Ihr Modul vor dem rrcache-Modul platzieren und den RRset ändern, wird es bereits zwischengespeichert.
1

Knot DNS-Entwickler (nicht obwohl Melders). Ich glaube, Du hast recht. Nach meinem Verständnis wird der Layer-Code synchron im Daemon-Thread ausgeführt. Die Asynchronität wird nur auf der Resolver-Netzwerk-E/A-Ebene angezeigt.

Intern führt der Server eine libuv-Schleife aus, die nur Callbacks für Ereignisse auf Basis von libuv ausführt (Sockets, Timer, Signale, etc.). Das Problem ist, dass Sie den laufenden Callback (C-Funktion) nicht an einem beliebigen Punkt anhalten können, zurück in die libuv-Schleife gelangen und die Callback-Ausführung zu einem späteren Zeitpunkt fortsetzen können.

Das heißt, asynchrones Warten auf ein Ereignis kann nur dort stattfinden, wo dies erwartet wurde. Und die Code-treibenden Schichten erwarten das nicht.

Antworten:

  • Ich bin mit libapr oder OpenMP nicht sehr vertraut. Aber ich denke nicht, dass dies wirklich gelöst werden könnte, ohne die Layer-Schnittstelle zu überarbeiten und asynchron zu machen.

  • Der freigegebene Cache konnte sicher verwendet werden. Wenn Sie die API nicht finden können, werden Jolly Knot DNS-Leute gerne einen Patch akzeptieren oder Ihnen beim Schreiben helfen.

  • Dies ist genau der Fall. Knot Resolver erwartet keinen Blockierungscode im Callback der Ebene.