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 Swoole Swow Fiber sürücülerini destekler.
  • Fiber sürücüsü kullanıyorsanız, composer require revolt/event-loop yüklemeniz gerekir.
  • Swoole veya Swow sü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, Swoole ve Swow gibi 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.
  • Swoole Swow Fiber sürücüleri kullanıldığında, workerman her seferinde onWorkerStart onMessage onConnect onClose gibi 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.