Memodernisasi Perangkat Lunak Lama: Pemrograman MUD Menggunakan Erlang dan CloudI
Diterbitkan: 2022-03-11Apa itu Modernisasi Warisan?
Kode lama ada di mana-mana. Dan ketika tingkat penyebaran kode terus meningkat secara eksponensial, semakin banyak kode yang diturunkan ke status warisan. Di banyak organisasi besar, pemeliharaan sistem warisan menghabiskan lebih dari 90% sumber daya sistem informasi.
Kebutuhan untuk memodernisasi kode dan sistem lama untuk memenuhi tuntutan kinerja dan pemrosesan saat ini tersebar luas. Posting ini memberikan studi kasus tentang penggunaan bahasa pemrograman Erlang, dan Arsitektur Berorientasi Layanan CloudI (SOA) berbasis Erlang, untuk mengadaptasi kode warisan – khususnya, kumpulan kode sumber C yang berusia puluhan tahun – ke abad ke-21 .
Membunuh Naga Kode Sumber
Bertahun-tahun yang lalu, saya adalah penggemar berat game online multipemain berbasis teks yang dikenal sebagai Multi-User Dungeons (MUD). Tapi mereka selalu diliputi masalah kinerja. Saya memutuskan untuk menyelami kembali tumpukan kode sumber C berusia puluhan tahun dan melihat bagaimana kami dapat memodernisasi kode warisan ini dan mendorong game online awal ini hingga batasnya. Pada tingkat tinggi, proyek ini adalah contoh yang bagus dalam menggunakan Erlang untuk mengadaptasi perangkat lunak lama untuk memenuhi persyaratan abad ke-21.
Ringkasan singkat:
- Tujuannya : Ambil video game MUD lama dengan 50 pemain terbatas dan dorong kode sumbernya untuk mendukung ribuan koneksi simultan.
- Masalahnya : Legacy, kode sumber C single-threaded.
- Solusinya : CloudI, layanan berbasis Erlang yang menyediakan toleransi kesalahan dan skalabilitas.
Apa itu MUD Berbasis Teks?
Semua Massively Multiplayer Online Role Playing Games (MMORPG) – seperti World of Warcraft dan EverQuest – telah mengembangkan fitur yang asal mulanya dapat ditelusuri kembali ke game online multipemain berbasis teks yang lebih tua yang dikenal sebagai Multi-User Dungeons (MUD).
MUD pertama adalah Roy Trubshaw's Essex MUD (atau MUD1) yang awalnya dikembangkan pada tahun 1978 menggunakan bahasa assembler MARO-10 pada DEC PDP-10, tetapi diubah menjadi BCPL, pendahulu dari bahasa pemrograman C (dan berjalan sampai 1987). (Seperti yang Anda lihat, hal-hal ini lebih tua dari kebanyakan programmer.)
MUD secara bertahap mendapatkan popularitas selama akhir 1980-an dan awal 1990-an dengan berbagai basis kode MUD yang ditulis dalam C. Basis kode DikuMUD, misalnya, dikenal sebagai akar dari salah satu pohon terbesar dari kode sumber turunan MUD, dengan setidaknya 51 varian unik semuanya berdasarkan kode sumber DikuMUD yang sama. (Selama jangka waktu ini, kebetulan, MUD menjadi alternatif yang dikenal sebagai "Penghancur Multi-Sarjana" karena jumlah mahasiswa sarjana yang gagal keluar dari sekolah karena obsesi mereka terhadap mereka.)
Masalah dengan MUD lama
Kode sumber C MUD historis (termasuk DikuMUD dan variannya) penuh dengan masalah kinerja karena keterbatasan yang ada pada saat pembuatannya.
Kurangnya threading
Saat itu, tidak ada perpustakaan threading yang mudah diakses. Selain itu, threading akan membuat kode sumber lebih sulit untuk dipelihara dan dimodifikasi. Akibatnya, MUD ini semuanya berulir tunggal.
Selama satu "centang" (peningkatan jam internal yang melacak perkembangan semua acara game), kode sumber MUD harus memproses setiap acara game untuk setiap soket yang terhubung. Dengan kata lain: setiap potongan kode memperlambat pemrosesan satu centang. Dan jika ada komputasi yang memaksa pemrosesan berlangsung lebih lama dari satu centang, MUD tertinggal, berdampak pada setiap pemain yang terhubung.
Dengan jeda ini, permainan langsung menjadi kurang menarik. Pemain melihat tanpa daya saat karakter mereka mati, dengan perintah mereka sendiri yang belum diproses.
Memperkenalkan SillyMUD
Untuk keperluan eksperimen modernisasi aplikasi warisan ini, saya memilih SillyMUD, turunan historis DikuMUD yang telah memengaruhi MMORPG modern dan masalah kinerja yang mereka bagikan. Selama tahun 1990-an, saya memainkan MUD yang diturunkan dari basis kode SillyMUD, jadi saya tahu kode sumbernya akan menjadi titik awal yang menarik dan agak familiar.
Apa yang saya warisi?
Kode sumber SillyMUD mirip dengan MUD C historis lainnya karena terbatas pada sekitar 50 pemain bersamaan (64, tepatnya, berdasarkan kode sumber).
Namun, saya perhatikan bahwa kode sumber telah dimodifikasi karena alasan kinerja (yaitu, untuk mendorong batasan pemutar bersamaan). Secara khusus:
- Kode sumber tidak memiliki pencarian nama domain pada alamat IP koneksi, tidak ada karena latensi yang diberlakukan oleh pencarian nama domain (biasanya, MUD yang lebih lama menginginkan pencarian nama domain untuk mempermudah melarang pengguna jahat).
- Kode sumber memiliki perintah "donasi" yang dinonaktifkan (agak tidak biasa) karena kemungkinan pembuatan daftar tertaut panjang dari item yang disumbangkan yang kemudian memerlukan penelusuran daftar intensif pemrosesan. Ini, pada gilirannya, merusak kinerja game untuk semua pemain lain (single-threaded, ingat?).
Memperkenalkan CloudI
CloudI sebelumnya telah dibahas sebagai solusi untuk pengembangan polyglot karena toleransi kesalahan dan skalabilitas yang disediakannya.
CloudI menyediakan abstraksi layanan (untuk menyediakan Service Oriented-Architecture (SOA)) di Erlang, C/C++, Java, Python, dan Ruby, sambil menjaga kesalahan perangkat lunak tetap terisolasi dalam kerangka kerja CloudI. Toleransi kesalahan disediakan melalui implementasi Erlang CloudI, mengandalkan fitur toleransi kesalahan Erlang dan implementasi Model Aktor. Toleransi kesalahan ini adalah fitur utama implementasi Erlang CloudI, karena semua perangkat lunak mengandung bug.
CloudI juga menyediakan server aplikasi untuk mengontrol masa pakai eksekusi layanan dan pembuatan proses layanan (baik sebagai proses sistem operasi untuk bahasa pemrograman non-Erlang atau sebagai proses Erlang untuk layanan yang diimplementasikan di Erlang) sehingga eksekusi layanan terjadi tanpa memengaruhi keadaan eksternal keandalan. Selengkapnya lihat postingan saya sebelumnya.

