Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?

Merhaba,

Laravel ile geliştirdiğim entegrasyon sisteminde iş katmanındaki class içerisinde foreach döngüsü ile minumum 1000 tane ürünü curl ile sorgulama , ekleme veya düzenleme yapıyorum. Ardından sonucu veritabanına basıyorum. Bu kısımda 50-60 ürün veya 150 ürün sonrasında bu hata ile karşılaşıyorum.
Sunucu tarafında max_execution_time değerlerini 1200 yapmıştım.

Kod tarafında index.php içerisine ana dizin olarak set_time_limit(0) , max_execution_time(0), ve memort_limit(1024M) vermeme rağmen yine aynı hata devam etmektedir.

Curl olarak kullandığım ixudra/curl içerisinde de TIMEOUT ve CONNTIMEOUT değerlerini de 0 gösterdim.

Konu hakkında 2 gündür sonuç alamadım. Yardımcı olabilecek var mı ?

İyi çalışmalar.

  • Ayrıca şunu unuttum. Kuyruğa ekleme yaparken dispatch(new CurlIslemleri(param1,param2))->onQueue('site1')); olarak kuyruk grubunu belirtmelisin.

  • Ekrem

      Seviye 9
    • Düzenlendi

    Sıkıntının ana temeli 1000 işlem için foreach ile tek process de yapıyorsun bu işlemi. Tahminimce bu işlemi tarayıcıdan tetikliyorsun ki burada erken bir şekilde hata alıyorsun.

    Öncelikle laravel gibi framework kullanıp da 1.000 değil 100 işlemi bile döngüye alıp işlem yapman çok saçma olur.

    Laravel Queue( Kuyruklama sistemi) tam senin yaptığın işler için düşünülerek hazırlanmış bir pakettir.

    Sen yapacağın işlemleri kuyruğa alırsın o kendisi sırayla tek tek işlemi gerçekleştirir, hata alırsa tekrar dener vs.

    adresini bir incelersen sorunun çözümü sağlayacaktır.

    @Ekrem Öncelikle cevabınız için teşekkür ederim. Queue mantığını hiç kavrayamadığım için bu kısmı kullanmamıştım.
    Takıldığım nokta:
    Xml, servis veya excelden okunan 1000 düğüm için sürekli bu verileri okumam gerekmeyecek mi ?

    Yoksa 1 kere okuduktan sonra job oluşturup bunları düğüm düğüm job'a eklemem gerekecek sanırım ?

    Seneryomuzu; 1 excel de 1.000 adet kayıt ve her 6 saatte bir okunacağını varsayarsak.

    6 Saatte bir çalışan cron oluşturup bu cron ile Excel'deki verileri kuyruğa atabilirsin.
    Kuyruk zaten aktif bir şekilde çalışıyor olacağı için, kuyruğa eklenen ilk kayıt itibari ile işlemini yapmaya başlayacaktır.

    Yani kısaca toparlamak gerekirse.

    1) Kayıtları istediğin periyotlarla ve istediğin türde (Excel, XML, Json vs. fark etmez) Job olarak ekle
    2) Kuyruk aktif olsun, sen arkana yaslan.

    İlk etapta bir çok insana biraz karışık gelebiliyor fakat gerçekten basit, sadece ve çok kullanışlı bir sistemdir.

    php artisan queue:table
    php artisan migrate

    komutlarıysa kuyruk sisteminin kurulumu yap.

    php artisan make:job CurlSorgulama
    komutu ile yeni bir tane görev oluştur.

    oluşturduğun görevde __construct içerisinde gönderdiğin parametreleri işle handle alanında curl işlemini yap(foreach içerisinde kullandığın kodu direk yapıştırman yeterli olacaktır).

    hemen ardından
    php artisan queue:work
    komutunu çalıştır.
    işelin nasıl ilerlediğini göreceksindir. Laravel dökümantasyonunu da biraz incelersen eminim istediğin gibi şekillendirebileceksindir.

    Takıldığın yer olursa paylaş.

    @Ekrem Detaylı anlatımınız için tekrardan çok teşekkür ederim.

    Konu hakkında dökümanı okuyarak ve sizin verdiğiniz bilgilere dayanarak işlemleri bu şekilde yapmaya çalışacağım.

    Aklıma takılan yine 1-2 kısım var ama bunları dökümanı okuduktan sonra çözemezsem tekrardan paylaşacağım.

    İyi çalışmalar.

    @Ekrem Merhaba tekrardan,

    Dediğiniz gibi bir kurgu oluşturdum ama sanırım kuyruğu çalıştıramadım.
    Kurgu şu şekilde oldu:

    Controller'dan iş katmanımı çağırdım. Sonrasında buradan xml,excel veya webservisten ürünleri okudum.

    DB::connection($database); olarak foreachten önce bir database connection işlemi başlattım.

    foreach ile bu düğümleri döndüm. Foreach içerisinde de ;

    dispatch(new CurlIslemleri($param1 , $param2)); olarak bu job'u çalıştırmayı denedim.

    __construct içerisinde param1 ve param2 değerlerini aldım.

    handle içerisinde de önceden foreach'te yaptığım işlemleri yaptım.

    Bu işlemler veriyi çözümleme , array oluşturma , curl işlemleri ve bunların sonucuna göre database insert/update kısımlarından oluşmakta.

    .env dosyasında herhangi bir değişiklik yapmadım. sync olarak kuyruk ayarı gözükmektedir.

    Sanırım kuyruğa alma noktasında bir yanlışım var.

    Bu konuda işleyiş ve sorularım hakkında birkaç konuya da değinmek isterim.
    1- Sistem dediğiniz gibi Cron job olarak veya dışarıdan bir browserdan çağıralarak oluşturuluyor. Burada 10 farklı kaynaktan veri okuyup aynı site veya farklı siteler güncellenebilir. Bunlar için ayrı ayrı job mu oluşturmam gerekir ? Yoksa her process jobu ayrı mı tutuyor ?
    2- İsteklerim sync mi olmalı yoksa async mi ? Process ve foreach içerisinde yapılanlar birbirinden bağımsız. Ama veri gönderdiğim yer bu kadar isteği aynı anda kaldıramayabilir. Karşı tarafı da kitlemek istemiyorum.

    Umarım anlatabilmişimdir.

    Teşekkürler.

      YalcinSahin

      Ayrıca eklemeyi unuttuğum bir nokta. Şu an paylaşımlı bir sunucuda olduğum için SSH ve Terminal kullanma şansım yok. Bu sebepten ötürü kuyruk oluşturduktan sonra , database içerisine oluşan tabloları manuel olarak dışa aktar- içeri aktar şeklinde sunucu veritabanına yükleme yaptım

      deathisonitsway

      Merhaba,

      Dediğinizi anlayamadım. Bu işleri neden php ile yapamam onu daha açıklayıcı belirtebilir misiniz ?

      @YalcinSahin Kuyruğu work etmeden kuyruğa attığın işlemleri çalıştırmada sıkıntı yaşarsın.

      php artisan queue:work
      işlemini çalıştırabilmen gerekir. Açıkçası başka türünü hiç kullanmadığım için bir yöntemi varsa da bilmiyorum. Ama ilk fırsatta bakacağım.

        Ekrem Kod tarafında sürekli kuyruğu çalıştıracak kontrol edecek bir yapıya ihtiyacım var o halde. Çünkü bu işlemi cron job olarak bıraktığımda bir daha manuel bir işlem yapmamam gerekir.

        Onun dışında kurduğum yapıda bir sıkıntı var mı ?

        dispatch(new CurlIslemleri(param1,param2)); şeklinde çalıştırmam doğru mu ?

        Kafama takılan diğer bir konu da şuydu:

        İş katmanında ben bir DB::connection($database) bağlantısı açıyorum. foreach bitiminde de DB::disconnetct($database) diye bağlantıyı sonlandırıyorum. Bu noktada database bağlantımı parametre olarak göndermem gerekir mi ?

          Ekrem

          Bu arada localde bu kodu çalıştırdığımda herhangi bir dönüş alamıyorum. Veritabanındaki jobs tablosuna bir şeyler de eklenmedi. Burada gözden atladığım bir kısım olabilir mi

            YalcinSahin Benim hatam. Yukarıda belirtmişsin ama gözden kaçırmışım env de sync olduğu için kuyruğa işlem gönderdiğinde direk olarak işleme alıyor. .env de QUEUE_CONNECTION=database yap ve artisan komutunu kapalı tutarak görev ekle. jobs tablosuna kayıtları yazdığını göreceksin.

              Ekrem Merhaba,

              wget -q -O- Link olarak cron job oluşturdum.

              Dediğiniz gibi jobs tablosuna veriler yazıldı. Ama joblar çalıştırılmadı. bunu tetikleyecek bir kısım yazmamız mı gerekiyor Ekrem Bey

                YalcinSahin
                Yapıda bir problem yok.

                Elimde 1 Adet Sorgulanacak data var ise yapın en basit hali ile aşağıda gibi olması lazım.

                Job'umuz:
                `<?php

                namespace Modules\Sorgulamalar\Jobs;

                use Illuminate\Bus\Queueable;
                use Illuminate\Queue\SerializesModels;
                use Illuminate\Queue\InteractsWithQueue;
                use Illuminate\Contracts\Queue\ShouldQueue;
                use Illuminate\Foundation\Bus\Dispatchable;

                class CurlSorgulamalar implements ShouldQueue
                {
                use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

                public $url;
                public $options;
                public function __construct($url, $options)
                {
                    $this->url = $url;
                    $this->options = $options;
                }
                
                public function handle()
                {
                    try{
                        /*
                         * Guzzle Client ile gerekli curl işlemini yapıp aldığın sonucu işleyeceğin alandır.
                         */
                    }catch (\Exception $exception){
                        /*
                         * Burada Loglama yapabilirsin...
                         * 
                         * Ayrıca hataya düştüğü zaman veri tabanından görevi silmeyecek ve yeniden zamanlayacaktır.
                         * 
                         */
                    }
                }

                }
                ?>`

                Controller'da ki işlemimiz:
                public function CurlListeOlustur(){
                ...
                dispatch(new CurlSorgulamalar($url, $options));
                ...
                }

                bu şekilde yazıp çalıştırdığın zaman okuduğun ve işleme aldığın görevleri veri tabanında jobs tablosunda toplam adet olarak görebilirsin.

                Unutmadan;
                php artisan queue:work bu komutu çalıştırmadığın sürece yaptığın her işlem sadece veri tabanına yazılacak ve işlem yapmayacaktır.

                @Ekrem

                Merhaba,

                local'de bunu denediğimde

                php artisan queue:work
                Processed: App\Jobs\CurlIslemleri dedi ve sadece 1 satır işlem yaptım.

                Daha bekleyen 2450 job satırı duruyor.

                Ayrıca şu konuda bilginiz var mı ?

                Ben her site için A,B,C,D diye kuyruklar oluşturmam gerekiyor. Yani A bitsin B başlasın gibi çalışıyor şu an anladığım kadarıyla.

                10tane job oluşturduğumu varsayıyorum. Bu jobları böyle listelere dahil etmem gerekiyor.

                Ardından A,B,C,D birbirinden bağımsız async çalışması gerekli.

                Haftaya 4 core' lu bir sunucuya geçtiğimde de A , B , C leri birbirindne bağımsız satır satır işlerken , bunları core sayısına göre 4 er'li okumasını sağlamak istiyorum.

                Sunucu'da Cron job olarak da php artisan queue:work komutunu ekleyebilmem gerekli ? Belirli aralıklarla kuyruğa istek atmam gerekecek. Çünkü bunları otomatik bırakmam lazım 🙂

                  ak Merhaba,

                  Şu anda sunucuya SSH yetkim yok. Bu yüzden dediğiniz task işlemlerini kullanamam

                  YalcinSahin
                  Öncelikle unutmadan şunu belirteyim. Cron Job'a php artisan queue:work ekleyemezsin.
                  Bunu etkili ve problemsiz kullanmak istiyorsan Ubuntu kurulu bir sunucuda supervisor eklentisine ihtiyacın var.
                  Yeni sunucuya geçeceğini belirtmişsin fakat bu sunucuda ssh yetkin olacak mı ? Eğer olacaksa işletim sistemi olarak Ubuntu 18.04'ü kurdurtmanı tavsiye ederim.

                  Kuyruklama sisteminin dökümanları içerisinde de belirttiği gibi php artisan queue:work dediğin zaman default kuyruğu çalıştırır. Fakat sen kuyruğa kayıt işlerken farklı gruplar halinde işleyebilirsin. site1,site2,site3 gibi. Elinde 5 site var her bir site için 250 adet kayıt var ama toplamda 1.250 kaydı tek tek yapması işine yaramayacaktır. Orada yine Laravel devreye giriyor
                  php artisan queue:work --queue=site1
                  php artisan queue:work --queue=site2
                  .....

                  diyerek aynı anda istediğin kadar kuyruk çalıştırabilirsin.
                  Ayrıca --tires=sayi ile hata alırsa kaç kere deneyeceğini belirtebilir --timeout=süre ile görevin timeout'unu ayarlayabilirsin.

                  Kısacası doğru konfigürasyon ile yukarıda yapmak istediğin her şeyi yapabilecek durumdadır.