1. 程式人生 > >Java經驗雜談(1.記PostFix郵件發送性能與有效發送問題)

Java經驗雜談(1.記PostFix郵件發送性能與有效發送問題)

批量 圖片 業務 有效 客戶 每天 隊列 客戶端 解鎖

業務需求:

需要定期給註冊會員發送廣告,問卷等郵件,每天需要完成百萬級的郵件發送。

服務器:
若幹臺postfix服務器

遇到問題:
對於每天百萬級的郵件發送任務,postfix服務器很容易完成,Java客戶端包含發送時的業務邏輯處理時間,多起幾個線程也很容易做到。
但是,如果發送速度過快,會被郵件服務商列入黑名單而拒收郵件,而每個郵件服務商對接收郵件的速度要求又不一樣。

解決方法:
這樣,需要針對每個郵件批量發送任務,按照每個郵件服務商能接收的速度來發送郵件。
比如,163每秒3封,sina每秒4封等。

於是我們設計了如下結構的郵件發送系統:

技術分享圖片

用Redis存儲每個域名最後的發送時間,

重復a,b
    a) 獲得並鎖住可發送的域名。
    b) 針對每一個可發送域名,
      1. 如果相應的域名隊列中存在待發送郵件,則發送並更新改域名的最後發送時間。
      2. 解鎖該域名發送記錄。

這樣,對郵件隊列采用非阻塞隊列,提高了系統的並發性。

看似解決了問題,但還是被部分服務商列入了黑名單。

於是對系統進行分析,如下:
這是一個典型的生產者與消費者問題,Java客戶端生產的郵件定時推送到Postfix隊列,然後Postfix消費隊列上的郵件,發送到目標郵件服務器。
生產一封,發送一封的話,不會有任何問題,但如果隊列中存在多封,那麽向目標郵件服務器投送的速度就無法控制了。

於是檢查postfix隊列:
postqueue -p

發現確實堆積了一些郵件。
原因:系統運行中,某一封郵件發送的延遲會導致後面的郵件發送都被延遲。

處置方法:
在Java端進行發送速度的控制顯然是治標不治本的,於是用Java端同樣的邏輯修改PostFix中郵件發送的代碼,
用同樣的配置文件,最終從根本上解決了控制郵件發送速度的問題。

Java經驗雜談(1.記PostFix郵件發送性能與有效發送問題)