Güzel Gearman işçi Durdurma

9 Cevap php

Ben Gearman işçiler Bazen, ben Gearman işçiler tarafından kullanılan PHP kodu güncellemek olacak vb kullanıcı sayfa görünümleri, kayıtları gibi şeyler tasarrufu, sürekli çalışan bir dizi var. Işçiler, yeni kod geçmek ben öldürmek ve işçiler için PHP süreçlerini yeniden almak için.

Bunu yapmak için daha iyi bir yolu nedir? Ben bu alt işlemlerin birini öldürmek Muhtemelen, ben bazen (çok önemli değil veriler olsa) verileri kaybediyorum.

Edit: Benim için çalışan bir cevap buldum ve aşağıda yayınlanmıştır.

9 Cevap

Eh, ben şimdi ben buna iyi bir cevap bulduk düşünüyorum, bu soru yayınlanmıştır.

Eğer Net_Gearman_Worker için kod bakarsanız, iş döngü içinde, fonksiyon stopWork izlenir göreceksiniz, ve true döndürür, bu işlevi çıkar.

I did the following:
Using memcache, I created a cached value, gearman_restarttime, and I use a separate script to set that to the current timestamp whenever I update the site. (I used Memcache, but this could be stored anywhere--a database, a file, or anything).

Ben İşçi sınıfı, aslında, Net_Gearman_Worker_Foo olmak için genişletilmiş ve benim işçilerin tüm bu örneğini vardı. Foo sınıfında, ben aşağıdakileri yapmak stopWork işlevini overrode: birincisi, gearman_restarttime denetler; ile ilk kez, bir genel değişken değeri kaydeder. O andan itibaren, her zaman aracılığıyla, bu global önbelleğe değerini karşılaştırır. O değişti, stopWork true döndürür ve işçi sonlandırılıyor. Bir cron her işçi hala çalışıyorsa görmek için her dakika denetler ve çıkıldı herhangi bir işçi yeniden başlatır.

Bir de stopWork bir zamanlayıcı koyarak, ve sadece bir kez, her x dakikada bir önbelleğini kontrol değerinde olabilir. Bizim durumumuzda, Memcache değerleri her zaman kontrol bir sorun görünmüyor yeterince hızlı, ama daha az sık sık kontrol, geçerli zaman damgası kapalı saklamak için başka bir sistem kullanıyorsanız, daha iyi olurdu.

Solution 1


Genellikle-r bayrağı ile unix cini programı ile benim işçi çalıştırmak ve onlara bir iş sonra sona izin. Her yineleme ve cini otomatik olarak yeniden başlayacaktır sonra komut incelikle sona erecek.

Sizin işçiler bir iş için bayat olacak ama bu verileri kaybetme olarak sizin için büyük bir anlaşma olmayabilir

Bu çözüm aynı zamanda bellek boşaltarak avantajına sahiptir. PHP 5.3 tanrı korkunç GC sahip ön olarak büyük işler yapıyoruz eğer belleğe sorun haline çalıştırabilirsiniz.

Solution 2


Ayrıca komut çıkar senin işçilerin tüm bir çıkın işlev eklemek olabilir. Seni yeniden istiyorum zaman sadece vermek Gearman yüksek önceliğe sahip çıkmak için çağırır.

Hmm, kendi iradeleri görünce evet o zaman sadece sadece kendilerini öldürmek eğer kaynak kodu, değiştirildiği zaman zaman kontrol etmek için işçilerin bir kod uygulamak. Yani işin ortasında iken kontrol ve iş çok büyük ise.

Diğer yolu şans ve yeniden var zaman dur demek için, belki ağ üzerinden, bir kesme çeşit uygulamak olacaktır.

Son çözüm, bu işlevselliği eklemek için Gearman kaynağını değiştirmek için yardımcı oluyor.

