Amazon SES aracılığıyla saniyede 100 e -posta gönderebilecek bir e -posta kuyruğu nasıl oluştururuz
Kuyruklar olmadan, sitenin aynı anda binlerce e -posta olmasa bile yüzlerce göndermeye çalıştığı bir durum yaşayacağız ve bu kesinlikle bellek eksikliği veya talebi işleme süresi nedeniyle kazalara neden olacak. Ayrıca, kesin olarak belirlenmeyen ve bir hesaptan diğerine değişen bir Amazon SES tarife sınırı da vardır. Bir kuyruk yapmamız gerektiğini fark ettikten sonra, aklım hemen kendi Ashley Rich’imiz tarafından yapılan WordPress eklentisi için kütüphane olan WP kuyruğuna sabitlendi. Daha önce Addon WP Migrate DB Pro Tema + Eklenti Dosyaları ve Görüntü İşleme Kuyruk Eklentisi gibi diğer eklentilerde kullandık.
Neden WP kuyruğu? İşi kaydetmenize izin vermek ve kuyruğa biraz iş eklemek için iyi bir iş çıkarır. Diğer birkaç kuyruk sistemine baktım ve hatta Amazon basit kuyruk hizmetine baktım. Ancak bunu yapmamaya karar verdim çünkü ek fiyatların ve karmaşıklığın güvenilmesi gereken başka hizmetler vardı. Buna ek olarak, kuyruk sisteminde ayarlamalar veya değişiklikler yapmamız gerekiyorsa, WP kuyruğunda Amazon SQ’lardan daha kolay olacaktır. AWS Komut Havuzu İhtiyaçlarımız için WP kuyruğunu kullanarak küçük bir zayıflık, kimin ilk geldiğine, kimin servis edildiğine dayanarak bir seferde bir işi tamamlamaya odaklanıyor. Bu basit ve işlevseldir, ancak günde binlerce e -posta göndermeyi planlayan kullanıcılar için yavaş olabilir. Amazon SES’e ortalama yangın talebi yaklaşık 0,4 saniye sürebileceğinden, sadece saniyede birkaç e -posta göndermeyi umabiliriz. Bunun üzerinde çalışmak için AWS, bir tane göndermek ve başka bir göndermeden önce yanıtlar beklemek yerine birkaç e -posta göndermek için birkaç UTA’nın kullanılmasını önerir. Neyse ki, Amazon, WP boşaltma SES tarafından kullanılan PHP SDK’da bunu yapmanın bir yolunu inşa etti. Commandpool nesneleri, yangına gönderilecek bir dizi komut eklemek için kullanılabilir ve bunları akıllıca gruplandırır. Kuyruk sisteminin dekorasyonu ile akışı görselleştirme, bir e -posta göndermek için eklentideki veri akışını görselleştirmek daha kolay olacaktır:
Sistemi gerçekten uygulayan eğlenceli bir eğlence için şimdi uygulama! Değiştir wp_mail () İlk adım, takılabilir WordPress’in bir işlevi olan WP_mail () işlevini değiştirmektir. Bu, WordPress aracılığıyla gönderilen tüm e -postaları (ve uygun temalar ve eklentiler) dinlememizi ve doğrudan e -posta göndermek yerine kendi işlevlerimizi kullanmamızı sağlar. WP boşaltılar SES’de bu oldukça kolaydır – yalnızca ana eklenti dosyasının altına aşağıdaki kodu ekleriz: if (! Function_exists (‘wp_mail’)) {$ setts = get_site_option (‘wposes_settings’); if (isset ($ setts [‘send-via-sis’]) && (bool) $ ayarlar [‘sed-via-sis’]) {function wp_mail ($ ila, $ subion, $ mesaj, $ başlıklar = ” , $ atthments = array ()) {global $ wp_offload_ses; $ wp_offload_ses-> mail_handler ($ to, $ subion, $ mesaj, $ başlıklar, $ ekler); }}} Yukarıda WP_mail () işlevinin üzerine yazılıp yazılmadığını kontrol edin ve değilse, WP boşaltma eklentisi bir e -posta gönderecek şekilde yapılandırılırsa WP_MAIL () işlevimizin kendisi yapılacaktır. Orijinal WP_mail () işleviyle aynı verileri aldı ve özel e -postamızın işlenmesine devam etti.Bir sonraki kuyruğa ekleyin Kuyuya bir e -posta eklememiz gerekiyor.Yukarıdaki wp_mail () işlevinde adlandırılan mail_hander () yöntemi, iletilen tüm öznitelikleri wp_mail () ile birleştirir ve yeni e -posta çalışmasını kuyruğa itme: public function mail_handler ($ to, $ öznesi, $ mesaj, $ başlıklar, $ ekler) {ekler) { $ atts = Applate_filters (‘wp_mail’, compact (‘to’, ‘konu’, ‘mesaj’, ‘başlıklar’, ‘ekler’));$ settings = $ this-> setts-> get_settings ();$ this-> get_queue ()-> push (yeni e-posta_job ($ atts, $ ayarlar), $ this-> gecikme);Dönüş;} Bu, daha sonra işlemek için veritabanına bir e -posta işi kaydeder.E -posta çalışmasından bahsetmişken, böyle görünüyor:
Sınıf e -posta_job iş { / ** * @var array * / private $ atts; / ** * @Var Array */ private $ ayarları; /*** Gerekli verileri işe aktarın. * * @param String $ atts */ genel işlev __Construct ($ atts, $ ayarlar) {$ this-> atts = $ atts; $ this-> ayarlar = $ ayarlar; } /*** İş mantığını ele alın. */ Genel işlev Hands () {global $ wp_offload_ses; if (isset ($ this-> atts [‘to’]))) {$ to = $ this-> atts [‘to’]; } if (isset ($ this-> atts [‘öznesi’])))) {$ suic = $ this-> atts [‘öznesi’]; } if (isset ($ this-> atts [‘mesaj’])))) {$ mesaj = $ this-> atts [‘Message’]; } if (isset ($ this-> atts [‘başlıklar’])))) {$ başlıklar = $ this-> atts [‘başlıklar’]; } if (isset ($ this-> atts [‘ataşmanlar’])))) {$ atthments = $ this-> atts [‘ekler’]; } $ client = $ wp_offload_ses-> get_ses_api ()-> get_client (); $ e-posta = yeni e-posta ($ to, $ öznesi, $ mesaj, $ başlıklar, $ ekler, $ this-> ayarlar); $ raw = $ e-posta-> hazırlık (); $ data = array (‘x-message-id’ => $ this-> id (), ‘rawMessage’ => dizi (‘data’ => $ raw,),); $ Client-> getCommand (‘sendrawemail’, $ data) döndür; }} Kuyruk bir işi işlerken, e -posta_job sınıfını veritabanından yapıcıya iletilen özniteliklerle geri yükler ve ardından çalışmayı çalıştırmak için işlem yöntemini () çağırır.
Bu durumda, gönderilmeye hazır bir e-posta alır ve gerçekten göndermek için komutu iade eder-bu daha sonra komutanlığında kullanılır.Commandpool aracılığıyla gönderin, neyse ki AWS PHP SDK, komutanlığı daha fazla kurcalamadan kullanmaya başlamak için gereken sınıfı içerir.Üç ana yöntemi olan tüm ilgili mantığı işleyen bir sınıf yaptım.İlk olarak, bir koleksiyona komut ekleyen add_command () işlevi vardır: public fonksiyon add_command ($ command) {$ this-> commands [] = $ command;$ num_commands = count ($ this-> komutlar);if ($ this-> get_concurrency () === $ num_commands ||$ this-> commands = array ();}} Ardından, komut sınırına ulaşıldığında, () yürütme işlevine şu denir:
özel işlev execute () {global $ wp_offload_ses; // commandpool $ client = $ wp_offload_ses-> get_ses_api ()-> get_client (); $ command_pool = new commandpool ($ client, $ this-> commands, [‘eşzamanlılık’ => $ this-> get_concurrency (), ‘fatura’ => işlev (sonuç arayüzü $ sonuç, $ iterkey, properterface $ agregatePromise) = $ this-> komutlar [$ iterkey] [‘x-meatse-id’]; $ job = $ this-> connection-> get_job ($ id); $ this-> connection-> dele ($ iş);}, ‘ reddedilen ‘=> işlev (sesexception $ nedeni, $ iterk, vaat arayüzü $ agregatePromise) {$ id = $ this-> commands [$ iterk] [‘ x-message-id ‘]; $ job = $ this-> bağlantı- > get_job ($ id); $ iş-> sürüm (); if ($ Job-> denemeleri ()> = $ this-> denemeler) {$ Job-> başarısız ();} ($ Job-> başarısız ( )) {$ this-> connection-> başarısızlık ($ iş, $ nedeni);} else {$ this-> connection-> release ($ iş);}}]); // e-postayı havuzda gönder $ Promise = $ command_pool-> Promise (); $ Prompord-> Wait (); } Bu işlev AWS Commandpool sınıfını başlatır ve eşzamansız bir istek gönderir. Bununla ilgili ilginç olan şey, yangın talebinin yanıtını ele almak için anonim işlevi de sürdürebilmenizdir, böylece her istek, tüm isteklerin gönderilmesini bekleyen zamanı tamamladıktan hemen sonra ele alınır. Yerine getirilen anonim işlev, başarılı bir şekilde çözülen ve kuyruklardan silinen istekleri işlerken, reddedilen işlevler tekrar denenebilecek şekilde çalışmayı başarısız ve serbest bırakan istekleri işler. İstek birkaç kez daha fazla başarısız olursa (bu durumda 3), bir arıza olarak işaretlenir ve otomatik olarak tekrar denenmez.
Commandpool Concurrence’ın diğer işlevler tarafından ayarlandığını fark etmiş olabilirsiniz, get_concurrency (). Bu işlev, SES’den maksimum teslimat hızını alır ve Commandpool nesnesine devam eder ve Amazon SES’i aşmadan her zaman tepe kapasitesinde çalışmasını sağlar: özel işlev get_concurrency () {global $ wp_offload_ses; if (! Is_null ($ this-> eşzamanlılık)) {return $ this-> eşzamanlılık; } $ kota = $ wp_offload_ses-> get_ses_api ()-> get_send_quota (); $ send_rate = 10; if (! Is_wp_error ($ kota)) {$ send_rate = $ kota [‘oranı’]; } $ this-> concurency = (int) appling_filters (‘wposes_max_concurrency’, $ send_rate); Dönüş $ this-> eşzamanlılık; } Kuyruk, daha fazla iş olmayana veya PHP zaman sınırı elde edilene kadar mevcut e -posta çalışmasını tekrarlamaya devam edecektir. Bundan sonra, kuyruk bir sonraki WP_CRON’u çalıştırana kadar durur ve daha sonra istek sürecine devam eder. Tüm kodlarla karşılaştırma basıldığında, her şeyin gerçekten çalışıp çalışmadığını görme zamanı. Asenkron istekleri uzun mesafeli API ile karşılaştırmak zor olduğundan, birkaç yüz e -mail için sıraya girecek hızlı bir komut dosyasını hackliyorum ve gönderilen her e -postanın zamanını kaydetmek için yerine getirilen komutan işlevini değiştiriyorum.
Birkaç kriterden sonra, saniyede 100 e -posta göndermenin kolay olduğu açıktır ve Amazon’un tarife sınırımı artırma isteğimi kabul ederse daha fazla göndereceğini varsayıyorum.