2015-01-02 18 views
7

Supersord/SQS ile Laravel 4'ü çalıştırıyoruz ve 10'dan fazla çalışan işlemi kullanarak çalıştırılan 30'dan fazla farklı görevimiz var. Her şey çok iyi gidiyor, ancak belli görevlerin zaman aşımına uğradığı görülüyor. Böyle bir istisna olsun:Laravel kuyruğunda çalışırken çalıştırılan şu anki görevi alın:

[Symfony\Component\Process\Exception\ProcessTimedOutException] 
The process ""/usr/bin/php5" artisan queue:work --queue="https://sqs.us-east-  1.amazonaws.com/xxxx" --delay=0 --memory=128 --sleep=3 --tries=0 --env=development" exceeded the timeout of 180 seconds. 

Bunu kullanarak bu istisnayı yakalamak:

App::error(function(Symfony\Component\Process\Exception\ProcessTimedOutException $exception) { 

    /// caught! 
}); 

Ben HANGİ görev için zamanında ediliyor belirlemek gibi olamaz Ancak (zaman aşımı oluştuğunda) ve hatta daha iyi ben istisna nesne yığın izini giriş denedi

göreve geçirildi veri .. erişebilir eğer:

$exception->getTraceAsString() 

Ancak, bu bana çağrılan görev hakkında yeterince ayrıntı getirmiyor.

GÜNCELLEME nasıl php artisan queue:listen çalışmalarına daha fazla araştırma yapmış

. Bazı referanslar:

