Kooperatif
Kooperatif, iş parçacıklarından daha hafif bir kullanıcı düzeyinde eşzamanlılık mekanizmasıdır ve bir süreç içinde çoklu görev planlaması gerçekleştirebilir. Kooperatifler, askıya alma ve yeniden başlatma işlemlerinin manuel kontrolü aracılığıyla kooperatifler arasında geçiş yapmayı sağlar, süreç bağlam değiştirme giderlerinden kaçınır.
Workerman, alt yapıda Swoole/Swow/Fiber sürücülerini otomatik olarak uyumlu hale getiren genel bir kooperatif arayüzü sunar.
İpucu
Bu özellik için workerman>=5.1.0 gerekir.
Dikkat
- Kooperatif yalnızca
SwooleSwowFibersürücülerini destekler. Fibersürücüsü kullanıyorsanız,composer require revolt/event-loopyüklemeniz gerekir.SwooleveyaSwowsürücüsü, PHP engelleyici fonksiyonlarını otomatik olarak kooperatif hale getirerek, önceki senkron kodların asenkron olarak çalışmasını sağlar.- Ancak
Fiber,SwooleveSwowgibi otomatik kooperatifleşme sağlayamaz; PHP’nin kendi engelleyici fonksiyonlarıyla karşılaştığında tüm süreci engeller ve kooperatif geçişi gerçekleşmez. SwooleSwowFibersürücüleri kullanıldığında,workermanher seferindeonWorkerStartonMessageonConnectonClosegibi geri çağırmalarda otomatik olarak bir kooperatif oluşturur.- Farklı
worker'lar için farklı kooperatif sürücüleri ayarlamak için$worker->eventLoop=xxx;kullanabilirsiniz.
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine;
use Workerman\Events\Swoole;
use Workerman\Events\Fiber;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker1 = new Worker('http://0.0.0.0:8001');
$worker1->eventLoop = Swoole::class; // Swoole kooperatifini kullanıyor
$worker1->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
$worker2 = new Worker('http://0.0.0.0:8001');
$worker2->eventLoop = Fiber::class; // Kendi Fiber kooperatifini kullanıyor
$worker2->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
Worker::runAll();
Kooperatiflerin Sağladığı Arayüz
interface CoroutineInterface
{
/**
* Kooperatif oluşturur ve hemen çalıştırır
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Kooperatifin çalışmasına başlar
*/
public function start(mixed ...$args): mixed;
/**
* Kooperatifin çalışmasını geri yükler
*/
public function resume(mixed ...$args): mixed;
/**
* Kooperatifin kimliğini alır
*/
public function id(): int;
/**
* Kooperatif yok edildiğinde çağrılan geri çağırmayı ayarlar
*/
public static function defer(callable $callable): void;
/**
* Mevcut kooperatifi duraklatır
*/
public static function suspend(mixed $value = null): mixed;
/**
* Mevcut kooperatifi alır
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Mevcut ortamın bir kooperatif ortamı olup olmadığını kontrol eder
*/
public static function isCoroutine(): bool;
}
Kooperatif Hakkında
Avantajlar
PHP'nin kooperatifleri tanıtmasındaki en büyük fayda senkron bir şekilde asenkron kod yazmayı sağlamasıdır, bu sayede geri dönüş cehenneminden kaçınılır ve kodun okunabilirliği ve bakım kolaylığı artırılır.
Kooperatifler, IO yoğun işlerin esnekliğini önemli ölçüde artırabilir ve daha az süreçle daha fazla verim sağlanabilir.
Dezavantajlar
Ancak kooperatiflerin tanıtılmasıyla geliştiricilerin global değişken kirlenmesi, kaynak rekabeti ve üçüncü taraf kütüphanelerin dönüşümü gibi sorunlara dikkat etmesi gerekmektedir. Geliştirme ve bakım maliyetleri artarak zihin yükü belirgin şekilde artar.
Kooperatiflerin getirilmesi, kooperatif yaratma, zamanlama, yok etme, bağlantı havuzları gibi ek maliyetlere yol açar.
Yapılan yoğun performans testlerine dayanarak, CPU’nun tam kullanımı sağlandığında, kooperatiflerin tanıtılması durumunda aşırı performansın engelleyici IO’ya göre yaklaşık %10-20 oranında düştüğü görülmüştür.