Doğru sıraya koyuyor ve serileştiriyor muyuz?


13

İletileri çeşitli hizmetler yoluyla işleriz (bir ileti, her biri belirli bir G / Ç ile ilgili işlevi yerine getirmeden önce muhtemelen 9 hizmete dokunacaktır). Şu anda performans için en kötü durum (XML veri sözleşmesi serileştirme) ve en iyi durum (bellek içi MSMQ) kombinasyonuna sahibiz.

Mesajın doğası, serileştirilmiş verilerimizin yaklaşık 12-15 kilobayt olduğu anlamına geliyor ve haftada yaklaşık 4 milyon mesaj işliyoruz. MSMQ'daki kalıcı mesajlar bizim için çok yavaştı ve veriler büyüdükçe MSMQ'nun bellek eşlemeli dosyalarından gelen baskıyı hissediyoruz. Sunucu sadece kuyruk için 16 GB bellek kullanımı ve büyüyor. Makine değişmeye başladığı için bellek kullanımı yüksek olduğunda da performans düşer. Zaten MSMQ kendi kendini temizleme davranışı yapıyoruz.

Burada yanlış yaptığımız bir kısım varmış gibi hissediyorum. Mesajları devam ettirmek ve sadece bir tanımlayıcıyı sıraya koymak için RavenDB'yi kullanmayı denedim, ancak performans çok yavaştı (en iyi dakikada 1000 mesaj). Bunun geliştirme sürümünü veya neyi kullanmanın bir sonucu olup olmadığından emin değilim, ancak kesinlikle daha yüksek bir verime ihtiyacımız var [1]. Kavram teoride çok işe yaradı, ancak performans bu görevi yerine getirmedi.

Kullanım modelinin, tüm okumaları yapan bir yönlendirici gibi davranan bir servisi vardır. Diğer hizmetler 3. taraf kancalarına göre bilgi ekler ve yönlendiriciye iletir. Çoğu nesneye 9-12 kez dokunulur, ancak yaklaşık% 10'unun 3. taraflar uygun şekilde yanıt verene kadar bir süre bu sistemde dolaşmaya zorlanır. Hizmetler şu anda bunu açıklıyor ve bu nedenle mesajın öncelik alanını kullandığımız için uygun uyku davranışlarına sahipler.

Benim sorum, bir C # / Windows ortamında ayrık ama LAN'ed makineleri arasında iletmek için ideal bir yığın nedir? Normalde XML serileştirme yerine BinaryFormatter ile başlıyorum, ancak daha iyi bir yol serileştirmeyi bir belge deposuna boşaltmaksa bu bir tavşan deliği. Dolayısıyla sorum.

[1]: İşimizin doğası, mesajları ne kadar erken işleme koyarsak o kadar çok para kazanmamız anlamına gelir. Haftanın ilerleyen saatlerinde bir mesajın işlenmesinin bu parayı kazanma olasılığımızın daha düşük olduğu anlamına geldiğini ampirik olarak kanıtladık. "Dakikada 1000" performansı oldukça hızlı görünse de, bu rakamı 10k / dakikadan daha fazla artırmamız gerekiyor. Haftalık mesajlarda rakam verdiğim için, bu mesajları işlemek için bir haftamız olduğu anlamına gelmez.

=============== düzenlemek:

Ek bilgi

Yorumlara dayanarak, biraz açıklama ekleyeceğim:

  • Serileştirmenin bizim darboğazımız olduğundan emin değilim. Uygulamayı karşılaştırdım ve serileştirme ısı grafiğinde görünmesine rağmen, hizmetin CPU kullanımının sadece% 2.5-3'ünden sorumlu.

  • Çoğunlukla mesajlarımızın kalıcılığı ve MSMQ'nun olası kötüye kullanımı konusunda endişeliyim. İşlemsel olmayan, kalıcı olmayan mesajlar kullanıyoruz, böylece kuyruk performansını yükseltmeye devam edebiliyoruz ve gerçekten en azından kalıcı mesajlara sahip olmak istiyorum, böylece yeniden başlatmadan sağ kalsınlar.

  • Daha fazla RAM eklemek bir stopgap ölçümüdür. Makine zaten 4GB -> 16GB RAM'den gitti ve daha fazla eklemeye devam etmek için onu aşağı çekmek zorlaşıyor.

  • Uygulamanın yıldız yönlendirme modeli nedeniyle, bir nesnenin açıldığı sürenin yarısı kadar sonra hiç değişmediği bir kuyruğa itilir. Bu, kendisini (IMO) başka bir yerde bir tür anahtar / değer deposunda depolamaya ve sadece mesaj tanımlayıcılarını geçirmeye borç verir.

  • Yıldız yönlendirme modeli uygulamanın ayrılmaz bir parçasıdır ve değişmez. Uygulamaya merkezileştiremeyiz çünkü yol boyunca her parça eşzamansız (yoklama şeklinde) çalışır ve yeniden deneme davranışını tek bir yerde merkezileştirmek isteriz.

  • Uygulama mantığı C # ile yazılmıştır, nesneler değişmez POCO'lardır, hedef dağıtım ortamı Windows Server 2012'dir ve belirli bir yazılım parçası yalnızca Linux'ta destekleniyorsa ek makineler üretmemize izin verilir.

  • Hedeflerim, bellek ayak izini azaltırken ve minimum sermaye harcamasıyla hata toleransını arttırırken mevcut verimliliği korumaktır.


İlgili noktalar soruya dahil edildiğinde yorumlar temizlendi.
ChrisF

