1. 程式人生 > >記錄一次不能傳送郵件故障處理

記錄一次不能傳送郵件故障處理

伺服器使用的是萬網的vps,郵件伺服器是阿里雲郵箱。今天發現不能傳送郵件。
1:編寫測試程式碼,傳送過程中,發現出現服務超時。我沒有伺服器管理許可權,處理起來比較棘手。
這裡寫圖片描述

2:經過百度搜索,發現阿里雲伺服器是禁止25埠傳送郵件的。
我們使用的是萬網vps,可能近期也封禁25 傳送郵件埠了。目前搜尋發現的一個方案是,使用80埠,馬上動手試驗:
這裡寫圖片描述

將埠變更會80,預設的使用的是25

3:經過測試,程式碼執行不在報錯,並且已經收到了郵件。
這裡寫圖片描述
如上圖所示,程式碼沒有報超時錯誤

這裡寫圖片描述
如上圖所示,伺服器上收到了郵件。

4:不穩定,可能和網速有關,傳送郵件耗時較多,一般需要1秒左右,最高5.7秒。影響使用者體驗。當然徹底解決方法,是更其他郵箱之類的,但這個是後話了,也需要時間。
這裡寫圖片描述

5:傳送郵件耗時,目前選擇的是使用php 自帶的函式後端執行,類似實現非同步的方式。
5.1 這是原來的傳送郵件方式
這裡寫圖片描述
優點是:程式碼容易理解,阻塞方式執行,可以提取返回值,好除錯
缺點:缺點也很明顯,因為是阻塞,可能應為一個傳送郵件的錯誤,導致整個功能失敗。另外,傳送郵件如果很耗時的話,會影響使用者體驗。
舉個例子,如果是使用者提交了一個評論,資料庫儲存完畢了,但傳送郵件這部分慢,讓使用者多等了足足5秒。
徹底解決辦法:我建議是使用佇列,後臺執行,不要和前臺耦合。
但現在系統正在執行,架構上不適合做緊急大的修改
5.2 臨時方案 類似非同步的方式,傳送郵件後臺執行,不佔用響應時間。

        $email = '[email protected]';//收件人
        $subject = '這裡是郵件標題';
        $body = '您好<br/>這裡是郵件內容<span style="color:red">紅字部分</span>';       
        echo('over' . time());
        //非同步方式,快 但是獲取不到結果
        register_shutdown_function(array('Email', "sendBack"),$email, $subject
, $body, Email::TYPE_AGREE_NOTICE); fastcgi_finish_request();

register_shutdown_function ,這個函式作用是,頁面的php執行完畢後,再執行傳送郵件程式。不管程式碼流程是什麼,把傳送郵件級別調整到最後
fastcgi_finish_request() ,這個函式 作用是,php 執行完畢後,理解發送前段nginx伺服器,使用者不必等待整個php 的全部執行。

舉個例子:以釋出評論為例,加入 寫入資料庫耗時1秒,傳送郵件耗時3秒
那麼傳統的方式,整體耗時 3 +1 = 4秒
但因為 fastcgi_finish_request執行,傳送郵件的3秒後端執行,前臺使用者感覺不到,耗時減少了。

這樣達到了一個目的,即便是傳送郵件出現錯誤,也不會影響主體功能的執行
比如,我把埠寫成錯誤的801

    $config = self::getConfig();
        $Mail = Yii::createComponent('application.extensions.mailer.EMailer');
        $Mail ->CharSet='utf-8';
        $Mail->Port = 801;

但如下圖所示,主體程式碼邏輯照常運作,不會收到影響
這裡寫圖片描述
如上圖,傳送郵件即便是超時,網頁耗時還是很低的。

6:總結,使用上面運作後,會達到一定效果
1:一定程度上邏輯分離,傳送郵件不會影響到主體流程
2:耗時減少(其實伺服器上資源消耗一樣,只不過在伺服器上執行,使用者感覺不到而已)
但也有缺陷:
1:不方便除錯,一旦傳送郵件出現錯誤,可能頁面上不能反饋出來。解決方案是,增加日誌
2: fastcgi_finish_request ,這個函式貌似 隻影響到已fastcgi 方式執行的web伺服器,nginx +php-fpm 這個方式是完美支援的。apache 可能不太相容