15 Mart 2019
Yusuf Borucu
2 yorum
3184 okunma
Laravel'de kuyruk (queue) kullanımı

Merhabalar,
Bu yazıda Laravel'de kuyruk (queue) kullanımından bahsedeceğim. Senaryomuz şu şekilde olacak. Kullanıcının bilgilerini alıp MERNIS kontrolünden geçiren ve bilgilerin doğruluğuna yönelik kullanıcıya e-posta gönderen ufak bir API fonksiyonu yazacağız. Böylece kullanıcı MERNIS kontrolünün tamamlanması ve e-posta gönderilmesi işlemlerinin bitmesini beklemeden cevabı direkt görmüş olacak. Örnek projeyi Github üzerinden paylaştım. Oradan da indirip inceleyebilirsiniz.
İlk olarak komut satırında masaüstü dizinine gelerek aşağıdaki komutu yazıp yeni bir Laravel projesi oluşturuyorum:
composer create-project --prefer-dist laravel/laravel queue
Sonrasında Xampp yardımıyla yerelde bir veritabanı oluşturuyorum. Proje kök dizinindeki .env dosyasını açarak veritabanı bilgilerini aşağıdaki gibi düzenliyorum:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=queue DB_USERNAME=root DB_PASSWORD=
defaultStringLength hatasıyla karşılaşmamak için app/Providers/AppServiceProvider.php dosyasını açarak boot() fonksiyonunu düzenliyorum:
public function boot() { Schema::defaultStringLength(191); }
Şimdi kuyrukta yapılacak işlem için bir job oluşturuyorum.
php artisan make:job SendMernis
Gelen isteği karşılayacak olan fonksiyonum için bir controller oluşturuyorum.
php artisan make:controller UserController
api.php dosyasında istek için route belirtiyorum.
Route::post('register', '[email protected]');
register fonksiyonum tam olarak şu şekilde olacak:
public function register() { $user['name'] = request()->name; $user['surname'] = request()->surname; $user['birth_year'] = request()->birth_year; $user['nationality_id'] = request()->nationality_id; $user['email'] = request()->email; $this->dispatch(new SendMernis($user)); return response()->json([ 'message' => 'Bilgileriniz Mernis kontrolünden geçirilerek tarafınıza e-posta gönderilecektir.' ], 200); }
Bu fonksiyonda kullanıcıdan gelen ad, soyad, doğum yılı, TC kimlik numarası ve e-posta adresi bilgilerini kuyruktaki fonksiyonumuza gönderdik ve kullanıcıya direkt olarak bir mesaj döndük.
resources/views klasörü içerisinde email adında bir klasör açıyorum. mernis_control adında bir blade dosyası açarak içeriğini şu şekilde dolduruyorum.
<html> <head> <meta charset="utf-8"> <title>Mernis Kontrolü</title> </head> <body> <div> {{ $content }} </div> </body> </html>
SendMernis.php dosyasında kuyruğa gelen işlemi karşılayan kısım olan handle ı şu şekilde dolduruyoruz:
public function handle() { $informations = array( "name" => $this->user['name'], "surname" => $this->user['surname'], "birth_year" => $this->user['birth_year'], "nationality_id" => $this->user['nationality_id'] ); $response = $this->mernis_control($informations); $content = $response == "true" ? 'Bilgileriniz doğru.' : 'Bilgileriniz yanlış.'; $data = array( 'content' => $content ); $this->send_mail('email.mernis_control', $data, $this->user['email'], 'Mernis Kontrolü'); }
mernis_control fonksiyonumuz şu şekilde:
public function mernis_control($informations) { $send = '<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <TCKimlikNoDogrula xmlns="http://tckimlik.nvi.gov.tr/WS"> <TCKimlikNo>'.$informations["nationality_id"].'</TCKimlikNo> <Ad>'.$informations["name"].'</Ad> <Soyad>'.$informations["surname"].'</Soyad> <DogumYili>'.$informations["birth_year"].'</DogumYili> </TCKimlikNoDogrula> </soap:Body> </soap:Envelope>'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://tckimlik.nvi.gov.tr/Service/KPSPublic.asmx"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, $send); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'POST /Service/KPSPublic.asmx HTTP/1.1', 'Host: tckimlik.nvi.gov.tr', 'Content-Type: text/xml; charset=utf-8', 'SOAPAction: "http://tckimlik.nvi.gov.tr/WS/TCKimlikNoDogrula"', 'Content-Length: '.strlen($send) )); $response = curl_exec($ch); curl_close($ch); return strip_tags($response); }
send_mail fonksiyonumuz şu şekilde:
public function send_mail($template, $data, $to, $subject) { Mail::send($template, $data, function ($message) use ($to, $subject) { $message->to($to)->subject($subject); }); }
Şimdi kuyruk işlemlerini veritabanında tutan jobs tablosunu oluşturmak için şu komutu yazıyoruz:
php artisan queue:table
Kuyruk işlemlerinin veritabanındaki tablodan işlenmesi için .env dosyasında şöyle bir düzenleme yapıyoruz:
QUEUE_DRIVER=database
Şimdi de veritabanı tablolarını oluşturmak için şu komutu yazıyoruz:
php artisan migrate
.env dosyasında mail ayarlarını düzenliyoruz:
MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=f901938115ba94 MAIL_PASSWORD=4e8d739fbd82a1 MAIL_ENCRYPTION=null
Artık herşey hazır olduğuna göre projemizi çalıştırıp sonuca ulaşalım:
php artisan serve php artisan queue:work (kuyruktaki işlemleri dinlemek için)
Postman'i açıp http://localhost:8000/api/register linkine aşağıdaki şekilde gerekli bilgilerle POST isteği yapıyoruz ve sonucu görüyoruz.
Evet yerel ortamda herşey gayet güzel çalışıyor. Ancak projemizi sunucuya attığımız zaman php artisan queue:work komutunun sürekli çalışıyor olması gerekecek. Bunun içinde supervisor paketini kullanacağız. Eğer sunucumuzda supervisor yoksa şu yazıdan kurulumu yapabilirsiniz: CentOS 7 kurulumu ve kullanımı
Sonrasında /etc dizinindeki supervisord.conf dosyasını nano ile açıyoruz:
nano /etc/supervisord.conf
Ve içeriğine şu satırları ekliyoruz:
[program:laravel-worker] command=/usr/bin/php /var/www/vhosts/queue/artisan queue:work --sleep=3 --tries=3 process_name=%(program_name)s_%(process_num)02d numprocs=8 priority=999 autostart=true autorestart=true startsecs=0 startretries=3 user=apache redirect_stderr=true stdout_logfile=/var/www/vhosts/queue/storage/logs/worker.log
Supervisor servisini durdurup başlatarak işlemi bitiriyoruz:
systemctl stop supervisord systemctl start supervisord
Umarım yararlı olmuştur.
İyi çalışmalar.
salih hanifeoğlu 29 Eylül 2019
merhaba öncelikle güzel bir konu işlemişsiniz teşekkür ederim, benim anlamadığım konu queue:work diyerek eklediğimiz notification lar otomatik olarak job table ne varsa atıyor bunu göndermek için illaki 3th party birseymi eklemek lazım queue:work muadili supervisor paketitni kullanmamız sart mı 5.8 veya 6 da teşekkür ederim umarım sorumu sorabilmisimdir. :)
Yusuf Borucu (Yazı sahibi)25 Ekim 2019
Merhaba, sorunuza ancak dönüş yapabiliyorum kusura bakmayın. Şöyle ki; eğer sunucuya ssh ile erişip projenin dizinine gelerek queue:work komutunu çalıştırırsak aslında olay bitmiş olur. 7/24 ssh erişimi sağlanmış şekilde kalacak bir bilgisayar varsa sorun olmaz yani. Ancak ssh erişimini sonlandırdığımız zaman o komutu çalıştırmayı da sonlandırmış oluruz. Oysa ki queue:work komutunun o dizinde sürekli olarak çalışması gerekiyor. Bunu da bize şuan için 3th party paketler sağlıyor ki o konuda da supervisor oldukça başarılı. İlerleyen zamanlarda farklı bir çözüm olursa onu da yazıya ekleyeceğim. İyi çalışmalar.