Bagaimana CloudI dapat memodernisasi MUD berbasis teks lama?
Kode sumber C MUD historis memberikan peluang menarik untuk integrasi CloudI mengingat masalah keandalannya:
- Stabilitas server game secara langsung memengaruhi daya tarik mekanik game apa pun.
- Memfokuskan pengembangan perangkat lunak untuk memperbaiki bug stabilitas server membatasi ukuran dan cakupan game yang dihasilkan.
Dengan integrasi CloudI, bug stabilitas server masih dapat diperbaiki secara normal, tetapi dampaknya terbatas sehingga operasi server game tidak selalu terpengaruh ketika bug yang sebelumnya tidak ditemukan menyebabkan sistem game internal gagal. Ini memberikan contoh yang bagus tentang penggunaan Erlang untuk menegakkan toleransi kesalahan dalam basis kode lama.
Perubahan apa yang diperlukan?
Basis kode asli ditulis untuk menjadi single-threaded dan sangat bergantung pada variabel global. Tujuan saya adalah untuk mempertahankan fungsionalitas kode sumber lama sambil memodernkannya untuk penggunaan saat ini.
Dengan CloudI, saya dapat menyimpan kode sumber single-threaded sambil tetap menyediakan skalabilitas koneksi soket.
Mari kita tinjau perubahan yang diperlukan:
Keluaran konsol
Penyanggaan keluaran konsol SillyMUD (tampilan terminal, sering kali terhubung dengan Telnet) sudah ada, tetapi beberapa penggunaan deskriptor file langsung memang memerlukan penyanggaan (sehingga keluaran konsol dapat menjadi respons terhadap permintaan layanan CloudI).
Penanganan soket
Penanganan soket dalam kode sumber asli mengandalkan panggilan fungsi select()
untuk mendeteksi input, kesalahan, dan peluang untuk keluaran, serta untuk menjeda tick game 250 milidetik sebelum menangani event game yang tertunda.
Integrasi CloudI SillyMUD bergantung pada permintaan layanan yang masuk untuk input saat menjeda dengan fungsi cloudi_poll C cloudi_poll
API (selama 250 milidetik sebelum menangani peristiwa game tertunda yang sama). Kode sumber SillyMUD dengan mudah dijalankan dalam CloudI sebagai layanan CloudI setelah diintegrasikan dengan C CloudI API (walaupun CloudI menyediakan API C dan C++, menggunakan C API memfasilitasi integrasi yang lebih baik dengan kode sumber C SillyMUD).
Langganan
Integrasi CloudI berlangganan tiga pola nama layanan utama untuk menangani peristiwa koneksi, pemutusan, dan gameplay. Pola nama ini berasal dari C CloudI API yang memanggil berlangganan dalam kode sumber integrasi. Oleh karena itu, koneksi WebSocket atau koneksi Telnet memiliki tujuan nama layanan untuk mengirim permintaan layanan saat koneksi dibuat.
Dukungan WebSocket dan Telnet di CloudI disediakan oleh layanan CloudI internal ( cloudi_service_http_cowboy
untuk dukungan WebSocket dan cloudi_service_tcp
untuk dukungan Telnet). Karena layanan CloudI internal ditulis dalam Erlang, mereka dapat memanfaatkan skalabilitas ekstrim Erlang, sementara pada saat yang sama menggunakan abstraksi layanan CloudI yang menyediakan fungsi CloudI API.
Maju
Dengan menghindari penanganan soket, lebih sedikit pemrosesan yang terjadi pada kesalahan soket atau situasi seperti kematian tautan (di mana pengguna terputus dari server). Dengan demikian, menghapus penanganan soket tingkat rendah mengatasi masalah skalabilitas utama.
Tapi masalah skalabilitas tetap ada. Misalnya, MUD menggunakan sistem file sebagai database lokal untuk elemen permainan statis dan dinamis (yaitu, pemain dan kemajuan mereka, bersama dengan zona dunia, objek, dan monster). Memfaktorkan ulang kode warisan MUD untuk mengandalkan layanan CloudI untuk database akan memberikan toleransi kesalahan lebih lanjut. Jika kami menggunakan database daripada sistem file, beberapa proses layanan SillyMUD CloudI dapat digunakan secara bersamaan sebagai server game terpisah, menjaga pengguna tetap terisolasi dari kesalahan runtime dan mengurangi waktu henti.
Berapa banyak perbaikan MUD?
Ada tiga bidang utama perbaikan:
- Toleransi kesalahan. Dengan integrasi layanan SillyMUD CloudI yang dimodernisasi, isolasi kesalahan soket dan latensi dari kode sumber SillyMUD memang memberikan tingkat toleransi kesalahan.
- Skalabilitas koneksi. Dengan penggunaan layanan CloudI internal, batasan pada pengguna bersamaan SillyMUD dapat dengan mudah beralih dari 64 (secara historis) menjadi 16.384 pengguna (tanpa masalah latensi!) .
- Efisiensi dan kinerja. Dengan penanganan koneksi yang dilakukan dalam CloudI alih-alih kode sumber SillyMUD utas tunggal, efisiensi kode sumber gameplay SillyMUD secara alami ditingkatkan dan dapat menangani beban yang lebih tinggi.
Jadi, dengan integrasi CloudI yang sederhana, jumlah koneksi diskalakan tiga kali lipat sambil memberikan toleransi kesalahan dan meningkatkan efisiensi gameplay lawas yang sama.
Gambar yang lebih besar
Erlang telah menyediakan 99,9999999% waktu aktif (kurang dari 31,536 milidetik waktu henti per tahun) untuk sistem produksi. Dengan CloudI, kami menghadirkan keandalan yang sama ini ke bahasa dan sistem pemrograman lain.
Selain membuktikan kelayakan pendekatan ini untuk meningkatkan kode sumber server game lama yang stagnan (SillyMUD terakhir dimodifikasi lebih dari 20 tahun yang lalu pada tahun 1993!), proyek ini menunjukkan pada tingkat yang lebih luas bagaimana Erlang dan CloudI dapat dimanfaatkan untuk memodernisasi aplikasi lama dan menyediakan kesalahan -toleransi, peningkatan kinerja, dan ketersediaan tinggi secara umum. Hasil ini memiliki potensi yang menjanjikan untuk mengadaptasi kode warisan ke abad ke-21 tanpa memerlukan perbaikan perangkat lunak yang besar.