Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Şunlar için geçerlidir: .NET Core 2.1, .NET Core 3.1, .NET 5
Bu makalede, Linux'ta .NET Core kilitlenme dökümü dosyalarını yakalamak için createdump aracının nasıl kullanılacağı ve ardından kilitlenme sorununu tanılamak için lldb'nin nasıl kullanılacağı açıklanır.
Önkoşullar
Bu sorun giderme laboratuvarlarını izlemenin en düşük gereksinimi, düşük CPU ve yüksek CPU performans sorunlarını gösteren bir ASP.NET Core uygulamasına sahip olmaktır.
İnternet'te bu hedefe ulaşmak için birkaç örnek uygulama bulabilirsiniz. Örneğin, istenmeyen davranışları göstermek için Microsoft'un basit webapi örneğini indirip ayarlayabilirsiniz. Alternatif olarak, örnek proje olarak BuggyAmb ASP.NET Core uygulamasını da kullanabilirsiniz.
Bu serinin önceki bölümlerini izlediyseniz, aşağıdaki kurulumun hazır olması gerekir:
- Nginx, iki web sitesini barındıracak şekilde yapılandırılmıştır:
- İlki, myfirstwebsite ana bilgisayar üst bilgisini (
http://myfirstwebsite
) kullanarak istekleri dinler ve istekleri 5000 numaralı bağlantı noktasını dinleyen demo ASP.NET Core uygulamasına yönlendirir. - İkincisi, buggyamb ana bilgisayar üst bilgisini (
http://buggyamb
) kullanarak istekleri dinler ve istekleri 5001 numaralı bağlantı noktasını dinleyen ikinci ASP.NET Core örnek buggy uygulamasına yönlendirir.
- İlki, myfirstwebsite ana bilgisayar üst bilgisini (
- Her iki ASP.NET Core uygulaması da sunucu yeniden başlatıldığında veya uygulama yanıt vermeyi durdurduğunda otomatik olarak yeniden başlatılan hizmetler olarak çalışıyor olmalıdır.
- Linux yerel güvenlik duvarı etkinleştirilir ve SSH ve HTTP trafiğine izin verecek şekilde yapılandırılır.
Not
Kurulumunuz hazır değilse "2. Bölüm ASP.NET Core uygulamaları oluşturma ve çalıştırma" bölümüne gidin.
Bu laboratuvara devam etmek için Nginx'in arkasında çalışan en az bir sorunlu ASP.NET Core web uygulamanız olmalıdır.
Bu laboratuvarın hedefi
Otomatik olarak oluşturulan çekirdek döküm dosyaları, yönetilen durum bilgilerinin tümünü içermediğinden kullanışlı değildir. .NET Core çekirdek kilitlenme dökümü dosyalarını yakalamak için önerilen araç oluşturulurump.
Bu bölümde, createdump kullanarak kilitlenme dökümü dosyasını yakalamayı ve kilitlenme sorununu tanılamak için dosyayı lldb'de açmayı öğreneceksiniz.
createdump'u işlem sonlandırma sırasında çalışacak şekilde yapılandırma
Createdump her .NET Core çalışma zamanıyla birlikte otomatik olarak yüklenir.
createdump yapılandırma ilkesi belgelerinde açıklandığı gibi, ortam değişkenleri olan yapılandırma seçeneklerini ayarlayabilirsiniz. Bunlar createdump komutuna parametre olarak geçirilir. Desteklenen ortam değişkenleri şunlardır:
COMPlus_DbgEnableMiniDump
: 1 olarak ayarlanırsa, sonlandırmadan sonra otomatik çekirdek dökümü oluşturmayı etkinleştirir. Varsayılan değer 0'dır.COMPlus_DbgMiniDumpType
: Bu, oluşturulacak mini döküm dosyasının türüdür. Bunun varsayılan değeri 2'dir (veya bir sabit listesi türüdürMiniDumpWithPrivateReadWriteMemory
). Bu, oluşturulan döküm dosyasının GC yığınlarını ve bir işlemdeki tüm mevcut iş parçacıklarının yığın izlemelerini yakalamak için gerekli bilgileri içereceği anlamına gelir.COMPlus_DbgMiniDumpName
: Ayarlanırsa, döküm dosyası yolunu ve dosya adını oluşturmak için şablon olarak kullanın. PID, parametresi kullanılarak%d
ada yerleştirilebilir. Varsayılan şablondur /tmp/coredump.%d. Bu ortam değişkenini kullanarak çıkış dizinini yapılandırabilirsiniz.COMPlus_CreateDumpDiagnostics
: 1 olarak ayarlanırsa, createdump aracı tanılama iletilerini (TRACE makro) etkinleştirir. Createdump beklendiği gibi çalışmıyorsa ve bellek dökümü dosyası oluşturmuyorsa bu ayar yararlı olabilir.
Bu değişkenlerle ilgili ayrıntıları createdump yapılandırma ilkesinde bulabilirsiniz.
Buradaki önemli değişken şu şekildedir COMPlus_DbgEnableMiniDump
: . Bu ortam değişkenini 1 olarak ayarlamanız gerekir. Bu ortamı ayarlamak için birkaç yöntem vardır:
- Uygulamanızın yapılandırma dosyasında ayarlayın.
export COMPlus_DbgEnableMiniDump=1
Ayarlamak için komutunu kullanın. Bu ayar, işletim sistemi yeniden başlatıldıktan sonra kalıcı olmaz. Bu nedenle, yeniden başlatmadan sonra ayarın etkin kalmasını istiyorsanız kalıcı olarak ayarlamanız gerekir.- ASP.NET Core hizmet birimi dosyasında ayarlayın.
Bu değişkenin ASP.NET Core hizmet birimi dosyasında ayarlanması en kolay yöntemdir. Bunun dezavantajı, hizmetin yeniden başlatılması gerektiğidir. Bu sorun giderme bölümünde, bu seçenek gösterilir.
Buggy uygulamasının hizmet dosyasını açın ve ortam değişkenini COMPlus_DbgEnableMiniDump=1
ekleyin. Bu, bu eğitimin önceki bölümlerinde birkaç kez yaptığınızla aynıdır.
Yapılandırma değiştirildiğinden hizmet yapılandırmasını yeniden yüklemeniz gerekir. Ardından BuggyAmb hizmetini yeniden başlatın.
Bu değişiklikleri yaptıktan sonra kilitlenme sorununu yeniden oluşturun. createdump çalışıyorsa döküm dosyası coredump olarak /tmp/ dizinine yazılmalıdır.<PID>. Sorunu yeniden oluşturmak için aynı adımları izleyin:
- Kilitlenme 3'e tıklayın. Sayfa doğru şekilde yüklenir, ancak işlemin kilitlenmesi gerektiğini belirten yanlış bir ileti döndürür.
- Yavaş'ı seçin. Bu, ürün tablosu yerine bir "HTTP 502" yanıt kodu (hatalı ağ geçidi hatası) oluşturur.
- Sorun oluştuktan sonra sayfaların hiçbiri işlenmez ve 10-15 saniye boyunca aynı hata iletisini alırsınız.
- 10-15 saniye sonra uygulama düzgün çalışmaya başlar.
Artık /tmp dizininde bir çekirdek döküm dosyanız olmalıdır.
Çekirdek döküm dosyanız yoksa, dosyayı doğru yapılandırdığınızdan buggyamb.service emin olun. Ayrıca hizmet yapılandırmasını yeniden yüklemeniz ve hizmeti yeniden başlatmanız gerekir.
Çekirdek döküm dosyasını lldb'de açma
Döküm dosyasını örnek çözümlemeyle birlikte izlemek üzere klasörünüze taşımanızı ~/dumps/ öneririz. Döküm dosyasını açmak için komutunu çalıştırın lldb --core ~/dumps/coredump.<10354>
. Bu komutta , 10354 yer tutucusunu işleminizin PID'iyle değiştirin.
Not
Daha önce bir döküm dosyası açtıysanız ve lldb ile çalıştıysanız, sembolleri zaten ayarlamış ve SOS yüklemişsinizdir. Simgeleri yeniden indirmek zorunda kalmadan aynı .NET Core sürüm döküm dosyasını açabilirsiniz. Ancak, sembollerin henüz indirilmediğiniz farklı bir .NET Core sürüm döküm dosyası açarsanız, çözümlemeyi başlatabilmeniz için önce bu sürüme ait simgeleri indirmeniz gerekir.
Yönetilen çağrı yığınını görüntülemek için SOS clrstack
komutunu çalıştırın. Sistem tarafından oluşturulan çekirdek döküm dosyasını kullanarak aynı komutu çalıştırdığınızda bir hatayla karşılaştığınızı unutmayın. Bu kez doğru yönetilen çağrı yığınını görmeniz gerekir.
Bu iyi bir başlangıç. Ancak, görüntülenen çağrı yığını hata ayıklama işlemimizin ana iş parçacığına aittir. Özel durumun oluştuğu iş parçacığı değildir.
Not
Windows üzerinde WinDbg'de bir kilitlenme dökümü dosyası açarsak, WinDbg kilitlenmeye neden olan iş parçacığını doğrudan seçer. Ancak lldb'de durum böyle değildir. lldb'de WinDbg, bellek dökümünü oluşturmak için hata ayıklayıcıyı tetikleyen iş parçacığını otomatik olarak seçmez.
Hata ayıklarken bu WinDbg davranışı yararlı olsa da, lldb'de bu özelliğin olmaması dünyanın sonu değildir. Bunun yerine, özel durumun nerede oluşturulabileceğini belirlemek için tüm iş parçacıklarını inceleyebilirsiniz. komutunu kullanarak thread list
yerel iş parçacıklarını inceleyerek başlayın.
Döküm dosyasının oluşturulduğu sırada nelerin çalıştığını anlayabilmek için tüm iş parçacığı çağrı yığınlarını hızlı bir şekilde inceleyerek başlamak her zaman iyi bir fikirdir. İlk olarak komutunu içeren yerel iş parçacığı listesine thread list
bakın.
Not
Listedeki (thread #1
) ilk iş parçacığının yanındaki yıldız işareti (*) bunun etkin iş parçacığı olduğunu gösterir.
Yerel iş parçacığı incelemesi çok fazla bir şey ortaya koymuyor. Bu bir .NET Core uygulaması olduğundan, SOS clrthreads
komutunu çalıştırarak CLR iş parçacıkları listesini inceleyin. Bu komut, uygulamada çalışan yönetilen iş parçacıklarını listeler.
Bu ekran görüntüsü tüm yönetilen iş parçacıklarını göstermiyor. Ancak, odaklanmanız gereken ayrıntılar ekran görüntüsünde listelenir. Thread #15
sistem günlüklerimizde gördüğümüz bir özel durum vardır.
bu iş parçacığının çağrı yığınını inceleyin. Bunu yapmak için önce söz konusu yazışmayı seçmeniz gerekir. Çalıştıracağınız bellek dökümü analizinde, iş parçacığı numarası büyük olasılıkla farklı olacaktır. Etkin iş parçacığı olarak başka bir iş parçacığı seçmek için komutunu kullanın thread select
ve lldb dbg iş parçacığı kimliğini geçirin. Örneğin, iş parçacığı 15'e geçmek için komutunu çalıştırın thread select 15
. Ardından, çalıştırdığınız her ardışık komut bu iş parçacığının bağlamında olur. Yerel çağrı yığınını görmek için (geri izleme) komutunu çalıştırın bt
.
Bu ekran görüntüsünde görebileceğiniz gibi, bu iş parçacığı kesinlikle kilitlenmeyi tetikleyen iş parçacığıdır.
PROCEndProcess
vePROCAbort()
işlenmeyen bir özel durumdan sonra çağrılır.POCCreateCrashDump
bir kilitlenme dökümü .NET Core tarafından yazıldığını bildirir.
komutunu çalıştırarak yönetilen çağrı yığınını clrstack
inceleyebilirsiniz. Ancak, bu çok fazla ortaya çıkmaz. pe
Özel durum ayrıntılarını almak için komutunu çalıştırın.
Bu bilgiler şunu gösterir: Yöntemindeki Crash3 sayfanızda LogTheRequest()
A System.Net.HttpWebRequest
tetikleniyor. Bu, sorunun bulunmasına yardımcı olacak önemli bir bilgidir. Peki HTTP isteğinin URL'sini bulmak istiyorsanız ne olacak? Devam etmek için, bu listeden daha fazla bilgi toplayıp toplayamayacağınızı görmek için yığında başvuruda bulunan nesneleri incelemeyi deneyin. Geçerli yığının sınırları içinde bulunan tüm yönetilen nesneleri görüntülemek için komutunu çalıştırın dso
.
Bu işe yaramaz. Hiçbir System.Net.HttpWebRequest
örneği görmemeniz gerekir. Özel durumun örnekleri vardır ve bunu zaten incelediniz. Bu nedenle, bu komut nedenle ilgili yeni bilgiler sağlamadı.
Tüm yönetilen nesneler yönetilen bir yığında depolanır ve komutunu çalıştırarak dumpheap
yönetilen yığına bakabiliriz. Herhangi bir parametre olmadan çalıştırmayın dumpheap
çünkü komut yönetilen yığın içindeki tüm nesneleri (büyük bir liste) listeler. Bunun yerine komutunu kullanarak yığının istatistiklerini dumpheap -stat
alabilirsiniz.
Komutunu aşağıdaki biçimde çalıştırarak istatistikleri daraltmak için bir taktik daha kullanabilirsiniz:
dumpheap -stat -type System.Net.HttpWebRequest
Aşağıdaki ekran görüntüsü, adında dizeyi System.Net.HttpWebRequest
içeren yönetilen nesnelerin istatistiklerini görüntüler.
Örnek uygulamada yönetilen yığında yalnızca bir System.Net.HttpWebRequest
nesne vardır. Önceki listede, girdinin yanında görülen adres bu nesnenin HttpWebRequest
bellekteki adresi değildir. Bunun yerine, türündeki System.Net.HttpWebRequest
nesnelerin "yöntem tablosuna" karşılık gelen adrestir. Nesnelerin gerçek listesini almak için, bu yöntem tablosu (MT) adresini komutuna dumpheap
aşağıdaki şekilde geçirebilirsiniz:
dumpheap -mt <address>
Örneğin, nesnesinin adresini bulmak için komutunu çalıştırın dumpheap -mt 00007f53623cb640
.
Artık sorunlu nesnenin adresini belirleyebilirsiniz. Bu örnekte, şeklindedir 00007f51300c0868
. Bu adresi komutuna geçirerek nesnenin dumpobj
özelliklerini araştırabilirsiniz. Bu, söz konusu nesnenin özelliklerini listeler. Bu örnekte, nesnesinin özelliklerini incelemek için komutunu çalıştırın dumpobj 00007f51300c0868
.
Not
Bir nesneyi araştırıyorsunuz System.Net.HttpWebRequest
ve bu nesnenin özelliklerinden biri._requestUri
Bu, türünde bir nesnedir System.Uri
. URI'yi belirlemek istiyorsunuz. Bu nedenle, özelliğinin _requestUri
adresini komutuna dumpobj
geçirin
Nesnesinin adresini System.Uri
kopyalayın ve yeniden kullanarak dumpobj
araştırın. dumpobj 00007f51300bfbb8
'i çalıştırın. Oluşturduğunuz bellek dökümü dosyasındaki nesnenin adresi kesinlikle farklı olacaktır. Listede özelliğini System.Uri
görüntüler_string
.
adresini _string
kopyalayın ve komutu buna karşı yeniden çalıştırın dumpobj
. dumpobj 00007f51300bfb40
'i çalıştırın. Sonuç aşağıdaki ekran görüntüsünde listelenmiştir.
Son olarak HttpWebRequest'in URL'sini bulabilirsiniz: http://buggyamb/Problem/Api/NotExistingLoggingApi
. Adından da anlaşılacağı gibi, bu büyük olasılıkla uygulama içinde mevcut bir sayfa değildir.
Son olarak, kilitlenmenin nasıl meydana geldiğiyle ilgili teori aşağıdaki gibidir:
- HttpWebRequest, Crash3 web sayfasındaki yönteminde
LogTheRequest()
var olmayan bir URL'ye yapılır. - Gerçek dünyadaki bir uygulamada, bu sorunu düzeltmenin çözümü, yapıldığında hataları
HttpWebRequest
işlemek olacaktır. Ancak bu durumda çözüm çok daha basittir: Var olmayan birHttpWebRequest
sayfaya istekte bulunmayın.
Bu noktada, kilitlenmeye neyin neden olduğu hakkında daha fazla sorunuz olmalıdır. Örneğin, Yavaş bağlantısını seçtikten sonra kilitlenme neden tetiklendi?
Kendiniz araştırmaya devam etmek için çekinmeyin. Atabileceğiniz bir sonraki önerilen adım, kök dizinin gcroot
nerede olduğunu bulmak için nesne adresini kullanarak HttpWebRequest
komutu çalıştırmaktır. Bu, kilitlenmenin nasıl oluştuğuna ilişkin bir resim geliştirmenize yardımcı olabilir.
Bu, laboratuvarın sonuca varıyor. Ctrl+C tuşlarına basın veya lldb hata ayıklayıcıdan çıkmak için komutunu kullanınq
.
Sonraki adımlar
Lab 2.1 Linux'ta createdump kullanarak performans sorunlarını giderme