2016-05-24 12 views
1

Ich habe einen Prozess, der Ergebnisse von Hunderten von Abfragen in 5 verschiedenen Datenbanken in eine Datei auf der Festplatte mit einem Producer-Consumer-Muster streamt. Die Abfragen und Verbindungen funktionieren alle, wenn sie sequenziell ausgeführt werden (oder wenn ich sie kontinuierlich wiederhole). Wenn sie jedoch mit Threads versehen werden, schlagen einige der Verbindungen fehl.Verbindungsfehler zu PostgreSQL beim Multithreading. C#

Ich füge gerade fehlgeschlagene Versuche zu einer fehlgeschlagenen Sammlung hinzu und führe sie dann rekursiv erneut, so dass sie schließlich alle enden, aber viel Zeit wird mit diesen fehlgeschlagenen Verbindungen verschwendet.

Hier ist der relevante Code verwende ich:

public void executeNodes(List<Node> nodeList, BlockingCollection<Dictionary<string, object>> producer, int retryAttempts) { 
     BlockingCollection<Node> retryNodes = new BlockingCollection<Node>(); 
     Parallel.ForEach(nodeList, new ParallelOptions() { MaxDegreeOfParallelism = 10 }, node => { 
      NpgsqlConnection conn = new NpgsqlConnection(node.ConnectionString); 
      try { 
       conn.Open(); 
       NpgsqlCommand npgQuery = new NpgsqlCommand(node.Query, conn); 
       NpgsqlDataReader reader = npgQuery.ExecuteReader(); 
       while (reader.Read()) { 
        Dictionary<string, object> row = new Dictionary<string, object>(); 
        for (int i = 0; i < reader.FieldCount; i++) { 
         row[reader.GetName(i)] = reader.GetValue(i); 
        } 
        producer.Add(row); 
       } 
       conn.Close(); 
       //Console.WriteLine("Success"); 
      } catch (Exception e) { 
       //Console.WriteLine("Failed"); 
       retryNodes.Add(node); 
      } 
     }); 
     if (retryNodes.Count == 0 || retryAttempts == 0) producer.CompleteAdding(); 
     else executeNodes(retryNodes.ToList<Node>(), producer, retryAttempts - 1); 
    } 

Wenn ein Knoten einfach ist:

public class Node { 
    public string ConnectionString; 
    public string Query; 

    public Node(string connectionString, string query) { 
     ConnectionString = connectionString; 
     Query = query; 
    } 
} 

Dieser Prozess wird erfolgreich und korrekt ausgeführt werden, aber es ist ärgerlich, dass ich Verbindung bin immer Fehler. Jede Hilfe würde sehr geschätzt werden.

Hinweise:

ich Zugabe versucht:

ServicePointManager.DefaultConnectionLimit = 20; 

ich versucht habe, Registry-Einträge hinzufügen specified in this page

Die Verbindungsfehler sind nicht aufgrund der Verbindungspool nicht erreicht.

Die Fehler ich sehe sind:

"Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond." 
+0

Nach wie vielen Verbindungen sehen Sie Probleme? Sie sind sicher, dass der Pool genutzt wird und Ihnen nicht die vergänglichen Ports ausgehen? – 9Rune5

+0

Also habe ich die Anzahl der Knoten auf 10 begrenzt, wobei eine davon zu einer Datenbank gehört und die andere zu einer anderen. Jedes Mal, wenn ich die erste Verbindung leite, ist es immer ein Erfolg, aber dann scheinen alle anderen fast zufällig zu sein, wenn sie erfolgreich sind oder nicht. Manchmal arbeiten 6/10 manchmal nur die erste Arbeit. Weißt du, wie ich die Anzahl der verfügbaren ephemeren Ports überprüfen kann? Edit, Gerade lief wieder und nur die erste fehlgeschlagen und der Rest war erfolgreich, so dass vorherige Aussage teilweise falsch war. –

+0

Die Anzahl der TCP-Ports zählt zu Tausenden. Wenn Sie nach nur wenigen Verbindungen Probleme haben, dann vergessen Sie meinen Kommentar. – 9Rune5

Antwort

1

So war mein Problem mit Connection Pooling. Sobald ich es in der Verbindungszeichenfolge auf false gesetzt habe, hat alles funktioniert.