Kuyruk alt sistemlerini değiştirmeden endişe etmeden önce en acil sorunu ele almak mantıklı olacaktır (ancak yine de sonuçta yapmaya değer olabilir). Hafızanın kontrolden çıkması, bir yerlerde hala sızıntı olduğunu göstermektedir. Hangi (varsa) bellek profili oluşturuldu?
Dan Lyons

@ DanLyons: tek bellek büyümesi MSMQ'da. Kimse bunun hakkında gerçekten konuşmuyor, ancak bunun nedeni, tümüyle bellek eşlemeli olan kalıcı olmayan mesajlar. Çok fazla veri serileştirdiğimiz için, önemli miktarda bellek ayırıyor. Mesajlar tüketildikçe ve MSMQ'nun dahili temizliği çalışırken bellek (sonunda) geri kazanılır.
Bryan Boettcher

Yanıtlar:


1

İlginizi çekebilecek bazı kuyruk karşılaştırmaları. MSMQ saniyede 10 bin ileti işleyebilmelidir. Bu bir yapılandırma sorunu olabilir mi yoksa istemciler kuyruğu okumaya devam etmiyor olabilir mi? Ayrıca ZeroMQ'nun bu ölçütlerde ne kadar parlak olduğunu da unutmayın (saniyede yaklaşık 100K mesaj), bir kalıcılık seçeneği sunmaz, ancak performans açısından akıllıca olmak istediğiniz yere götürmelidir.


4

Kuyruklu bir mesaj sistemi (bizim durumumuzda ses parmak izleri) ile birkaç yıl önce biraz benzer bir durum yaşadık. Sıkıştırılmış veri paketlerinin sürekliliğine büyük önem verdik, ancak her şeyi diske dönüştürmenin ve kuyruğu diskten tüketmenin çok pahalı olduğunu öğrendik.

Bellek tabanlı kuyruklara geçtiysek, performans olağanüstüydi, ancak büyük bir sorunumuz vardı. Arada bir, kuyrukların tüketicileri hatırı sayılır bir süre boyunca kullanılamaz hale geldi (bizim durumumuzdaki tüketici ve üretici unsurları WAN aracılığıyla bağlandı), böylece üreticinin kuyruğu yönetilemez hale geldiği ve sizin durumunuz gibi bir noktaya kadar büyüyecekti, bellek tüketimi çok yüksek olduğunda, takas sırasında aşırı bellek kaybı, sistemi tam bir taramaya getirdi.

Vaftiz ettiğimiz bir kuyruk tasarladık VMQueue (geriye dönük olarak çok kötü bir isim olan Sanal Bellek Kuyruğu için). Bu kuyruğun fikri, tüketici süreci eşit bir şekilde çalışıyorsa, başka bir deyişle, enqueued öğelerinin sayısını belirli bir seviyenin altında tutacak kadar hızlı işliyorsa, temelde bir bellek tabanlı kuyruk. Ancak, tüketici yavaşladığında veya kullanılamaz hale geldiğinde ve üretici kuyruğu belirli bir boyuta büyüdüğünde, kuyruk öğeleri otomatik olarak diske ve diskten (BinaryFormatterBu arada serileştirme). Bu işlem bellek kullanımını tamamen kontrol altında tutar ve disk belleği işlemi hızlıdır veya ağır bellek yükü sırasında oluşan sanal bellek değişiminden daha hızlıdır. Tüketici kuyruğu eşiğin altında boşaltmayı başardığında, saf bir bellek tabanlı kuyruk olarak çalışmaya devam eder

Sistem çökerse veya yeniden başlatılırsa, kuyruk diske depolanan tüm disk belleği öğelerini kurtarabilir, yalnızca kilitlenmeden önce bellekte tutulan öğeleri kaybeder. Bir kilitlenme veya yeniden başlatma sırasında sınırlı sayıda paketi kaybetmeyi göze alabiliyorsanız, bu kuyruk yardımcı olabilir.

Eğer ilgileniyorsanız, onunla VMQueueoynayabilir böylece sınıf kaynak kodunu paylaşabilirim . Sıra, Serileştirilebilir olarak işaretlenmiş herhangi bir sınıfı kabul eder. Kuyruk oluşturulduktan sonra sayfanın boyutunu öğe sayısı olarak belirlersiniz. Sınıf arabirimi, standart bir Queue sınıfıyla neredeyse aynıdır. Ancak kod çok eskidir, (.net 1.1) bu yüzden ne yazık ki genel bir arayüz mevcut değildir.

Kanıtlanmış MSMQ teknolojisinden hareket etmenin büyük bir bahis olduğunu biliyorum, ancak bu kuyruk neredeyse 6 yıldır güvenilir bir şekilde çalışıyor ve üretici makinenin birkaç hafta boyunca çevrimdışı olduğu senaryolardan kurtulmamıza ve kurtarmamıza izin verdi! İlgileniyorsanız lütfen bize bildirin. :)


1

HP ProLiant ML350G5 sistemi dakikada 82 bin işlem alır - yani bahsettiğiniz "10 bin / dakika" iş hacmi 8 kattan fazladır.

Performans: 82.774 tpmC

Ayrıca, dürüst olmak gerekirse, sadece 64 hatta 128 GB RAM ile giderdim - RAM ucuz. Greenspun , "ona RAM atmak" ve "onu optimize etmek için akıllı bir MIT eğitimli adam edin" arasındaki farkı belirtir ve RAM kazanır.

64 GB RAM ile donatılmış bir SQL Server makinesi ve ASP.NET sayfalarını çalıştıran bir dizi ön uç makine ile sona erdi ... Zorluk olmadan...

"Makine zaten 16 GB RAM'e gitti" notu yeterli değil, bir makale 64 GB RAM'de 400 bin kullanıcıyı işleyen bir sunucuya işaret ediyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.