8

我已經構建了一個應用程序,通過Amazon SES爲網站發送電子郵件郵件。它用C#編碼。多線程加速電子郵件發送應用程序

每封電子郵件需要0.3秒才能通過Amazon SES API發送。這意味着,使用單線程應用程序,我只能每秒發送3封電子郵件。

我實現了一個生產者/消費者,多線程應用程序與1個生產者查詢定製電子郵件爲每一個客戶,和25消費者從隊列中提取併發送電子郵件。

我的多線程應用程序每秒發送12個電子郵件(四倍速度增加)。我預計25線程應用會提高速度。

我的問題是: 多少錢我可以真的加快發送郵件在單處理器機器?我的收益看起來是否合理,還是我的速度問題更可能是由於編碼而非計算機無法快速處理電子郵件?

在此先感謝!

UPDATE:如果其他人遇到同樣的問題....連接到AWS以發送電子郵件需要很長時間。 AWS Developer論壇上的以下主題提供了一些見解(您可能需要向下滾動才能看到更有用的帖子)。

https://forums.aws.amazon.com/thread.jspa?threadID=78737

+0

從我對多線程的理解來看,它可以處理多個任務,但仍然需要相同的時間。所以我不認爲使用多線程會節省大量時間。但是,如果在電子郵件發送時UI仍然需要可訪問,則可以使用多線程。 – craig1231 2012-01-01 23:13:57

+0

您的系統中有多少個核心? – Tudor 2012-01-01 23:14:23

+0

在典型的郵件過程中,隊列計數會發生什麼情況?查看生產者線程是否超出電子郵件發件人或不是。也許每隔一秒將P-C隊列計數轉儲到計時器的屏幕上。 – 2012-01-02 02:36:48

回答

2

我的問題我s:我能在單處理器機器上加快發送郵件程序 多少錢?我的收益看起來是否合理,或者我的 速度問題更可能是由於編碼而不是計算機的 無法更快處理電子郵件?

從廣義上講,線程數增加25倍的4倍加速並不算離譜,但也不算太好。

當CPU使用率很高時,單個CPU只會成爲瓶頸。您可以通過查看應用程序運行時的總CPU使用情況來判斷這是否是一個問題。理論上,發送大量電子郵件應該是I/O限制操作;如果這不是你的情況,那麼你的代碼可能有問題。

儘管我沒有使用亞馬遜SES,但我知道其他亞馬遜產品絕對使用各種形式的帶寬/請求限制。亞馬遜可能(可能)會限制您的吞吐量,而不是您的應用程序。

我寫了一個高性能的羣發郵件應用程序而回,而我所做的是:

  1. 二手異步I/O儘可能地,除了多線程。這樣,如果一個請求很慢,它不會佔用整個線程。
  2. 直接發送電子郵件到終端服務器,而不是通過中間網關。這需要使用P/Invoke來調用DNS來檢索必需的MX或A記錄。之後,我使用標準的SmtpClient類(其具有SendAsync方法)實際發送郵件。

這種方法還可以讓我在發送郵件時看到並記錄錯誤,從而爲用戶提供更好的反饋。另一種方法是依賴於從網關服務器接收並解析錯誤郵件,這很容易出錯,至少可以這樣說。

+0

+1 - 到目前爲止,這是最能解決問題並提供最詳細和具體信息的答案。謝謝!將嘗試一些這些建議,並返回到此線程發佈結果! – Rebecca 2012-01-03 16:58:47

1

在對多核(或多處理器)上運行多線程應用系統中的黃金法則是,(一般)不能達到比N次的順序執行的時間,其中N是一個更好的加速核心數量。所以如果你有一個活動需要12秒,並且你在4個核心上並行運行它,你總共不會超過3秒。

相反,如果以前你可以在單個時間單位執行一項活動,4個核心,你不能在相同的時間單位做的更好,然後4個活動。

此外,該上限並不總是能夠達到由於幾個因素,其通常影響並行程序的性能:磁盤I/O瓶頸,存儲器飽和,鎖爭用等

+1

那麼這隻適用於CPU有限的問題。即我已經編寫了並行查詢服務器的代碼,比核心數量有更高的加速比(還使用更多的線程)。但沒有一些分析瓶頸的地方,我們沒有太多的可以說.. – Voo 2012-01-01 23:22:12