, sen php artisan queue:listen çağırdığınızda, (Symfony'nin/Bileşen/Proses kullanarak) ALT SÜREÇ oluşturulur esasen komutu çalıştırır php artisan queue:work. Bu alt süreç bir sonraki işi kuyruktan alır, çalıştırır, tamamlandığında raporlar ve daha sonra Dinleyici bir sonraki işi ele almak için başka bir alt süreci ortaya çıkarır.

Alt işlemlerden biri belirlenen zaman aşımı sınırından uzun sürüyorsa, PARENT Listener bir istisna atar, ancak üst örnekte oluşturduğu alt işlem hakkında veri yoktur. İĞNE BİR HARCAMA İLE! Ana Dinleyici DOES'un alt işlemi 'çıktısını aldığını görüyoruz. Bana göre ebeveyn, alt süreci (işçi) çıktısını konsola getirmekten başka bir şey yapmıyor. Ancak, belki de bu çıktıyı yakalamanın bir yolu vardır, böylece bir istisna atıldığında, çıktıyı kaydedebiliriz ve bu nedenle zaman aşımı gerçekleştiğinde hangi görevin çalıştığı hakkında bilgi sahibi olabiliriz!

Ayrıca, supervisord kullanırken, tüm çalışan çıktılarını kaydeden bir stdout_logfile belirtebildiğimizi fark ettik. Şu anda tüm 10 süpervizörümüzün "programları" için tek bir günlük dosyası kullanıyoruz. Bunu, her bir "program" ın kendi günlük dosyası olarak kullanması için değiştirebilirdik ve belki de zaman aşımı istisnası ana Dinleyici'ye atıldığında, bu günlük dosyasının son 10 satırını alabilirdik. Bu ayrıca zaman aşımı sırasında hangi görevlerin çalıştırıldığına dair bilgi verir. Ancak, hangi denetleyici programın çalıştığı ana Dinleyiciyi "nasıl bilgilendireceğimi" bilmiyorum, böylece hangi günlük dosyasına bakılacağını biliyor!

+0

Sık sık yeterli olur - hızlı bir hata ayıklama için - "Görev X başlatılıyor" ve "Görev X bitti". Sonra zaman aşımı oluştuğunda - hangi görevin bitmediğine bakın ... – Laurence

+0

@TheShiftExchange maalesef bu pek yardımcı olmaz. Çok sık zaman aşımı oluşur, ancak iş hala tamamlanır ve hala "Görev X bitti" mesajını günlüğe kaydeder. – phirschybar

+1

Aslında - bu bize çok şey anlatmıyor mu? Bu yüzden çağrılan görevi yakalayamıyorsunuz - çünkü görev tamamlandı mı? Yani sorun görev dışında mı yatıyor? – Laurence

cevap

4

Özel durum sınıfına bakma (Symfony\Component\Process\Exception\ProcessTimedOutException) Symfony\Component\Process\Process örneğini döndüren getProcess() yöntemini buldum. Orada getOutput() var. Yöntem, adının söylediği şeyi yapar.

Yorumlarda önerdiğiniz gibi, her görevde sınıf adını ve parametreleri ekleyerek ve ardından sorunlu görevi belirlemek için oluşturulan çıktıyı kullanarak bunu kullanabilirsiniz.

İşte bir örnek (... belki Illuminate\Queue\Listener sınıfa ile müdahalesi hariç) çok şık değil ama daha iyi bir yol düşünemiyorum, dediği gibi bunu (denenmemiş olsa da)

nasıl yapabildiğimi Maalesef bu size 012 çağırmak zorunda kalacak her görevde demektir

abstract class BaseTask { 
    public function fire(){ 
     echo get_class($this) . ':' . json_encode(func_get_args()) . ';'; 
    } 
} 

: bunu istediğiniz bir BaseTask Yani

ClassName:ParametersAsJson;ClassName:ParametersAsJson; 

: Ben çıkış için bu biçimi seçti

class Task extends BaseTask { 
    public function fire($param1, $param2){ 
     parent::fire($param1, $param2); 

     // do stuff 
    } 
} 

Ve nihayet, istisna işleyicisi:

App::error(function(Symfony\Component\Process\Exception\ProcessTimedOutException $exception) { 

    $output = $exception->getProcess()->getOutput(); 
    $tasks = explode(';', $output); 
    array_pop($output); // remove empty task that's here because of the closing ";" 
    $lastTask = end($tasks); 
    $parts = explode(':', $lastTask); 

    $className = $parts[0]; 
    $parameters = json_decode($parts[1]); 

    // write details to log 

}); 
+0

Zaten bunu neredeyse önerdiğiniz gibi yaptım. Artık üretimde zaman aşımlarının olmasını bekliyorum. Mesaj sonuçları olacak! Teşekkürler. – phirschybar

+0

harika çalışıyor. teşekkürler @lukasgeiter. – phirschybar

+0

Harika! Bakalım kimsenin daha zarif bir şeyle gelip gelmediğini ... – lukasgeiter

3

laravel 4.1 yana olduğu tüm iş ayrıntıları istisna zamanında veritabanı veya mevcut kalıcıyken başarısız işlerini gerçekleştirmek için yerleşik bir mekanizma (ya da her ikisi de). Ayrıntılı ve açık belgeler Laravel's website'da mevcuttur.

Özetlemek gerekirse :

  1. laravel Sen hemen işleme
  2. için detaylı iş bilgilerini alacak Queue::failing aracılığıyla bir özel durum işleyici, kayıt olabilirsiniz sonra incelemek
  3. için failed_jobs tabloya başarısız işleri taşıyabilirsiniz

Ancak, bir zaman aşımının Laravel'de bir başarısızlık olarak kabul edilip edilmediğinin sorgulanması, bu yüzden testlere ihtiyaç duyduğumdan dolayı test gerektiriyor. kuyrukları ile rience.

Eğer laravel 4.0 kullanıyorsanız belki de gerçekten (yükseltmek zorunda kez yerine gereksiz hale gelecektir komplike kod yazarken en az 4.1 yükseltme değerlendirmek faydalı olacaktır Eğer olacak bir noktada yükseltme, doğru mu?:)). Upgrade path oldukça basit görünüyor.

Bu, Laravel 4.0 sorunuzu doğrudan yanıtlamamakla birlikte, sizin ve gelecekteki herhangi bir okuyucunun dikkate alabileceği bir şeydir.

+0

Bu gerçekten çok iyi bir cevap ve aynı zamanda Laravel'e özgü. Diğer cevabı kabul ettim çünkü zaman aşımının nedenini ayıklamak için başarısız olan (zaman aşımına neden olan) başarısız olan belirli görevin çıktısını almamı sağlıyor. Örneğin kıyaslama yapabilirim ve daha sonra kaydedilen hata iletisinde bu çıktıyı yakalayabilirim. – phirschybar

İlgili konular