Topik ini memberikan gambaran menyeluruh tentang model actor, yaitu state yang terenkapsulasi, pesan asinkron, dan ketiadaan memori bersama, kemudian menjelaskan sejarah singkat Akka serta perubahan lisensinya pada tahun 2022. Apache Pekko diperkenalkan sebagai fork komunitas yang memelihara ekosistem actor di JVM di bawah Apache License 2.0. Sebuah contoh Pekko typed yang kecil namun utuh memperlihatkan cara actor merespons permintaan, dan bagian akhir memberikan panduan kapan actor perlu dipertimbangkan dibandingkan dengan Future.
Model actor dalam satu gambar besar#
Model actor (actor model) adalah skema konkurensi yang membagi program menjadi unit-unit kecil bernama actor. Setiap actor memiliki state sendiri yang terenkapsulasi, artinya tidak ada bagian program lain yang dapat membaca atau mengubah state itu secara langsung. Satu-satunya jalan masuk adalah pesan (message) yang dikirim secara asinkron, yakni pengirim melanjutkan pekerjaannya tanpa menunggu pesan diterima.
Setiap actor memproses pesan dari kotak suratnya (mailbox) satu per satu. Sifat ini membuat actor berperilaku layaknya unit pemrosesan tunggal, sehingga state internalnya tidak pernah diakses bersamaan oleh dua alur eksekusi. Karena tidak ada memori bersama, tidak ada pula kunci (lock), variabel atomik, atau mekanisme pengamanan lain yang biasanya mengiringi pemrograman alur bersama (shared-memory threading). Kesalahan seperti balapan data (data race) dan kebuntuan (deadlock) tidak muncul pada bagian yang dikelola oleh model ini.
Actor juga dapat mengubah perilakunya (behavior) di antara pesan. Perilaku adalah nilai yang menentukan cara actor merespons pesan berikutnya, sehingga mesin status (state machine) dapat dimodelkan secara alami, misalnya actor yang berpindah dari keadaan menunggu ke keadaan memproses. Seluruh pustaka actor di JVM, termasuk Akka dan Apache Pekko, dibangun di atas prinsip-prinsip yang sama.
Dari Akka ke Apache Pekko#
Akka adalah pustaka model actor untuk JVM yang dirilis pada tahun 2009 dan menjadi implementasi yang paling luas digunakan di ekosistem Scala. Ribuan aplikasi produksi mengandalkannya, dan dokumentasinya menjadi rujukan baku untuk pola-pola actor. Selama lebih dari satu dekade, lisensinya adalah Apache License 2.0, sehingga penggunaan komersial maupun nonkomersial berjalan tanpa hambatan.
Situasi berubah pada September 2022 ketika Lightbend selaku pengelola proyek mengubah lisensi Akka menjadi Business Source License 1.1 (BSL) untuk versi 2.7 ke atas. Lisensi BSL memperbolehkan penggunaan gratis untuk pengembangan, sedangkan penggunaan dalam produksi dikenai syarat, misalnya batas pendapatan tahunan perusahaan atau kewajiban membeli lisensi komersial. Kode sumber tetap terbuka untuk dilihat, tetapi proyek tersebut tidak lagi memenuhi definisi open source.
Kepastian lisensi itu mendorong lahirnya Apache Pekko, fork komunitas yang dibentuk dari basis kode Akka 2.6 dan ditempatkan di bawah naungan Apache Software Foundation. Pekko dilisensikan dengan Apache License 2.0 dan dipelihara oleh komunitas secara terbuka. API-nya meniru API Akka 2.6, sehingga kode yang sudah ada dapat dimigrasikan dengan mengganti namespace akka menjadi org.apache.pekko. Rilis 1.0.0 muncul pada pertengahan 2023, dan lini 1.1.x terus dikembangkan dengan dukungan lintas versi Scala, termasuk 2.13 dan 3.
Contoh kecil Pekko typed#
Varian typed dari Pekko menerapkan protokol pesan pada tingkat tipe data, yaitu setiap actor hanya menerima pesan dari satu tipe yang dideklarasikan secara eksplisit. Contoh berikut mendefinisikan actor penyapa dengan satu pesan bernama Sapa. Pesan itu membawa nama serta ActorRef balasan, dan program utama memperoleh jawaban melalui ask pattern.
//> using dep org.apache.pekko::pekko-actor-typed:1.1.4
//> using dep org.slf4j:slf4j-nop:2.0.17
import org.apache.pekko.actor.typed.{ActorRef, ActorSystem}
import org.apache.pekko.actor.typed.scaladsl.Behaviors
import org.apache.pekko.actor.typed.scaladsl.AskPattern._
import org.apache.pekko.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
object Penyapa:
sealed trait Perintah
final case class Sapa(nama: String, balasKe: ActorRef[String]) extends Perintah
val penyapa: Behaviors.Receive[Perintah] =
Behaviors.receiveMessage:
case Sapa(nama, balasKe) =>
balasKe ! s"Halo, $nama!"
Behaviors.same
@main def lanskap(): Unit =
val sistem = ActorSystem(Penyapa.penyapa, "sapaan")
implicit val timeout: Timeout = Timeout(3.seconds)
implicit val scheduler: org.apache.pekko.actor.typed.Scheduler = sistem.scheduler
val jawaban1 = Await.result(sistem.ask(ref => Penyapa.Sapa("Dewi", ref)), 3.seconds)
val jawaban2 = Await.result(sistem.ask(ref => Penyapa.Sapa("Ali", ref)), 3.seconds)
println(jawaban1)
println(jawaban2)
sistem.terminate()scala-cli run penyapa.scalaHalo, Dewi!
Halo, Ali!Bagian object Penyapa mendefinisikan protokol pesan sebagai sealed trait Perintah, sehingga kompiler mengetahui seluruh jenis pesan yang mungkin diterima actor. Pesan Sapa menyertakan ActorRef[String] sebagai alamat balasan, dan actor mengirim jawabannya dengan operator !. Metode Behaviors.receiveMessage mengembalikan Behaviors.same, artinya actor tetap menggunakan perilaku yang sama untuk pesan berikutnya.
Pada program utama, ask pattern mengirim pesan dan mengembalikan Future[String], kemudian Await.result menunggu jawabannya hingga batas waktu tiga detik. Dua panggilan ask dieksekusi secara berurutan dan masing-masing ditunggu sebelum dicetak, sehingga urutan keluaran terjamin. Pemanggilan sistem.terminate() menghentikan sistem actor agar proses program berakhir dengan rapi.
Kapan actor dipertimbangkan dibanding Future#
Future mewakili satu nilai hasil yang akan tersedia di kemudian hari, sehingga cocok untuk operasi asinkron yang dieksekusi satu kali, selesai, lalu hasilnya dikonsumsi. Actor berada pada kategori lain, yaitu entitas berumur panjang yang terus menerima pesan sepanjang hidupnya. Actor menyimpan state di antara pesan-pesan itu dan memperbaruinya secara aman karena hanya satu pesan yang diproses pada satu waktu.
| Aspek | Future | Actor |
|---|---|---|
| Umur hidup | satu kali eksekusi, lalu hasilnya dikonsumsi | berumur panjang, merespons pesan terus-menerus |
| State | tidak menyimpan state di antara operasi | state terenkapsulasi dan diperbarui melalui pesan |
| Komposisi | transformasi dan for-comprehension | protokol pesan dan pengiriman di antara actor |
| Kesesuaian | paralelisasi perhitungan, pemanggilan layanan | entitas yang menyimpan state, antrean, koordinasi banyak pesan |
Aturan praktisnya sederhana. Gunakan Future untuk alur asinkron sederhana yang tidak menyimpan state, dan pertimbangkan actor apabila state bersama yang harus dilindungi semakin kompleks atau jumlah entitas konkuren yang berumur panjang semakin besar. Banyak aplikasi nyata mengombinasikan keduanya, yaitu Future untuk perhitungan dan pemanggilan layanan, sedangkan actor untuk menyimpan state dan mengatur koordinasi.
Ringkasan#
- Model actor mengenkapsulasi state dalam unit yang memproses pesan asinkron satu per satu, sehingga tidak ada memori bersama, tidak ada kunci, dan balapan data tidak muncul.
- Akka mengubah lisensinya menjadi BSL 1.1 pada tahun 2022, dan Apache Pekko melanjutkan ekosistem tersebut sebagai fork komunitas di bawah Apache License 2.0 dengan API yang setara.
- Pekko typed mendeklarasikan protokol pesan bertipe, dan ask pattern mengembalikan
Futureyang dapat ditunggu denganAwaituntuk memperoleh hasil secara deterministik. - Future cocok untuk operasi asinkron sekali eksekusi, sedangkan actor cocok untuk entitas berumur panjang yang menyimpan state.
Referensi#
- Pekko Typed — Apache Pekko Documentation — Ringkasan model actor typed beserta prinsip dan modulnya.
- Actors — Apache Pekko Documentation — Anatomi behavior, ActorRef, dan pengiriman pesan pada Pekko typed.
- Interaction Patterns — Apache Pekko Documentation — Pola request-response dengan ask beserta variasinya.
- Migration Guides — Apache Pekko Documentation — Panduan resmi migrasi kode Akka ke Apache Pekko.