+1

這個回答不適用於OP的情況。 – 2012-01-02 00:28:07

1

生產者消費者只用一個隊列沒有很好的規模。添加更多消費者或生產者時,隊列成爲瓶頸。

如果你有多處理器架構,您可以使用多個進程來發送電子郵件。你仍然可以使用你的生產者消費者多線程版本,但現在它將成爲一個foreach過程;這會加快速度(正如Tudor解釋的),但問題仍然存在。

然而,你可能有,對於整個系統,只有一個發送郵件(比如HTTTP消息)網絡管理器或類似實體和一個網卡。現在瓶頸可能是這位網絡管理員。我想知道更多關於系統:)

+0

與用於設置TCP連接和發送電子郵件的I/O時間和等待時間相比,在P-C隊列活動上花費的時間並不重要。如果隊列操作成爲這個應用程序的瓶頸,我會很驚訝。 – 2012-01-02 02:30:36

+0

你不能保證生產者不需要很多時間。我同意你,有可能網絡管理員是一個瓶頸。然而問題仍然是排隊方法不能很好地滿足消費者和消費者的需求 – Adrian 2012-01-02 03:27:05

+0

似乎生產者與消費者相比很快完成......這似乎並不是瓶頸,而是一個好點。 – Rebecca 2012-01-03 19:36:46

4

可以加快很多,即使它的單處理器計算機的體系結構。

發送電子郵件確實消耗大量的CPU ,它是一個IO約束操作。 因此,通過並行地完成工作,您將會提高您的表現。

+0

+1,即使單線程處理器上有很多線程I/O等待,也可以大幅加速。 – 2012-01-02 02:27:22

+0

你如何建議並行工作? – 2012-01-02 21:17:34

+0

@SurjitSamra - 不知道你在問什麼。他使用了我不熟悉的一些亞馬遜API。 – Maxim 2012-01-02 22:56:05

-2

如何評論說,這是一個I/O問題,因爲,你需要找到一個很好的任務數與紅外/帶寬大小

使用隊列模式,

例子:

1 - 一個排隊投遞郵件

2 - 「N」 作業調度電子郵件

+1

這沒有多大意義。 – Lloyd 2012-01-02 01:37:48

0

幾個月前,我的情況相似。儘管我們需要很多因素才能告訴您導致性能較低,但您可以嘗試使用EC2實例的mirco實例嘗試發送電子郵件。

事實證明,在我的情況下工作得很好,而且在我正在開發Web應用程序時這是一個合適的解決方案。

3

我博客瞭解我的解決方案。基本上你用一個Parallel.ForEach循環與MaxDegreeOfParallelism,不要忘記增加計數在app.config

下面是app.config樣本:

<system.net> 
    <connectionManagement> 
     <add address="*" maxconnection="392" /> 
    </connectionManagement> 
    <mailSettings> 
     <smtp from="[email protected]" deliveryMethod="Network"> 
      <network host="email-smtp.us-east-1.amazonaws.com" userName="SmtpUsername" password="SmtpPassword" enableSsl="true" port="587" /> 
     </smtp> 
    </mailSettings> 
</system.net> 

這裏是Parallel.ForEach循環樣本:

class Program 
{ 
    static readonly object syncRoot = new object(); 
    private readonly static int maxParallelEmails = 196; 

    static void Main(string[] args) 
    { 

     IList<Model.SendEmailTo> recipients = _emailerService.GetEmailsToSend(); 
     int cnt = 0; 
     int totalCnt = recipients.Count; 


     Parallel.ForEach(recipients.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = maxParallelEmails }, recipient => 
     { 
      // Do any other logic 

      // Build the email HTML 

      // Send the email, make sure to log exceptions 

      // Track email, etc 

      lock (syncRoot) cnt++; 
      Console.WriteLine(String.Format("{0}/{1} - Sent newsletter email to: {2}", cnt, totalCnt, recipient.Email)); 
     }); 
    } 
} 

我的博客解釋了它的詳細信息:http://michaeldimoudis.com/blog/2013/5/25/reliably-and-speedily-send-mass-emails-via-amazon-ses-in-c

0

的任務既不是CPU綁定,也不受IO限制。 該任務向SES發送一封電子郵件(帶有限數據或IO),然後等待。因此,使用可用RAM的最大線程數。

相關問題