Zend_Mail: Nasıl PHP ölümcül hatayı düzeltmek için: İzin bellek boyutu tükendi?

3 Cevap php

Ben abonelerin listesinin, bir PDF eki ile bir foreach döngü içinde tek bir seferde, e-posta gönderen bir cron işi var. Ben cron komut bu mesajı aldım:

Fatal error: Allowed memory size of 94371840 bytes exhausted (tried to allocate 78643193 bytes)

Ben bu hatayı önlemek için ne yapmak gerekiyor?

Ayrıca, ben tüm abonelere göndererek bitirmek vermedi eminim, bu yüzden nasıl herkese göndermek olmasaydı bu yüzden tekrar almak için nerede bilen bu takip gerekir?

Updater: Burada bir kod örneği var: (Ben arada Zend Framework kullanıyorum)

public function send(Default_Model_MyEmail $myEmail)
{
    if (null != ($id = $myEmail->attachmentId)) {
        $file = new Default_Model_File();
        $file->find($id);
        $filepath = APPLICATION_UPLOADS_DIR . '/' . $file->getActualFilename();

        $attachment = new Zend_Mime_Part(file_get_contents($filepath));
        $attachment->type = $file->getMimeType();
        $attachment->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
        $attachment->encoding = Zend_Mime::ENCODING_BASE64;
        $attachment->filename = $file->getDisplayFilename();    
    }
    $transport = new Zend_Mail_Transport_Smtp('localhost');

    $mail = new Zend_Mail('utf-8');
    $mail->setFrom('from@address', 'From Name');
    $mail->setReplyTo('replyto@address');
    $mail->setSubject($myEmail->subject);
    if (isset($attachment)) {
        $mail->addAttachment($attachment);
    }

    $subscribers = $this->getSubscribers();
    foreach ($subscribers as $subscriber) {
        $mail->addTo($subscriber->email);
        $bodyText = $myEmail->body
            . "\r\n\r\nIf for any reason you would like to be removed from this mailing list, "
            . "please visit \r\nhttp://myapp.com/myemail/unsubscribe/email/"
            . $subscriber->email;
        $mail->setBodyText($bodyText);
        $mail->send($transport);
        $mail->clearRecipients();
    }
}

Update: I $transport değişkeni yeniden duyuyorum. Ben bu birden abonelerine göndermek için doğru bir yol olduğunu izlenim altında oldu, ama belki bu nedeni nedir? Sen ne düşünüyorsun?

Update: I bellek kullanımı tabloları yazdırmak günlük tabloların bir sürü ekledim, ama ben gerçekten şimdi ne yapacağımı bilmiyorum. Bellek kullanımı her e-posta ile artar. 200 abone liste ile, 160 alır daha sonra bellek çalışır. Ben ne yapmalıyım?

3 Cevap

Kodunuzu hata mesajı dayalı 78MB bir yığın tahsis çalışıyor gibi görünüyor.

Denemek ve bir kerede bir bellek gerçekten büyük bir yığın tahsis duyabileceğiniz her şey için kodunuzu kontrol edin. Başarısız tahsisi blok büyük olduğundan, bu muhtemelen, küçük nesneleri serbest bırakmak için bir başarısızlık neden değildir.

Bu neden olan bir kod pasajı sonrası ise, ben bir göz var ve daha detaylı bir cevap için denemek için mutlu olurdu.

Eğer herkese ya gönderilen olmadığını bulmaya gelince, e-posta sunucusu (SMTP sunucusu) onay gönderilen mesajların bir günlüğüne yazar. Eğer öyleyse, e-posta aldım kişilerin bir listesini almak mümkün olabilir. Genel olarak, ben bir dosyaya veya veritabanına gelecekte bir çökme var durumda, gönderilen her e-posta giriş yapmak için PHP kodu değiştirebilirsiniz öneririm.

Kodunu gördükten sonra EDIT:

Yüzeyde, bu e-posta ve bağlantı bir kez oluşturulur ve yeniden kullanılır temsil nesnesi gibi görünüyor.

Ben yerel kod hata ayıklama öneririz.

İlk olarak, üretimde ne eşit bir bellek sınırı kurmak. this resource nasıl anlamaya çalışın.

Sonra, ne kadar memory is available her tekrarında sonra görmek için döngü içinde bazı debug çıktılarını ekleyin.

Son olarak, yerel kod çalıştırmak, ancak e-posta adresinizi ya da tercihen bilinen kötü bir e-posta adresi alanınızdaki (yani spam insanları yok) ya da yerine. Sizin gönderme ilerledikçe bellek kullanımını izleyin.

Bu umarım hata nedenini daraltmak yardımcı olmalıdır.

EDIT 2:

Tamam, bellek kullanımı sürekli büyüyen olduğunu gördükten sonra, biraz google sihirli bu bir reported workaround ile bilinen bir sorun olduğunu döndü.

Malfist cevabı @ yapabilirsiniz ek olarak:

  • Eğer değişkenleri yeniden yerine her döngü tekrarında için yenilerini ekliyoruz emin olun.
  • Bir e-posta başarıyla gönderildi edildiğinde sistem almak not var, ve e-postalar belli bir sayıdan sonra göndermeyi durdurmak. Dahaki sefere cron bu gönderilmek üzere bırakılır kim anlamaya ve devam edilmelidir çalışır.

Bellek kullanımını azaltmak, ya da bellek sınırı artırmak.