Bermain dengan Swoole, PHP Async, Event Driven I/O

Ahmad Oriza 6 April 2020

Bermain dengan Swoole, PHP Async, Event Driven I/O

Optimasi

Ketika aplikasi kita bermasalah dengan performa (Konsumsi RAM,CPU). Disitulah saatnya kita memikirkan untuk optimasi. Biasanya terasa jika user semakin banyak, sehingga membuat server sibuk.

Codepolitan sendiri pernah mengalami hal ini, memang users kita tidak terlalu banyak, cuma 110 ribuan registered, cuma server kami harus menangani 100 an orang aktif dalam waktu bersamaan, request resource bergantian cukup membuat repot.

Belajar optimasi platform cukup menyenangkan, lebih asik dari membuat fitur itu sendiri menurut saya. Yang saya pahami terdapat beberapa cara untuk mengoptimasi arsitektur :

- Optimasi di sisi kode, cek kode mana yang makan proses tinggi, lalu refactor.
- Pisahkan kode jadi service tersendiri di server berbeda.
- Pisahkan beberapa proses jadi Queue based, setting worker. 
- Tambahkan resource CPU/RAM.
- Pasang cache (Redis, Varnish dsb) untuk query yang makan resources.
- Pasang cache sisi DNS, Cloudflare terbaik.
- Load balancing server, bikin banyak instance dengan 1 pintu masuk.
- Pisah app dengan db server.

Dan masih banyak lagi.

PHP Async? What?!

Pastinya kamu sudah sering dengan istilah Async. Yup ! Javascript. Yang terkenal dengan NodeJs nya

Ternyata optimasi juga bisa dilakukan dengan cara yang agak extreem di PHP. Yaitu mengubah paradigma koding kita yang tadinya prosedural/oop menjadi Async dengan menggunakan Swoole. Normalnya proses PHP itu sifatnya top to down, blocking.

Mau coba?

Instalasi Swoole

Instalasi Swoole relatif sederhana. Swoole butuh PECL untuk instalasi. Dia berdiri sebagai PHP C Extension. Teman-teman yang belum familiar dengan PECL bisa baca di https://pecl.php.net. PECL/PEAR adalah dependency manager di level php extension.

Yang perlu kamu siapkan :

1. OS, distro Ubuntu/Debian, Cloud based / Vm (docker/vm/vagrant) tidak masalah.
2. Install PECL/PEAR jika belum punya. Karena Swoole akan menjadi PHP Extension. Ketik `sudo apt install php-pear`
3. Install PHP Dev `sudo apt install php-dev`. Di dalam module dev ini ada `PHPize`, Swoole butuh buat compile C Extension jadi binary pakai PHPize.
4. Jalankan `sudo pecl install swoole`.

Terakhir, aktifkan ekstensinya di php.ini, buka filenya lalu tuliskan :

extension=swoole.so

Path php.ini pada laptop saya berada di /etc/php/7.2/cli/php.ini. Silahkan cocokan path dengan instalasi PHP pada komputer kamu.

Sampai disini harusnya Swoole module sudah berjalan.

PHP + Swoole

Kita coba buat program sederhana, hanya mendengarkan request dan mengeluarkan output Hello World. Buatlah file baru dimanapun kamu mau, lalu ketikan kode ini :

<?php // Konstruktor Swoole, param pertama host, kedua port. $server = new Swoole\HTTP\Server("127.0.0.1", 8080); // Define event on start $server->on("start", function (Swoole\Http\Server $server) { echo "Swoole http server is started at http://127.0.0.1:8080\n"; }); // Define event on request $server->on("request", function (Swoole\Http\Request $request, Swoole\Http\Response $response) { $response->header("Content-Type", "text/plain"); $response->end("Hello World\n"); }); // Jalankan server. $server->start();

Sekarang jalankan file tersebut dengan perintah :

php path/to/latihan-swoole.php

