Bölüm 1
Geliştirici: Xin Zhang
Aelf Enterprise (Kurumsal) Blockchain'in test ağı (Testnet) aşaması boyunca sıfırdan kod yazarken beklendiği gibi sayısız gün, sorun gidermek (troubleshooting) ve çok sayıda sorunu çözmek için harcandı. Böyle bir problem, düğümlerin aktif hale geldikten kısa bir süre sonra çökmesine neden olur. Bu makale, Aelf geliştiricilerinin konunun özünü nasıl tanımladığını ve çözdüğünü ele alacaktır.
Arka Plan
Aelf tek düğüm test aşaması sırasında geliştiriciler, düğümün aniden çevrimdışı olduğunu buldu. Kaydı kontrol ettikten sonra işçilerin (işlem yürütme süreci sırasında) tamamen düşürüldüğü, işlemlerin yürütülmesinin durduğu ve bunun sonucunda düğümün çöktüğü anlaşıldı.
Ön teşhis
Düğümler ve tüm çalışanları aynı sunucuda olduğu için bu sorun oldukça olağandışıydı ve bu nedenle ağ iletişimi bir sorun olmamalıydı. Ek teşhisler; ana düğümün, tüm işçilerin ve Lighthouse’ların neredeyse aynı anda çevrimdışı olduklarını ortaya çıkardı. Sorun gidermeye (troubleshooting) devam ettik ve sorunları zabbix aracılığıyla bulduk - sunucunun RAM'i, bir noktada operasyon kapasitesine ulaşmaya yaklaşmış. Zaman damgasına bakıldığında, düğümün arızalandığı zamanla çakıştı.
Temel Sorunun Belirlenmesi
Düğümün bellek kullanımını test etmeye odaklandık. Ön sonuçlar, düğümün uzun süre çalıştığından işlemin sunucunun belleğini sürekli olarak kapladığını gösterdi. Bellek kullanımı, özellikle çok sayıda işlem gönderildikten sonra önemli ölçüde artmaktadır ve en önemlisi de işlemler durduktan sonra bile bellek serbest bırakılmamıştır.
Sorunu yeniden üretme
Öncelikle kullanılan hizmet ortamını tanıtmalıyım: Ubuntu 16.04.5 LTS ve dotnet core versiyon 2.1.402
Düğüm, yaklaşık 90 MB'lik bir temel bellek kullanımına sahiptir.
Düğüme sürekli olarak çok sayıda işlem göndererek, düğüm alış - veriş havuzunu işlemleri biriktirirken ve yürütürken izleyebiliriz (aşağıda gösterilmiştir).
Bir süre sonra, bellek kullanımı 1 GB'a ulaştı.
Bu noktada, işlemlerin yürütülmesi durduruldu. Aşağıda görüldüğü gibi halihazırda alış - veriş havuzunda bulunan tüm işlemler yürütülmüştür.
“Bellek ayak izini izlemeye devam ettik ve bir süre sonra bellek kullanımının azalmadığını ve 1GB kullanım seviyesini koruduğunu tespit ettik.”
Analiz ve Çözüm
Düğümlerimizi analiz etmek için lldb kullanırız.
Bu, ilk önce sunucuya lldb yüklenerek yapılır.
Sudo apt-get install lldb
Yerel ibsosplugin.so lokasyonunun bulunması
Find /usr -name libsosplugin.so
lldb'nin başlatılması ve işleme eklenmesi
Sudo lldb –p 13067
libsosplugin.so yüklenmesi
Plugin load /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.4/libsosplugin.so
Setclrpath /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.4/
Bir sonraki nesnenin analiz edilmesi
Dumpheap -stat
Aşağıdaki nesnelerden çok sayıda gözlemledik
AElf.Kernel.TransactionHolder
System.String
AElf.Common.Address
System.Collections.Concurrent.ConcurrentDictionary`2+Node[[AElf.Common.Hash,A Elf.Common],[AElf.Kernel.TransactionHolder,AElf.Kernel.TxHub]]
AElf.Kernel.Transaction
AElf.Common.Hash
Google.Protobuf.ByteString
System.Byte[]
Olağandışı büyük nesneleri tanımlamaya çalıştığımızdan, 1024 bayttan daha büyük nesnelere odaklandık.
Göreceli olarak büyük aynı tipten 4 nesne olduğunu görebiliriz
System.Collections.Concurrent.ConcurrentDictionary`2+Node[[AElf.Common.Hash, AElf.Common],[AElf.Kernel.TransactionHolder, AElf.Kernel.TxHub]][]
MethodTable'a karşılık gelen nesnelere daha fazla bakarak
8 nesneden 4'ünün alışılmadık derecede büyük olduğunu belirledik. Nesne bilgilerini görüntülemek için bunlardan birini seçerek içinde 573.437 değerin depolandığını gördük.
Yukarıdaki analize dayalı karşılık gelen kaynak kodunu kontrol ettik ve şu sınıfı yerleştirdik: AElf.Kernel.TxHub. Bu sınıfın temel rolü, işlem havuzu işlem verilerini depolamaktır. Bu sınıf, işlem verilerini depolamak için 8 ConcurrentDictionary
Bu sorunu çözdükten sonra doğrulama için yukarıdaki adımları tekrar ettik. Etki belliydi. İşlem havuzundaki işlemleri yürüttükten sonra, bellek kullanımı önemli ölçüde azaldı. Bellek kullanımının son sonuçları aşağıdaki gibidir:
Ek olarak bellekteki nesnelerin içeriğine bakarak, toplam nesne sayısının da önemli ölçüde düştüğünü gördük.
Çekirdek sorunu tanımlanmış ve çözülmüş olsa da zaman içinde bellekte hâlâ küçük bir artış olduğunu ve bellekte büyük nesnelerin bulunduğu durumlar olduğunu fark ettik. Kalan (artık) sorunları analiz etmek için daha fazla zaman harcayacağız.
KAYNAK: https://medium.com/aelfblockchain/aelf-tech-talks-resolving-the-memory-dilemma-on-aelf-blockchain-2c7d10f09a3a