Ben (Gearman :: XS ile perl'de olsa) hem de son zamanlarda bu bakarak oldum. Benim usecase senin gibi aynı oldu - uzun süren Gearman işçi periyodik kendi başına yeni bir sürümünü denetlemek ve yeniden sağlar.

Benim ilk girişimi sadece son işçi komut sürümü (bir md5sum de çalışır) kontrol beri ne kadar uzun işçi tutmak parçayı sahip oldu. N saniye işler arasında, geçtikten sonra bir kez, tek başına yeni bir sürümü kullanılabilir olup olmadığını görmek için kontrol edin ve kendini (fork () / exec ()) yeniden başlatmak olacaktır. Bu çalışma Tamam yaptım, ama nadir işler için kayıtlı işçilerin potansiyel dönmek için () iş için saatlerce bekleyen sona, ve böylece şimdiki zaman kontrol etmek için olabilir.

Çalışması () ile işler için bekleyen Yani ben şimdi oldukça kısa bir zaman aşımı kuruyorum, bu yüzden daha düzenli zaman kontrol edebilirsiniz. PHP arayüzü iş için kayıt yaparken bu zaman aşımı değerini ayarlayabilirsiniz öneririz. Ben yeni sürüm kontrol tetiklemek için SIGALRM kullanıyorum. Iş (), yani alarm Perl arayüzü bloklar başlangıçta tetiklenir değildi. 60 saniye zaman aşımını ayarlama SIGALRM çalışma var.

Birisi bir işçi çalıştıran Perl için cevap arıyor olsaydı, o GearmanX::Starter kütüphane için ne bir parçası. Geçerli işi iki farklı şekilde tamamladıktan sonra işçileri durdurabilirsiniz: dışarıdan işçi sürecini bir SIGTERM gönderirken, ya da programlı bir küresel değişkeni ayarlayarak tarafından.

Işçiler PHP ile yazılmış olduğu gerçeği göz önüne alındığında, bu bilinen bir programa onları geri dönüşüm için iyi bir fikir olacaktır. Bu zamandan beri başlamış veya iş belirli sayıda teşebbüs edildikten sonra yapılabilir statik bir miktar olabilir.

Bu aslında (hayır cinas amaçlanan) bir taşla iki kuş öldürür. Bellek sızıntıları için potansiyel hafifletici vardır, ve senin işçilerin herhangi bir potansiyel yeni kod pick up ne zaman belirlemek için tutarlı bir yol var.

Ben genellikle bir işçi sürecinde nerede olduğunu kontrol etmek için basit yani onlar stdout ve / veya bir günlüğü tesis kendi aralığı rapor şekilde işçileri yazmak.

Ben bu aynı sorun koştu ve python 2.7 için bir çözüm geldi.

Ben sistemdeki diğer bileşenler ile iletişim kurmak için Gearman kullanan bir python komut dosyası yazıyorum. Komut dosyası birden çok işçi var olacak, ve ben ayrı bir konu, her işçi çalıştırıyorum. İşçiler hepsi işlemek ve bir mesaj kuyruğuna o veriyi depolamak, Gearman veri almak ve ana iş parçacığı olarak gerekli sıranın kapalı indirebiliriz.

Temiz her işçi kapatılıyor benim çözüm gearman.GearmanWorker alt sınıfı ve work() işlevi geçersiz oldu:

from gearman import GearmanWorker
POLL_TIMEOUT_IN_SECONDS = 60.0
class StoppableWorker(GearmanWorker):
    def __init__(self, host_list=None):
        super(StoppableWorker,self).__init__(host_list=host_list)
        self._exit_runloop = False


    # OVERRIDDEN
    def work(self, poll_timeout=POLL_TIMEOUT_IN_SECONDS):
        worker_connections = []
        continue_working = True

        def continue_while_connections_alive(any_activity):
            return self.after_poll(any_activity)

        while continue_working and not self._exit_runloop:
            worker_connections = self.establish_worker_connections()
            continue_working = self.poll_connections_until_stopped(
                worker_connections,
                continue_while_connections_alive,
                timeout=poll_timeout)

        for current_connection in worker_connections:
            current_connection.close()

        self.shutdown()


    def stopwork(self):
        self._exit_runloop = True

Sadece GearmanWorker gibi kullanın. Bu komut çıkmak için zamanı geldiğinde, stopwork() işlevini çağırın. Hemen durmayacak - bu çalışma döngünün tekmeler önce poll_timeout saniye kadar sürebilir.

stopwork() işlevini çağırmak için birden fazla akıllı yolu olabilir. Benim durumumda, ben ana iş parçacığı geçici bir Gearman istemci oluşturmak. Ben kapatma çalışıyorum işçi için, ben Gearman sunucu üzerinden özel bir STOP komutunu gönderin. Işçi, bu mesajı aldığında, kendisini kapatmaya bilir.

Bu yardımcı olur umarım!

http://phpscaling.com/2009/06/23/doing-the-work-elsewhere-sidebar-running-the-worker/

Yukarıdaki makale gösterir gibi, ben temizleme işleri arasında zaman zaman çıkan, bir BASH kabuk içinde bir işçi çalıştırmak (veya yeniden yüklemek işçi-script) var - ya da belirli bir görev ona verilir eğer belirli bir ile çıkabilirsiniz kodunu çıkmak ve kapatmaya.

Bu sürekli entegrasyon sistemi içine güzel uyabilecek. Ben bunu var ya :-) yakında olmalıdır umut

Yeni kodu kontrol gibi, otomatik olarak inşa edilmiş ve sunucu üzerine dağıtılabilir alır. Yapı komut bir parçası olarak, tüm işçi öldürmek ve yenilerini başlatmak.