Bagikan melalui


Pengantar Aktor Andal di Service Fabric

Reliable Actors adalah kerangka kerja aplikasi Service Fabric berdasarkan pola Aktor Virtual . RELIABLE Actors API menyediakan model pemrograman utas tunggal yang dibangun di atas jaminan skalabilitas dan keandalan yang disediakan oleh Service Fabric.

Apa itu Aktor?

Aktor adalah unit komputasi dan status independen yang terisolasi dengan eksekusi utas tunggal. Pola aktor adalah model komputasi untuk sistem bersamaan atau terdistribusi di mana sejumlah besar aktor ini dapat dijalankan secara bersamaan dan independen satu sama lain. Aktor dapat berkomunikasi satu sama lain dan mereka dapat membuat lebih banyak aktor.

Kapan Menggunakan Aktor-Aktor Andal

Service Fabric Reliable Actors adalah implementasi dari desain aktor. Seperti pola desain perangkat lunak apa pun, keputusan apakah akan menggunakan pola tertentu dibuat berdasarkan apakah masalah desain perangkat lunak sesuai dengan pola atau tidak.

Meskipun pola desain aktor dapat cocok dengan sejumlah masalah dan skenario sistem terdistribusi, pertimbangan yang cermat tentang batasan pola dan kerangka kerja yang menerapkannya harus dibuat. Sebagai panduan umum, pertimbangkan pola aktor untuk memodelkan masalah atau skenario Anda jika:

  • Ruang masalah Anda melibatkan sejumlah besar (ribuan atau lebih) unit status dan logika yang kecil, independen, dan terisolasi.
  • Anda ingin bekerja dengan objek berulir tunggal yang tidak memerlukan interaksi signifikan dari komponen eksternal, termasuk memeriksa status di antara sekumpulan pemeran.
  • Instans aktor Anda tidak akan memblokir penelepon dengan penundaan yang tidak dapat diprediksi karena melakukan operasi I/O.

Aktor pada Service Fabric

Dalam Service Fabric, aktor diimplementasikan dalam kerangka kerja Reliable Actors: Kerangka kerja aplikasi berbasis pola aktor yang dibangun di atas Service Fabric Reliable Services. Setiap layanan Reliable Actor yang Anda tulis sebenarnya adalah Reliable Service yang telah dipartisi dan bersifat stateful.

Setiap aktor didefinisikan sebagai instans dari jenis aktor, sama seperti objek .NET merupakan instans dari jenis .NET. Misalnya, mungkin ada jenis aktor yang mengimplementasikan fungsionalitas kalkulator dan mungkin ada banyak aktor jenis itu yang didistribusikan pada berbagai node di seluruh kluster. Setiap aktor tersebut diidentifikasi secara unik oleh ID aktor.

Masa Kehidupan Aktor

Aktor Service Fabric bersifat virtual, yang berarti bahwa masa pakainya tidak terkait dengan representasi dalam memori mereka. Akibatnya, mereka tidak perlu dibuat atau dihancurkan secara eksplisit. Runtime Reliable Actors secara otomatis mengaktifkan aktor saat pertama kali menerima permintaan untuk ID aktor tersebut. Jika aktor tidak digunakan untuk jangka waktu tertentu, Reliable Actors runtime akan melakukan pengumpulan sampah pada objek dalam memori. Ini juga akan menjaga pengetahuan tentang keberadaan aktor jika perlu diaktifkan kembali nanti. Untuk detail selengkapnya, lihat Siklus hidup aktor dan pengumpulan sampah.

