Hollywood adalah mesin aktor yang sangat cepat untuk kecepatan dan aplikasi latensi rendah. Pikirkan tentang server game, pialang iklan, mesin perdagangan, dll ... Ini dapat menangani 10 juta pesan di bawah 1 detik .
Model aktor adalah model komputasi yang digunakan untuk membangun sistem yang sangat bersamaan dan terdistribusi. Itu diperkenalkan oleh Carl Hewitt pada tahun 1973 sebagai cara untuk menangani sistem yang kompleks dengan cara yang lebih scalable dan toleran terhadap kesalahan.
Dalam model aktor, blok bangunan dasar adalah aktor, kadang -kadang disebut sebagai penerima di Hollywood, yang merupakan unit komputasi independen yang berkomunikasi dengan aktor lain dengan bertukar pesan. Setiap aktor memiliki keadaan dan perilakunya sendiri, dan hanya dapat berkomunikasi dengan aktor lain dengan mengirim pesan. Paradigma yang meletuskan pesan ini memungkinkan sistem yang sangat terdesentralisasi dan toleran terhadap kesalahan, karena aktor dapat terus beroperasi secara mandiri bahkan jika aktor lain gagal atau menjadi tidak tersedia.
Aktor dapat diatur ke dalam hierarki, dengan aktor tingkat tinggi mengawasi dan mengoordinasikan aktor tingkat bawah. Ini memungkinkan untuk penciptaan sistem kompleks yang dapat menangani kegagalan dan kesalahan dengan cara yang anggun dan dapat diprediksi.
Dengan menggunakan model aktor dalam aplikasi Anda, Anda dapat membangun sistem yang sangat terukur dan toleran terhadap kesalahan yang dapat menangani sejumlah besar pengguna bersamaan dan interaksi yang kompleks.
Pengiriman pesan yang dijamin pada kegagalan aktor (mekanisme buffer)
Fire & Forget atau Request & Response Adesaging, atau keduanya
DRPC berkinerja tinggi sebagai lapisan transportasi
Buffer proto yang dioptimalkan tanpa refleksi
Ringan dan sangat dapat disesuaikan
Dukungan klaster untuk menulis aktor penemuan diri terdistribusi
make bench
spawned 10 engines spawned 2000 actors per engine Send storm starting, will send for 10s using 20 workers Messages sent per second 3244217 .. Messages sent per second 3387478 Concurrent senders: 20 messages sent 35116641, messages received 35116641 - duration: 10s messages per second: 3511664 deadletters: 0
go get github.com/anthdm/hollywood/...
Hollywood membutuhkan Golang Versi
1.21
Kami sarankan Anda memulai dengan menulis beberapa contoh yang berjalan secara lokal. Berjalan secara lokal sedikit lebih sederhana karena kompiler dapat mengetahui jenis yang digunakan. Saat berjalan dari jarak jauh, Anda harus memberikan definisi protobuffer untuk kompiler.
Mari kita pergi melalui pesan Hello World. Contoh lengkap tersedia di folder Hello World. Mari kita mulai di Main:
engine, err: = Actor.Newengine (Actor.NewengineConfig ())
Ini menciptakan mesin baru. Mesin adalah inti dari Hollywood. Ini bertanggung jawab untuk pemijahan aktor, mengirim pesan dan menangani siklus hidup aktor. Jika Hollywood gagal membuat mesin itu akan mengembalikan kesalahan. Untuk pengembangan, Anda tidak boleh menggunakan untuk meneruskan opsi apa pun ke mesin sehingga Anda dapat melewati nol. Kami akan melihat opsi nanti.
Selanjutnya kita perlu membuat aktor. Ini beberapa kali disebut sebagai Receivers setelah antarmuka yang harus mereka terapkan. Mari kita buat aktor baru yang akan mencetak pesan saat menerima pesan.
pid: = engine.spawn (newhelloer, "hello")
Ini akan menyebabkan mesin memunculkan aktor dengan ID "Halo". Aktor akan dibuat oleh fungsi newHelloer yang disediakan. ID harus unik. Ini akan mengembalikan pointer ke PID. PID adalah pengidentifikasi proses. Ini adalah pengidentifikasi unik untuk aktor. Sebagian besar waktu Anda menggunakan PID untuk mengirim pesan ke aktor. Terhadap sistem jarak jauh Anda akan menggunakan ID untuk mengirim pesan, tetapi pada sistem lokal Anda kebanyakan Anda menggunakan PID.
Mari kita lihat fungsi newHelloer dan aktornya kembali.
ketik helloer struct {} func newhelloer () actor.receiver {return & helloer {}
} Cukup sederhana. Fungsi newHelloer mengembalikan aktor baru. Aktor adalah struct yang mengimplementasikan aktor. Mari kita lihat metode Receive .
ketik pesan struct {} func (h *helloer) terima (ctx *actor.context) {switch msg: = ctx.message (). (type) {case actor.initialized: fmt.println ("Helloer telah diinisialisasi") case Actor.Started: fmt.println ("Helloer telah memulai") case Actor.Stopped: fmt.println ("Helloer telah berhenti") Kasus *Pesan: fmt.println ("Hello World", msg.data)
}
}Anda dapat melihat kami mendefinisikan struct pesan. Ini adalah pesan yang akan kami kirim ke aktor nanti. Metode menerima juga menangani beberapa pesan lainnya. Pesan siklus hidup ini dikirim oleh mesin ke aktor, Anda akan menggunakannya untuk menginisialisasi aktor Anda
Mesin melewati aktor.context ke metode Receive . Konteks ini berisi pesan, PID pengirim dan beberapa dependensi lain yang dapat Anda gunakan.
Sekarang, mari kita kirim pesan ke aktor. Kami akan mengirim message , tetapi Anda dapat mengirim semua jenis pesan yang Anda inginkan. Satu -satunya persyaratan adalah bahwa aktor harus dapat menangani pesan tersebut. Agar pesan dapat melintasi kawat, mereka harus dapat di -serial. Agar protobuf dapat membuat serialisasi pesan, itu harus menjadi penunjuk. Pesan lokal bisa dari jenis apa pun.
Akhirnya, mari kita kirim pesan ke aktor.
engine.send (pid, "halo dunia!")
Ini akan mengirim pesan ke aktor. Hollywood akan merutekan pesan ke aktor yang benar. Aktor kemudian akan mencetak pesan ke konsol.
Folder Contoh adalah tempat terbaik untuk belajar dan menjelajahi Hollywood lebih lanjut.
Saat Anda menelurkan aktor, Anda harus memberikan fungsi yang mengembalikan aktor baru. Karena aktor bertelur, ada beberapa opsi yang dapat Anda berikan.
E.Spawn (newfoo, "myactorname")
Terkadang Anda ingin memberikan argumen kepada konstruktor aktor. Ini dapat dilakukan dengan menggunakan penutupan. Ada contoh ini dalam contoh permintaan. Mari kita lihat kodenya.
Konstruktor default akan terlihat seperti ini:
funce newnameresponder () actor.receiver {return & nameresponder {name: "noname"}
}Untuk membangun aktor baru dengan nama Anda dapat melakukan hal berikut:
funce newcustomnameresponder (name string) actor.producer {return func () actor.receiver {return & nameresponder {name}
}
}Anda kemudian dapat menelurkan aktor dengan kode berikut:
pid: = engine.spawn (newcustomnameresponder ("anthony"), "name-responder") E.Spawn (newfoo, "myactorname", aktor.withmaxrestarts (4), aktor.withinboxsize (1024 * 2), aktor.withid ("bar"),
)
)Pilihannya harus cukup jelas. Anda dapat menetapkan jumlah maksimum restart, yang memberi tahu mesin berapa kali aktor yang diberikan harus dimulai kembali jika terjadi kepanikan, ukuran kotak masuk, yang menetapkan batas tentang bagaimana dan pesan yang tidak diproses dapat dipegang sebelum akan mulai sebelum akan dimulai sebelum akan mulai mulai untuk memblokir.
Aktor tanpa negara dapat ditanamkan sebagai fungsi, karena cepat dan sederhana.
e.spawnfunc (func (c *actor.context) {switch msg: = c.message (). (type) {case actor.started: fmt.println ("start") _ = msg
}
}, "foo")Aktor dapat berkomunikasi satu sama lain melalui jaringan dengan paket jarak jauh. Ini bekerja sama dengan aktor lokal tetapi "Over the Wire". Hollywood mendukung serialisasi dengan protobuf.
remote.new () mengambil alamat mendengarkan dan struct.config remote.
Anda akan membuat instantiate remote baru dengan kode berikut:
tlsconfig: = tlsconfig: & tls.config {sertifikat: [] tls.certificate {cert},
} config: = remote.newconfig (). withtls (tlsconfig) remote: = remote.new ("0.0.0.0:2222", config) engine, err: = Actor.Newengine (Actor.NewEngineConfig (). WithRemote (remote) )Lihatlah contoh aktor jarak jauh dan klien obrolan & server untuk informasi lebih lanjut.
Dalam sistem produksi pada akhirnya akan salah. Aktor akan macet, mesin akan gagal, pesan akan berakhir di antrian tunet. Anda dapat membangun perangkat lunak yang dapat menangani acara ini dengan cara yang anggun dan dapat diprediksi dengan menggunakan aliran acara.
EventStream adalah abstraksi yang kuat yang memungkinkan Anda membangun sistem yang fleksibel dan dapat dicolokkan tanpa ketergantungan.
Berlangganan aktor apa pun ke berbagai daftar acara sistem
Siarkan acara khusus Anda ke semua pelanggan
Perhatikan bahwa peristiwa yang tidak ditangani oleh aktor mana pun akan dijatuhkan. Anda harus memiliki aktor yang berlangganan aliran acara untuk menerima acara. Sebagai minimum, Anda ingin menangani DeadLetterEvent . Jika Hollywood gagal mengirimkan pesan ke aktor, itu akan mengirim DeadLetterEvent ke aliran acara.
Peristiwa apa pun yang memenuhi antarmuka actor.LogEvent akan dicatat ke logger default, dengan tingkat keparahan, pesan, dan atribut acara yang ditetapkan oleh metode actor.LogEvent log() .
actor.ActorInitializedEvent , seorang aktor telah diinisialisasi tetapi tidak memproses actor.Started message
actor.ActorStartedEvent , seorang aktor telah memulai
actor.ActorStoppedEvent , seorang aktor telah berhenti
actor.DeadLetterEvent , sebuah pesan tidak disampaikan kepada seorang aktor
actor.ActorRestartedEvent , seorang aktor telah memulai kembali setelah kecelakaan/panik.
actor.RemoteUnreachableEvent , mengirim pesan melalui kawat ke remote yang tidak dapat dijangkau.
cluster.MemberJoinEvent , anggota baru bergabung dengan cluster
cluster.MemberLeaveEvent , anggota baru meninggalkan cluster
cluster.ActivationEvent , aktor baru diaktifkan pada cluster
cluster.DeactivationEvent , seorang aktor dinonaktifkan pada cluster
Ada contoh pemantauan EventStream yang menunjukkan kepada Anda cara menggunakan aliran acara. Ini fitur dua aktor, satu tidak stabil dan akan macet setiap detik. Aktor lain berlangganan aliran acara dan memelihara beberapa konter untuk berbagai acara seperti crash, dll.
Aplikasi akan berjalan selama beberapa detik dan racun aktor yang tidak stabil. Ini akan menanyakan monitor dengan permintaan. Saat aktor melayang di dalam mesin, ini adalah cara Anda berinteraksi dengan mereka. Utama kemudian akan mencetak hasil kueri dan aplikasi akan keluar.
Kami menggunakan pola opsi fungsi. Semua opsi fungsi ada dalam paket aktor dan memulai nama mereka dengan "engineOpt". Saat ini, satu -satunya pilihan adalah memberikan remote. Ini dilakukan oleh
r: = remote.new (remote.config {listenaddr: addr}) engine, err: = actor.newengine (Actor.engineoptremote (r))Addr adalah string dengan format "host: port".
Anda dapat menambahkan middleware khusus ke penerima Anda. Ini dapat berguna untuk menyimpan metrik, menyimpan dan memuat data untuk penerima Anda di actor.Started dan actor.Stopped .
Sebagai contoh tentang cara menerapkan middleware khusus, lihat folder middleware di contoh
Hollywood memiliki beberapa logging bawaan. Ini akan menggunakan logger default dari paket log/slog . Anda dapat mengonfigurasi logger sesuai keinginan Anda dengan mengatur logger default menggunakan slog.SetDefaultLogger() . Ini akan memungkinkan Anda untuk menyesuaikan level log, format, dan output. Silakan lihat paket slog untuk informasi lebih lanjut.
Perhatikan bahwa beberapa peristiwa mungkin dicatat ke logger default, seperti DeadLetterEvent dan ActorStartedEvent karena peristiwa ini memenuhi actor.LogEvent . Lihat bagian EventStream di atas untuk informasi lebih lanjut.
make test
Bergabunglah dengan komunitas Discord kami dengan lebih dari 2000 anggota untuk pertanyaan dan obrolan yang bagus.
Proyek ini saat ini digunakan dalam produksi oleh organisasi/proyek berikut:
Sensora IoT
Hollywood dilisensikan di bawah lisensi MIT.