Multi-Threading zum Beschleunigen einer E-Mail-sendenden Anwendung

8

Ich habe eine Anwendung entwickelt, um E-Mail-Mailer für eine Website über Amazon SES zu senden. Es ist in C # codiert.

Jede E-Mail dauert 0,3 Sekunden, um sie über die Amazon SES-API zu senden. Das heißt, mit einer Single-Thread-Anwendung kann ich nur 3 E-Mails pro Sekunde senden.

Ich habe eine Producer / Consumer, Multithread-Anwendung mit einem Producer implementiert, um die E-Mails für jeden Kunden anzupassen, und 25 Konsumenten, die aus der Warteschlange ziehen und die E-Mails senden.

Meine Multithread-Anwendung sendet 12 E-Mails pro Sekunde (eine vierfache Geschwindigkeitssteigerung). Ich hätte von einer 25-Thread-Anwendung eine höhere Geschwindigkeit erwartet.

Meine Frage ist: Wie viel kann ich wirklich beschleunigen das Senden eines Mailers auf einem Single-Prozessor-Maschine ? Erscheint mein Gewinn vernünftig, oder ist mein Geschwindigkeitsproblem wahrscheinlicher aufgrund der Codierung als aufgrund der Unfähigkeit des Computers, die E-Mails schnell zu verarbeiten?

Vielen Dank im Voraus!

UPDATE: Für den Fall, dass andere das gleiche Problem haben ... Die Verbindung zu AWS, um die E-Mail zu senden, nimmt viel Zeit in Anspruch. Der folgende Thread in AWS Developer-Foren gibt einige Einblicke (Sie müssen möglicherweise einen Bildlauf nach unten durchführen, um zu den nützlicheren Posts zu gelangen).

Ссылка

    
Rebecca 01.01.2012, 23:08
quelle

8 Antworten

2
  

Meine Frage ist: Wie viel kann ich den Versand eines Mailers wirklich beschleunigen?   auf einer Single-Prozessor-Maschine? Sind meine Gewinne vernünftig oder meine?   Geschwindigkeitsproblem eher aufgrund der Codierung als der des Computers   Unfähigkeit, die E-Mails schneller zu verarbeiten?

Allgemein gesprochen ist eine 4x-Beschleunigung für eine 25-fache Erhöhung der Thread-Anzahl nicht unverschämt, aber auch nicht großartig.

Eine einzelne CPU wird nur dann ein Engpass, wenn Ihre CPU-Auslastung hoch ist. Sie können feststellen, ob dies ein Problem für Sie darstellt, indem Sie sich die Gesamt-CPU-Auslastung bei laufender App ansehen. Theoretisch sollte das Senden von Massen-E-Mails eine E / A-beschränkte Operation sein. Wenn dies für Sie nicht der Fall ist, kann Ihr Code Probleme haben.

Obwohl ich Amazon SES noch nicht verwendet habe, weiß ich, dass andere Amazon-Produkte definitiv verschiedene Formen der Bandbreiten- / Anfragedrosselung verwenden. Es ist möglich (wahrscheinlich), dass Ihr Durchsatz mehr von Amazon als von Ihrer App begrenzt wird.

Ich habe vor einiger Zeit eine leistungsstarke Massenmail-App geschrieben, und was ich getan habe, war:

  1. Async-E / A wurde so weit wie möglich zusätzlich zu mehreren Threads verwendet. Wenn eine Anfrage langsam ist, wird auf diese Weise kein gesamter Thread verbraucht.
  2. Senden Sie die E-Mail direkt an die Endserver und nicht über ein intermediäres Gateway. Dazu musste P / Invoke verwendet werden, um DNS aufzurufen, um die erforderlichen MX- ​​oder A-Datensätze abzurufen. Danach habe ich die Standardklasse SmtpClient verwendet (die eine Methode SendAsync hat), um die Mail tatsächlich zu senden.

Dieser Ansatz ermöglicht es mir auch, Fehler beim Senden der E-Mail zu sehen und aufzuzeichnen, was wiederum den Benutzern ein besseres Feedback gibt. Die Alternative besteht darin, sich auf das Empfangen und Parsen von Fehler-E-Mail vom Gateway-Server zu verlassen, was zumindest fehleranfällig ist.

    
RickNZ 02.01.2012, 04:35
quelle
4