Abstraksi masa eksistensi aktor virtual ini membawa beberapa batasan sebagai dampak dari model aktor virtual, dan sebenarnya implementasi Reliable Actors kadang-kadang menyimpang dari model ini.

  • Aktor diaktifkan secara otomatis (menyebabkan objek aktor dibuat) ketika pesan dikirim untuk pertama kalinya ke ID aktor. Setelah beberapa periode waktu, objek aktor adalah sampah yang dikumpulkan. Di masa depan, penggunaan ID aktor lagi akan mengakibatkan dibangunnya objek aktor baru. Status aktor keluar dari masa pakai objek saat disimpan di manajer status.
  • Memanggil metode apa pun dari aktor untuk ID aktor akan mengaktifkan aktor tersebut. Oleh karena itu, tipe aktor memiliki konstruktor mereka yang dipanggil secara implisit oleh runtime. Oleh karena itu, kode klien tidak dapat meneruskan parameter ke konstruktor jenis aktor, meskipun parameter dapat diteruskan ke konstruktor aktor oleh layanan itu sendiri. Hasilnya adalah bahwa aktor dapat dibangun dalam keadaan yang terinisialisasi sebagian pada waktu metode lain dipanggil padanya, jika aktor memerlukan parameter inisialisasi dari klien. Tidak ada titik masuk tunggal untuk aktivasi aktor dari klien.
  • Meskipun Reliable Actors secara implisit membuat objek aktor, Anda dapat menghapus aktor dan keadaannya secara eksplisit.

Distribusi dan failover

Untuk memberikan skalabilitas dan keandalan, Service Fabric mendistribusikan aktor di seluruh kluster dan secara otomatis memigrasikannya dari node yang gagal ke yang sehat sesuai kebutuhan. Ini adalah abstraksi atas Reliable Service yang dipartisi dan stateful. Distribusi, skalabilitas, keandalan, dan failover otomatis semuanya terjamin karena aktor berjalan di dalam Reliable Service stateful yang disebut Actor Service.

Aktor didistribusikan di seluruh partisi Actor Service, dan partisi tersebut didistribusikan di seluruh node dalam kluster Service Fabric. Setiap partisi layanan berisi satu set aktor. Service Fabric mengelola distribusi dan failover partisi layanan.

Misalnya, layanan actor dengan sembilan partisi yang disebarkan ke tiga node menggunakan penempatan partisi actor default akan didistribusikan dengan demikian:

Distribusi Reliable Actor

Actor Framework mengelola skema partisi dan pengaturan rentang kunci untuk Anda. Ini menyederhanakan beberapa pilihan tetapi juga membawa beberapa pertimbangan:

  • Reliable Services memungkinkan Anda memilih skema partisi, rentang kunci (saat menggunakan skema partisi rentang), dan jumlah partisi. Reliable Actor dibatasi untuk skema pemartisian rentang (skema Int64 yang seragam) dan mengharuskan Anda menggunakan rentang kunci Int64 lengkap.
  • Secara default, aktor ditempatkan secara acak ke dalam partisi yang menghasilkan distribusi yang seragam.
  • Karena aktor ditempatkan secara acak, seharusnya operasi aktor akan selalu memerlukan komunikasi jaringan, termasuk serialisasi dan deserialisasi data panggilan metode, menimbulkan latensi dan overhead.
  • Dalam skenario lanjutan, dimungkinkan untuk mengontrol penempatan partisi aktor dengan menggunakan ID aktor Int64 yang memetakan ke partisi tertentu. Namun, melakukannya dapat mengakibatkan distribusi aktor yang tidak seimbang di seluruh partisi.

Untuk informasi selengkapnya tentang bagaimana layanan aktor dipartisi, lihat konsep partisi untuk aktor.

Komunikasi aktor

Interaksi aktor didefinisikan dalam antarmuka yang dibagikan oleh aktor yang mengimplementasikan antarmuka, dan klien yang mendapatkan proksi ke aktor melalui antarmuka yang sama. Karena antarmuka ini digunakan untuk memanggil metode aktor secara asinkron, setiap metode pada antarmuka harus mengembalikan Tugas.

Pemanggilan metode dan responsnya pada akhirnya menghasilkan permintaan jaringan di seluruh kluster, sehingga argumen dan jenis hasil tugas yang dikembalikan harus dapat diserialisasikan oleh platform. Secara khusus, mereka harus memiliki kontrak data yang dapat diserialisasikan.

Wakil aktor

API klien Reliable Actors menyediakan komunikasi antara instans aktor dan klien aktor. Untuk berkomunikasi dengan aktor, klien membuat objek proksi aktor yang mengimplementasikan antarmuka aktor. Klien berinteraksi dengan aktor dengan memanggil metode pada objek proksi. Proksi aktor dapat digunakan untuk komunikasi klien-ke-aktor dan aktor-ke-aktor.

// Create a randomly distributed actor ID
ActorId actorId = ActorId.CreateRandom();