Maka output yang akan muncul seperti ini :

Swoole http server is started at http://127.0.0.1:8080

Sekarang silahkan akses URL http://127.0.0.1:8080 via CLI Curl atau buka browsernya, dan kamu akan melihat output Hello World

Penjelasan Kode

Kita instansiasi objek Swoole dulu. Swoole disini sudah terinstall sebagai PHP extension, sehingga kita tidak perlu lagi include class Swoole. Lanjut tulis method on dengan parameter pertama berupa event, dan kedua berupa closure. Method on ini akan dibaca Swoole sebagai event handler. Disitu bisa dilihat ada 2 event :

1. On start, disini ketika server start, kita tulis supaya menampilkan output server start.
2. On request, disini berguna ketika ada request masuk, tampilkan output sample.

Saat server start, echo output CLI, dan saat ada request masuk, balas dengan Hello World.

Penulisan kode sudah sangat beda dengan native PHP bukan? sudah mirip kode pada platform NodeJs/Express. PHP Rasa Js ?!

Konsep

Bagaimana kode tadi diproses?

Kode yang dijalankan diatas Swoole akan dijalakan sebagai PHP mod CLI. Tentunya kamu sudah pernah mencoba perintah ini :

php latihan.php

Yup itu adalah mode CLI dari PHP. Biasanya setting php.ini pun terletak pada folder yang berbeda dengan versi Apache/Nginx. Pada lingkungan tradisional, misal pada Apache/Nginx, PHP akan dijalankan dengan PHP FPM (FastCGI Process Manager) dengan gambaran proses sebagai berikut :

HTTP request -> Apache -> PHP FPM (Opcode, Opcache, Zend VM) -> Output -> Apache -> HTTP response

Setiap request akan masuk dulu ke Apache sebagai wrapper protokol. Yang menjalankan eksekusi PHP adalah Apache sendiri. Setelah menjalankan PHP, Apache akan mengeluarkan output pada client. Yang membuat PHP bisa berkomunikasi dengan Apache adalah CGI (Common Gateway Interface).

Sekarang mari kita lihat proses yang terjadi ketika menggunakan Swoole :

Protocol request -> Swoole Server (Master -> Manager -> Worker -> Task Worker) -> Output -> Protocol response 

Disini tidak perlu lagi ada peran server pihak ketiga, disini proses sudah menggunakan menggunakan Swoole Server. Server tersebut menjadi entry point dari request, dan kemudian setiap request diserahkan ke manager.

Manager akan membagikan task/request ke task worker. Saya kurang tahu berapa task worker yang ada secara default. Kemungkinan sudah dibuat sedemikian rupa sesuai dengan jumlah request.

Image

Prinsip worker ini mungkin sudah bisa dibayangkan oleh teman teman yang pernah membuat Queue system.

Protokol yang didukung Swoole antara lain :

- TCP
- UDP
- HTTP2
- WebSocket

Yang membuat semakin menarik adalah server ini juga bisa mengolah websocket. Dia bisa menggantikan websocket server seperti Socket IO atau Rachet PHP. Mungkin suatu saat ada orang yang membuat wrappernya, ataukah kamu ingin buat?

Benchmark

Saya disini mencoba benchmark PHP dengan/tanpa Swoole di lingkungan lokal. Laptop saya Lenovo D330, WSL Ubuntu, Ram 4gb, CPU Intel Celeron.

Saya run dengan Apache Benchmark menembak URL lokal dengan concurrent 1000 sebanyak 1000 kali.

ab -c 1000 -n 1000 http://localhost:8000/hello.php

Hasil yang didapatkan :

Image
PHP mengabiskan waktu 1.6 detik.
PHP Swoole menghabiskan waktu 0.7 detik.

Menarik bukan?

Referensi :

https://samsonasik.wordpress.com/2020/04/05/using-swoole-in-mezzio-application-with-sdebug/ https://www.swoole.co.uk/