Eski Yazılımları Modernleştirme: Erlang ve CloudI Kullanarak MUD Programlama
Yayınlanan: 2022-03-11Eski Modernizasyon Nedir?
Eski kod her yerdedir. Ve kodun çoğalma hızı katlanarak artmaya devam ettikçe, bu kodun gitgide daha fazlası eski statüsüne düşürülüyor. Birçok büyük kuruluşta, eski sistemlerin bakımı, bilgi sistemleri kaynaklarının %90'ından fazlasını tüketir.
Mevcut performans ve işleme taleplerini karşılamak için eski kod ve sistemleri modernize etme ihtiyacı yaygındır. Bu gönderi, eski kodu - özellikle de onlarca yıllık bir C kaynak kodu koleksiyonunu - 21. yüzyıla uyarlamak için Erlang programlama dilinin ve Erlang tabanlı CloudI Hizmet Odaklı Mimarinin (SOA) kullanımına ilişkin bir örnek olay incelemesi sunar. .
Kaynak Kodu Ejderhasını Öldürmek
Yıllar önce, Çok Kullanıcılı Zindanlar (MUD'ler) olarak bilinen metin tabanlı çok oyunculu çevrimiçi oyunların büyük bir hayranıydım. Ama her zaman performans sorunlarıyla uğraşıyorlardı. Onlarca yıllık bir C kaynak kodu yığınına geri dalmaya ve bu eski kodu nasıl modernize edebileceğimizi ve bu ilk çevrimiçi oyunların sınırlarını nasıl zorlayabileceğimizi görmeye karar verdim. Yüksek düzeyde, bu proje, eski yazılımları 21. yüzyıl gereksinimlerini karşılayacak şekilde uyarlamak için Erlang'ı kullanmanın harika bir örneğiydi.
Kısa bir özet:
- Hedef : Eski bir 50 oyunculu sınırlı MUD video oyununu alın ve binlerce eşzamanlı bağlantıyı desteklemek için kaynak kodunu zorlayın.
- Sorun : Eski, tek iş parçacıklı C kaynak kodu.
- Çözüm : Hataya dayanıklılık ve ölçeklenebilirlik sağlayan Erlang tabanlı bir hizmet olan CloudI.
Metin Tabanlı MUD nedir?
World of Warcraft ve EverQuest gibi tüm Devasa Çok Oyunculu Çevrimiçi Rol Yapma Oyunları (MMORPG'ler), ilk kökenleri Çok Kullanıcılı Zindanlar (MUD'ler) olarak bilinen eski metin tabanlı çok oyunculu çevrimiçi oyunlara kadar izlenebilen özellikler geliştirmiştir.
İlk MUD, 1978'de bir DEC PDP-10'da MARO-10 montajcı dili kullanılarak geliştirilen, ancak C programlama dilinin öncülü olan BCPL'ye dönüştürülen Roy Trubshaw'ın Essex MUD'si (veya MUD1) idi. 1987). (Gördüğünüz gibi, bunlar çoğu programcıdan daha eskidir.)
MUD'ler, 1980'lerin sonlarında ve 1990'ların başlarında, C ile yazılmış çeşitli MUD kod tabanları ile giderek popülerlik kazandı. Örneğin, DikuMUD kod tabanı, tümü en az 51 benzersiz varyantla türetilmiş MUD kaynak kodunun en büyük ağaçlarından birinin kökü olarak bilinir. aynı DikuMUD kaynak kodunu temel alır. (Bu süre zarfında, tesadüfen, MUD'ler, takıntıları nedeniyle okulu bırakan üniversite lisans öğrencilerinin sayısı nedeniyle alternatif olarak "Çoklu Lisans Yok Edici" olarak bilinir hale geldi.)
Eski MUD'larla ilgili sorun
Tarihsel C MUD kaynak kodu (DikuMUD ve türevleri dahil), oluşturulduğu sırada mevcut sınırlamalar nedeniyle performans sorunlarıyla dolu.
iş parçacığı eksikliği
O zamanlar, kolay erişilebilir bir iş parçacığı kitaplığı yoktu. Ayrıca, iş parçacığı oluşturma, kaynak kodunun bakımını ve değiştirilmesini daha zor hale getirirdi. Sonuç olarak, bu MUD'lerin tümü tek iş parçacıklı idi.
Tek bir "tik" (tüm oyun olaylarının ilerlemesini izleyen dahili saatin bir artışı) sırasında, MUD kaynak kodunun her oyun olayını her bağlanan soket için işlemesi gerekir. Başka bir deyişle: her bir kod parçası, tek bir onay işaretinin işlenmesini yavaşlatır. Ve herhangi bir hesaplama, işlemi tek bir tıklamadan daha uzun sürmeye zorlarsa, MUD gecikerek bağlı her oyuncuyu etkiler.
Bu gecikme ile oyun hemen daha az ilgi çekici hale gelir. Oyuncular, kendi komutları işlenmeden kalırken, karakterleri ölürken çaresizce bakarlar.
SillyMUD ile tanışın
Bu eski uygulama modernizasyonu deneyinin amaçları doğrultusunda, modern MMORPG'leri ve onların paylaştığı performans sorunlarını etkileyen, DikuMUD'un tarihsel bir türevi olan SillyMUD'u seçtim. 1990'larda SillyMUD kod tabanından türetilen bir MUD oynadım, bu yüzden kaynak kodunun ilginç ve biraz tanıdık bir başlangıç noktası olacağını biliyordum.
Ne miras alıyordum?
SillyMUD kaynak kodu, kabaca 50 eşzamanlı oyuncuyla (kaynak koduna göre tam olarak 64) sınırlı olduğu için diğer tarihi C MUD'larınınkine benzer.
Ancak, kaynak kodun performans nedenleriyle (yani, eşzamanlı oynatıcı sınırlamasını zorlamak için) değiştirildiğini fark ettim. özellikle:
- Kaynak kodunda, bağlantı IP adresinde bir alan adı araması eksikti, bir alan adı aramasının zorunlu kıldığı gecikme nedeniyle mevcut değildi (normalde, eski bir MUD, kötü niyetli kullanıcıları yasaklamayı kolaylaştırmak için bir alan adı araması ister).
- Kaynak kodun "bağış" komutunu devre dışı bıraktı (biraz alışılmadık), bağışlanan öğelerin uzun bağlantılı listelerinin olası oluşturulması ve bu da daha sonra yoğun işlem gerektiren liste geçişleri gerektiriyordu. Bunlar da diğer tüm oyuncular için oyun performansına zarar verir (tek iş parçacıklı, hatırladınız mı?).
CloudI ile tanışın
CloudI, sağladığı hata toleransı ve ölçeklenebilirliği nedeniyle daha önce çok dilli geliştirme için bir çözüm olarak tartışılmıştı.
CloudI, Erlang, C/C++, Java, Python ve Ruby'de bir hizmet soyutlaması (Hizmet Odaklı Mimari (SOA) sağlamak için) sağlarken yazılım hatalarını CloudI çerçevesinde izole eder. Erlang'ın hataya dayanıklı özelliklerine ve Aktör Modelinin uygulanmasına dayanan CloudI'nin Erlang uygulaması aracılığıyla hata toleransı sağlanır. Bu hata toleransı, tüm yazılımlar hatalar içerdiğinden CloudI'nin Erlang uygulamasının önemli bir özelliğidir.
CloudI ayrıca, hizmet yürütmenin ömrünü ve hizmet süreçlerinin oluşturulmasını (Erlang dışı programlama dilleri için işletim sistemi süreçleri veya Erlang'da uygulanan hizmetler için Erlang süreçleri olarak) kontrol etmek için bir uygulama sunucusu sağlar, böylece hizmet yürütme, harici durumu etkilemeden gerçekleşir. güvenilirlik. Daha fazlası için bir önceki paylaşımıma bakın.

CloudI, eski bir metin tabanlı MUD'yi nasıl modernize edebilir?
Geçmiş C MUD kaynak kodu, güvenilirlik sorunları göz önüne alındığında CloudI entegrasyonu için ilginç bir fırsat sunar:
- Oyun sunucusu kararlılığı, herhangi bir oyun mekaniğinin çekiciliğini doğrudan etkiler.
- Yazılım geliştirmeyi sunucu kararlılığı hatalarını düzeltmeye odaklamak, ortaya çıkan oyunun boyutunu ve kapsamını sınırlar.
CloudI entegrasyonuyla, sunucu kararlılığı hataları normal şekilde düzeltilebilir, ancak etkileri sınırlıdır, böylece önceden keşfedilmemiş bir hata dahili bir oyun sisteminin başarısız olmasına neden olduğunda oyun sunucusunun çalışması her zaman etkilenmez. Bu, eski bir kod tabanında hata toleransını zorlamak için Erlang kullanımına harika bir örnek sağlar.
Hangi değişiklikler gerekliydi?
Orijinal kod tabanı, hem tek iş parçacıklı hem de genel değişkenlere büyük ölçüde bağımlı olacak şekilde yazılmıştır. Amacım, eski kaynak kodu işlevselliğini günümüz kullanımı için modernize ederken korumaktı.
CloudI ile, soket bağlantısı ölçeklenebilirliği sağlarken kaynak kodunu tek iş parçacıklı tutabildim.
Gerekli değişiklikleri gözden geçirelim:
konsol çıkışı
SillyMUD konsol çıktısının (genellikle Telnet ile bağlantılı bir terminal ekranı) arabelleğe alınması zaten yerindeydi, ancak bazı doğrudan dosya tanımlayıcı kullanımı arabelleğe almayı gerektiriyordu (böylece konsol çıktısı bir CloudI hizmet talebine yanıt olabilir).
Soket kullanımı
Orijinal kaynak kodundaki soket işleme, giriş, hatalar ve çıkış şansını algılamak ve ayrıca bekleyen oyun olaylarını işlemeden önce 250 milisaniyelik bir oyun tik için duraklamak için bir select()
işlev çağrısına dayanıyordu.
CloudI SillyMUD entegrasyonu, C CloudI API'nin cloudi_poll
işleviyle (aynı bekleyen oyun olaylarını işlemeden önceki 250 milisaniye için) duraklarken, giriş için gelen hizmet isteklerine dayanır. SillyMUD kaynak kodu, C CloudI API ile entegre edildikten sonra CloudI içinde bir CloudI hizmeti olarak kolayca çalıştırılır (C CloudI, SillyMUD'un C kaynak koduyla entegrasyonu daha iyi kolaylaştıran C API kullanarak hem C hem de C++ API'leri sağlar).
abonelikler
CloudI entegrasyonu, bağlanma, bağlantı kesme ve oyun olaylarını işlemek için üç ana hizmet adı modeline abone olur. Bu ad kalıpları, entegrasyon kaynak kodunda abone ol çağrısı yapan C CloudI API'sinden gelir. Buna göre, WebSocket bağlantıları veya Telnet bağlantıları, bağlantılar kurulduğunda hizmet isteklerini göndermek için hizmet adı hedeflerine sahiptir.
CloudI'deki WebSocket ve Telnet desteği, dahili CloudI hizmetleri tarafından sağlanır (WebSocket desteği için cloudi_service_http_cowboy
ve Telnet desteği için cloudi_service_tcp
). Dahili CloudI hizmetleri Erlang'da yazıldığından, Erlang'ın aşırı ölçeklenebilirliğinden yararlanırken aynı zamanda CloudI API işlevlerini sağlayan CloudI hizmet soyutlamasını da kullanabilirler.
İleriye gidiyor
Soket kullanımından kaçınılarak, soket hatalarında veya bağlantı ölümü (kullanıcıların sunucuyla bağlantısının kesildiği) gibi durumlarda daha az işlem gerçekleşti. Bu nedenle, düşük seviyeli soket işlemenin kaldırılması, birincil ölçeklenebilirlik sorununu ele aldı.
Ancak ölçeklenebilirlik sorunları devam ediyor. Örneğin, MUD, dosya sistemini hem statik hem de dinamik oyun öğeleri için yerel bir veritabanı olarak kullanır (yani oyuncular ve ilerlemeleri, dünya bölgeleri, nesneler ve canavarlar). MUD'nin eski kodunu, bunun yerine bir veritabanı için bir CloudI hizmetine dayanacak şekilde yeniden düzenlemek, daha fazla hata toleransı sağlayacaktır. Dosya sistemi yerine bir veritabanı kullansaydık, birden fazla SillyMUD CloudI hizmet süreci aynı anda ayrı oyun sunucuları olarak kullanılabilir, bu da kullanıcıları çalışma zamanı hatalarından izole eder ve kesinti süresini azaltır.
MUD ne kadar iyileşti?
Üç ana iyileştirme alanı vardı:
- Hata toleransı. Modernleştirilmiş SillyMUD CloudI hizmet entegrasyonuyla, SillyMUD kaynak kodundan soket hatalarının ve gecikmenin izolasyonu, bir dereceye kadar hata toleransı sağlar.
- Bağlantı ölçeklenebilirliği. Dahili CloudI hizmetlerinin kullanımıyla, SillyMUD eşzamanlı kullanıcıları üzerindeki sınırlama, 64'ten (geçmişte) 16.384 kullanıcıya (gecikme sorunu olmadan) kolayca gidebilir.
- Verimlilik ve performans. Tek iş parçacıklı SillyMUD kaynak kodu yerine CloudI içinde yapılan bağlantı yönetimiyle , SillyMUD oyun kaynak kodunun verimliliği doğal olarak iyileştirilir ve daha yüksek bir yükü kaldırabilir.
Dolayısıyla, basit CloudI entegrasyonuyla, hata toleransı sağlarken ve aynı eski oyunun verimliliğini artırırken bağlantı sayısı üç büyüklük derecesine göre ölçeklenir.
Büyük Resim
Erlang, üretim sistemleri için %99,99999999 çalışma süresi (yılda 31.536 milisaniyeden daha az kesinti süresi) sağladı. CloudI ile aynı güvenilirliği diğer programlama dillerine ve sistemlerine de getiriyoruz.
Durgun eski oyun sunucusu kaynak kodunu geliştirmek için bu yaklaşımın uygulanabilirliğini kanıtlamanın ötesinde (SillyMUD en son 20 yıl önce 1993'te değiştirildi!), Bu proje daha geniş bir düzeyde Erlang ve CloudI'nin eski uygulamaları modernize etmek ve hata sağlamak için nasıl kullanılabileceğini gösteriyor. - tolerans, geliştirilmiş performans ve genel olarak yüksek kullanılabilirlik. Bu sonuçlar, büyük bir yazılım revizyonu gerektirmeden eski kodu 21. yüzyıla uyarlamak için umut verici bir potansiyele sahiptir.