// This only creates a proxy object, it does not activate an actor or invoke any methods yet.
IMyActor myActor = ActorProxy.Create<IMyActor>(actorId, new Uri("fabric:/MyApp/MyActorService"));

// This will invoke a method on the actor. If an actor with the given ID does not exist, it will be activated by this method call.
await myActor.DoWorkAsync();
// Create actor ID with some name
ActorId actorId = new ActorId("Actor1");

// This only creates a proxy object, it does not activate an actor or invoke any methods yet.
MyActor myActor = ActorProxyBase.create(actorId, new URI("fabric:/MyApp/MyActorService"), MyActor.class);

// This will invoke a method on the actor. If an actor with the given ID does not exist, it will be activated by this method call.
myActor.DoWorkAsync().get();

Perhatikan bahwa dua bagian informasi yang digunakan untuk membuat objek proksi aktor adalah ID aktor dan nama aplikasi. ID aktor secara unik mengidentifikasi aktor, sementara nama aplikasi mengidentifikasi aplikasi Service Fabric tempat aktor disebarkan.

Kelas ActorProxy(C#) / ActorProxyBase(Java) di sisi klien melakukan resolusi yang diperlukan untuk menemukan actor by ID dan membuka saluran komunikasi dengannya. Ini juga mencoba menemukan aktor dalam kasus kegagalan komunikasi dan failover. Akibatnya, pengiriman pesan memiliki karakteristik berikut:

  • Pengiriman pesan adalah upaya terbaik.
  • Aktor mungkin menerima pesan duplikat dari klien yang sama.

Konkurensi

Runtime Aktor Andal menyediakan model akses berbasis giliran yang sederhana untuk mengakses metode-metode aktor. Ini berarti bahwa hanya satu utas saja yang dapat aktif di dalam kode objek aktor pada satu waktu. Akses berbasis giliran sangat menyederhanakan sistem bersamaan karena tidak perlu mekanisme sinkronisasi untuk akses data. Ini juga berarti sistem harus dirancang dengan pertimbangan khusus untuk sifat akses utas tunggal dari setiap instans aktor.

  • Satu instans aktor tidak dapat memproses lebih dari satu permintaan pada satu waktu. Instans aktor dapat menyebabkan hambatan throughput jika diharapkan untuk menangani permintaan secara bersamaan.
  • Aktor dapat saling kebuntuan jika ada permintaan melingkar antara dua aktor sementara permintaan eksternal dibuat untuk salah satu aktor secara bersamaan. Runtime aktor akan secara otomatis mengatur batas waktu pada panggilan aktor dan melemparkan pengecualian kepada pemanggil untuk mencegah kemungkinan situasi kebuntuan.

Komunikasi Aktor Andal

Akses berbasis giliran

Giliran terdiri dari pelaksanaan lengkap dari suatu metode aktor sebagai respons terhadap permintaan dari aktor atau klien lain, atau pelaksanaan lengkap panggilan balik timer/pengingat. Meskipun metode dan panggilan balik ini bersifat asinkron, runtime Actor tidak menyisipkan atau mencampurkan mereka. Giliran harus sepenuhnya selesai sebelum giliran baru diizinkan. Dengan kata lain, metode aktor atau panggilan balik timer/pengingat yang saat ini dijalankan harus sepenuhnya selesai sebelum panggilan baru ke metode atau panggilan balik diizinkan. Metode atau panggilan balik dianggap telah selesai jika eksekusi telah kembali dari metode atau panggilan balik dan tugas yang dikembalikan oleh metode atau panggilan balik telah selesai. Perlu ditekankan bahwa konkurensi berbasis giliran dihormati bahkan di berbagai metode, timer, dan panggilan balik.

Runtime Actors memberlakukan konkurensi berbasis giliran dengan memperoleh kunci per aktor di awal giliran dan melepaskan kunci di akhir giliran. Dengan demikian, konkurensi berbasis giliran diberlakukan berdasarkan per-aktor dan bukan di seluruh aktor. Metode aktor dan panggilan balik timer/pengingat dapat dijalankan secara bersamaan atas nama aktor yang berbeda.

Contoh berikut mengilustrasikan konsep di atas. Pertimbangkan jenis aktor yang mengimplementasikan dua metode asinkron (misalnya, Method1 dan Method2), timer, dan pengingat. Diagram di bawah ini menunjukkan contoh garis waktu untuk eksekusi metode dan panggilan balik ini atas nama dua aktor (ActorId1 dan ActorId2) yang termasuk dalam jenis aktor ini.

Konkurensi dan akses berbasis giliran runtime Reliable Actor

Diagram ini mengikuti konvensi berikut:

  • Setiap garis vertikal menunjukkan alur logis eksekusi metode atau panggilan balik atas nama aktor tertentu.
  • Peristiwa yang ditandai pada setiap garis vertikal terjadi dalam urutan kronologis, dengan peristiwa yang lebih baru terjadi di bawah yang lebih lama.
  • Warna yang berbeda digunakan untuk garis waktu yang sesuai dengan aktor yang berbeda.
  • Penyorotan digunakan untuk menunjukkan lamanya waktu kunci setiap aktor dipegang demi suatu metode atau pemanggilan balik.

Beberapa poin penting yang perlu dipertimbangkan:

  • Saat Method1 mengeksekusi atas nama ActorId2 sebagai respons terhadap permintaan klien xyz789, permintaan klien lain (abc123) tiba yang juga mengharuskan Method1 dijalankan oleh ActorId2. Namun, eksekusi kedua Method1 tidak dimulai sampai eksekusi sebelumnya selesai. Demikian pula, pengingat yang terdaftar oleh ActorId2 diaktifkan saat Method1 sedang dijalankan sebagai respons terhadap permintaan klien xyz789. Panggilan balik pengingat dijalankan hanya setelah kedua eksekusi Method1 selesai. Semua ini disebabkan oleh konkurensi berbasis giliran yang diberlakukan untuk ActorId2.
  • Demikian pula, konkurensi berbasis giliran juga diberlakukan untuk ActorId1, seperti yang ditunjukkan oleh eksekusi Method1, Method2, dan panggilan balik timer atas nama ActorId1 yang terjadi secara serial.
  • Eksekusi Method1 atas nama ActorId1 tumpang tindih dengan eksekusinya atas nama ActorId2. Ini karena konkurensi berbasis giliran hanya diberlakukan dalam aktor dan bukan antar aktor.
  • Dalam beberapa metode/eksekusi panggilan balik, Task(C#) / CompletableFuture(Java) yang dikembalikan oleh metode/panggilan balik selesai setelah metode kembali. Dalam beberapa kasus lain, operasi asinkron telah selesai pada saat metode/panggilan balik kembali. Dalam kedua kasus, kunci per aktor dilepaskan hanya setelah metode/panggilan balik telah selesai dan operasi asinkron berakhir.

Masuknya kembali

Runtime Actor memungkinkan masuknya kembali secara default. Ini berarti bahwa jika metode aktor Actor A memanggil metode pada Actor B, yang pada gilirannya memanggil metode lain pada Actor A, metode tersebut diizinkan untuk dijalankan. Ini karena ini adalah bagian dari konteks rantai panggilan logis yang sama. Semua panggilan timer dan pengingat dimulai dengan konteks panggilan logis baru. Lihat reentrancy Reliable Actors untuk informasi lebih lanjut.

Cakupan jaminan konkurensi

Runtime Actors memberikan jaminan konkurensi ini dalam situasi di mana ia mengontrol pemanggilan metode ini. Misalnya, ini memberikan jaminan untuk pemanggilan metode yang dilakukan untuk merespons permintaan klien, serta untuk panggilan balik timer dan pengingat. Namun, jika kode aktor secara langsung memanggil metode ini di luar mekanisme yang disediakan oleh runtime Actor, maka runtime tidak dapat memberikan jaminan konkurensi apa pun. Misalnya, jika metode dipanggil dalam konteks beberapa tugas yang tidak terkait dengan tugas yang dikembalikan oleh metode aktor, maka runtime tidak dapat memberikan jaminan konkurensi. Jika metode dipanggil dari utas yang dibuat aktor sendiri, maka runtime juga tidak dapat memberikan jaminan konkurensi. Oleh karena itu, untuk melakukan operasi latar belakang, aktor harus menggunakan timer aktor dan pengingat aktor yang menghormati konkurensi berbasis giliran.

Langkah berikutnya

Mulailah dengan membangun layanan Reliable Actors pertama Anda: