Bunun yanı sıra bunları söyleyenler bize, "python consumer olarak php den şu kadar kat daha iyi"yi gösterseler bile aşağıdaki işlemlerden sonra acaba arada bir fark kalıyor mu veya ne kadarlık fark kalıyor, veya python memory olarak hiç mi şişmeyecek veya sorunlar çıkarmayacak? Bu sorunlar çıkarken PHP'nin yanında bir de python'un dertleriyle uğraşmamız gerekmeyecek mi?
Bu nedenle soruna çözüm odaklı yaklaşmak gerek, yeni bir sorun çıkartmamalıyız. Elimizdeki ürünleri en iyi şekilde konumlandırıp ayağa kaldırırsak "ortak problem" olarak karşımıza çıkan sorunları çözüp, ondan sonra bunun üzerine diğer konulardan bahsetmek gerek diye düşünüyorum.
Şimdi size ortak problemlerin ortak çözümünü anlatmaya çalışacağım;
Consumer yazarken hangi dil olursa olsun ihtiyacımız olan temel bazı özellikler var. Bunları yaptığımız sürece, çok iyi memory yönetemezseniz bile paçayı kurtarabilirsiniz. Bunlar şöyle;
1. İşlemesi gereken mesaj sayısına limit koymak.
2. İşlem yapılmadığı zaman ne kadar süre sonra consumer process'inin kapanacağını söylemek.
3. Kendisini sürekli canlı tutmak.
Bu üç madde çok iyi iş yapıyor, bunlara ek olarak memory limitide koyabilirsiniz. Ben buna pek sıcak bakmıyorum.
Biz PHP de bu işi için şu kütüphaneyi kullanıyoruz https://github.com/videlalvaro/php-amqplib
Symfony içinde bu saydığım işlemleri hızlıca yapmak için şu bundle https://github.com/videlalvaro/rabbitmqbundle işimizi görüyor.
Yukarıdaki maddeler ile ilgili dikkat çekmek istediğim kısımlar;
1. Madde için aşağıdaki limit koyabilirsiniz. Böylece process'in ekstra ram temizleme ve benzeri işleri ile uğraşmanız gerekmiyor.
./app/console rabbitmq:consumer -m 50 upload_picture
2. Madde ve İlk yazıda bahsettiğim (her consumer'a eşit yük dağılımı) ayarlar burada gözüküyor. Bu madde şu açıdan önemli, MySQL gibi bir veritabanına bağlantı açıp uzun süre beklerseniz (wait_timeout) bu bağlantınızı belirli bir süre sonra öldürür. Bu durumda da her işelemde "mysql gone away" hatası alırsınız. Bu ve benzeri durumların önüne geçmek için yaşam süresi vermek önemli.
product_process: qos_options: {prefetch_size: 0, prefetch_count: 10, global: false} idle_timeout: 30
3. Madde için bir supervisord kullanıyoruz. Örnek bir ayar aşağıda girdim. Herhangi bir sebeple kapanan process yeniden ayağa kaldırılıyor. Bu ayar ile aşağıdaki komutu iki kere çalıştırmasını istedik. Yani iki adet "consumer"'umuz oldu.
[program:product_process] command=/usr/local/php5/bin/php /home/p1/app/console rabbitmq:consumer -m 100 product_process --env=prod process_name=%(process_num)02d numprocs=2 directory=/tmp autostart=true autorestart=true startsecs=5 startretries=100 user=project redirect_stderr=false stdout_logfile=/var/log/supervisor/product_process.out.log stdout_capture_maxbytes=5MB stdout_logfile_backups=10 stderr_logfile=/var/log/supervisor/product_process.error.log stderr_capture_maxbytes=5MB stderr_logfile_backups=10
Biz bu şekilde ciddi bir performans yakaladık bu bilgiyi paylaşmamanın haksızlık olacağını düşündüğümden yazmak istedim :)
Not (05.04.2014): 3 Mayıs 2014 tarihinde yapılan php-ist konferansında sunum yapan Alvaro Videla'ya Mustafa kardeşim bazı sorular yöneltmiş. Özetle PHP'nin consumer için uygun olup olmadığını sormuş.
Cevap: Derlenebilen dillerin consumer yazmak için daha iyi olduğu, uzun süre ayakta olan php processlerinde ram saçmalama durumu olduğunu söylemiş.
Daha sonra bizim yukarıda anlattığımız çözümlerin geçerliliğini sormuş. Bunlar için ise aşağı yukarı bu şekilde bir çok sorunun çözüldüğünü söylemiş.
Sonuç olarak eğer bu şekilde sorununuz çözülüyorsa bu şekilde ilerlemek, ancak bunlar sizi kesmiyorsa consumer kısmını derlenen diller ile yazıp kafanızın rahat etmesini sağlamanız gerekiyor. Herşey ihtiyaca göre şekilleniyor. Ana sonuç: Samsun S3 mini işinizi görüyorsa Note 3 almayın :)