Sie können sehr viel beschleunigen, obwohl es ein Einzelprozessor ist.

Beim Senden einer E-Mail verbraucht nicht viel CPU , es handelt sich um eine E / A-gebundene Operation. Daher steigern Sie Ihre Leistung sehr, indem Sie parallel arbeiten.

    
Maxim 01.01.2012 23:34
quelle
3

Ich habe über meine Lösung gebloggt. Grundsätzlich verwenden Sie eine Parallel.ForEach Schleife mit einem MaxDegreeOfParallelism , vergessen Sie nicht, die maxconnection Anzahl in app.config zu erhöhen.

Unten ist das app.config Beispiel:

%Vor%

Und hier ist das Parallel.ForEach loop sample:

%Vor%

Mein Blog erklärt es ausführlicher: Ссылка

    
dimoss 03.06.2013 05:44
quelle
1

In einer Multithread-Anwendung, die auf einem Multi-Core- (oder Multiprozessor-) System ausgeführt wird, ist die goldene Regel, dass Sie im Allgemeinen keine bessere Beschleunigung erreichen als N mal die sequentielle Ausführungszeit, wobei N die Anzahl der Kerne ist. Wenn also eine Aktivität 12 Sekunden dauert und Sie parallel auf 4 Kernen laufen, können Sie insgesamt nicht mehr als 3 Sekunden machen.

Umgekehrt, wenn Sie zuvor eine Aktivität in einer einzigen Zeiteinheit ausführen konnten, können Sie mit 4 Kernen nicht mehr als 4 Aktivitäten in derselben Zeiteinheit ausführen.

Darüber hinaus wird diese obere Grenze nicht immer aufgrund mehrerer Faktoren erreicht, die die Leistung von parallelen Programmen generell beeinflussen: Festplatten-E / A-Engpässe, Speichersättigung, Sperrkonflikte, etc.

    
Tudor 01.01.2012 23:16
quelle
1

Producer Consumer mit nur einer Warteschlange skaliert nicht gut. Die Warteschlange wird zum Engpass, wenn Sie weitere Konsumenten oder Produzenten hinzufügen.

Wenn Sie eine Multiprozessorarchitektur haben, können Sie mehrere Prozesse zum Senden von E-Mails verwenden. Sie können weiterhin Ihre Multithread-Version für Producer Consumer verwenden, aber jetzt wird es ein einziger Prozess sein; das wird die Dinge etwas beschleunigen (wie Tudor erklärt hat), aber das Problem bleibt bestehen.

Sie haben jedoch möglicherweise für das gesamte System nur einen Netzwerkmanager oder eine ähnliche Entität, die die Nachrichten (z. B. htttp-Nachrichten) und eine Netzwerkkarte sendet. Jetzt könnte der Flaschenhals dieser Netzwerkmanager sein. Ich möchte mehr über die Architektur des Systems wissen:)

    
Adrian 01.01.2012 23:23
quelle
0

Ich war vor ein paar Monaten in einer ähnlichen Situation. Obwohl es viele Faktoren gibt, die wir benötigen, um Ihnen zu sagen, welches die geringere Leistung verursacht, können Sie versuchen, mit einer mirco-Instanz der EC2-Instanz zu versuchen, E-Mails zu senden.

Das hat in meinem Fall gut funktioniert, und es war eine geeignete Lösung, als ich an der Webanwendung arbeitete.

    
Mr Programmer 04.04.2013 09:49
quelle
0

Die Task ist weder CPU-gebunden noch IO-gebunden. Die Task fordert SES auf, eine E-Mail zu senden (mit begrenzten Daten oder IO) und wartet dann. Verwenden Sie also die größte Anzahl von Threads, die Sie für den verfügbaren Arbeitsspeicher verwenden können.

    
EmailSenderAWS 30.01.2017 01:27
quelle
-2

Wie kommentiert, das ist ein I / O-Problem, weil Sie eine gute Anzahl von Jobs mit infra / Bandbreite Größe finden müssen

Verwenden Sie ein Warteschlangenmuster,

Beispiel:

1 - Verteilen Sie eine Zustellungs-E-Mail

2 - "N" Jobs versenden die E-Mail

    
Renato Elias 02.01.2012 01:29
quelle