Düşünceleri Açmak
Sistemin bazı bölümlerinin başka bir dilde daha iyi olacağı sonucuna nasıl geldiniz? Performans sorunu mu yaşıyorsunuz? Bu sorunlar ne kadar şiddetli? Daha hızlı olabilirse, daha hızlı olması şart mıdır?
Tek iş parçacıklı eşzamansız
Tek iş parçacıklı eşzamansızlık ve çok iş parçacığı eşzamanlılığının farklılıkları, artıları ve eksileri ile ilgili birçok soru ve başka web kaynakları bulunmaktadır. Node.js'in tek iş parçacıklı asenkron modelinin I / O ana tıkanıklık olduğunda nasıl bir performans gösterdiğini ve aynı anda servis verilen birçok istek olduğunu okumak ilginçtir .
Twisted, Tornado ve diğer asenkron modeller, tek bir dişlinin mükemmel bir şekilde kullanılmasını sağlıyor. Çok sayıda web programlaması çok fazla G / Ç'ye (ağ, veritabanı vb.) Sahip olduğu için, uzak çağrıları beklemek için harcanan zaman önemli ölçüde artar. Diğer veritabanı aramalarını başlatmak, sayfa oluşturmak ve veri üretmek gibi başka şeyler yapmak için harcanan zaman budur. Bu tek ipliğin kullanımı son derece yüksektir.
Tek iş parçacıklı eşzamansızlığın en büyük yararlarından biri, daha az bellek kullanmasıdır. Çok iş parçacıklı yürütme, her iş parçacığı, belirli bir miktarda ayrılmış bellek gerektirir. Diş sayısı arttıkça, sadece dişlerin var olması için gereken hafıza miktarı da artar. Bellek sonlu olduğundan, herhangi bir zamanda oluşturulabilecek iplik sayısında sınırlar olduğu anlamına gelir.
Örnek
Bir web sunucusu durumunda, her bir talebe kendi başlığına verilir gibi davran. Her iş parçacığı için 1 MB bellek gerektiğini ve web sunucusunun 2GB RAM’e sahip olduğunu söyleyin. Bu web sunucusu herhangi bir zamanda (yaklaşık olarak) 2000 isteğini herhangi bir zamanda işleme koyabilecek ve daha fazla işlem yapabilecek kadar bellek kalmayacaktı.
Yükünüz bundan daha yüksekse, istekler çok uzun sürecektir (daha eski isteklerin tamamlanmasını beklerken) veya olası eşzamanlı istek sayısını artırmak için kümeye daha fazla sunucu atmanız gerekecek .
Çok iş parçacıklı eşzamanlılık
Çok iş parçacığı eşzamanlılık yerine, aynı anda birkaç görevi yürütmeye dayanır. Bu, bir iş parçacığı geri dönmek için bir veritabanı çağrısında bekleyen engellenirse, diğer isteklerin aynı anda işlenebileceği anlamına gelir. İplik kullanımı daha düşüktür, ancak yürütülen iplik sayısı çok daha fazladır.
Çok iş parçacıklı kod da nedeni çok daha zordur. Kilitleme, senkronizasyon ve diğer eğlenceli eşzamanlılık sorunları ile ilgili sorunlar var. Tek iş parçacıklı asenkronizasyon aynı sorunlardan muzdarip değildir.
Ancak çoklu iş parçacığı kodu CPU yoğun görevler için çok daha başarılı . Bir iş parçacığının “verimi” (normal olarak engelleyebilecek bir ağ araması gibi) için bir fırsat yoksa, tek iş parçacıklı bir model hiçbir şekilde eşzamanlılığa sahip olmaz.
Her ikisi de bir arada olabilir
Tabi ikisi arasında örtüşme var; karşılıklı olarak dışlayıcı değillerdir. Örneğin, çoklu iş parçacığı kodu, her iş parçacığını daha iyi kullanmak için engelleyici olmayan bir şekilde yazılabilir.
Alt çizgi
Dikkate alınması gereken başka birçok konu var, ancak bunun gibi ikisini düşünmeyi seviyorum:
- Programınız G / Ç'ye bağlıysa , tek iş parçacıklı asenkronizasyon muhtemelen oldukça iyi çalışacaktır.
- Programınız CPU'ya bağlıysa , o zaman çok parçalı bir sistem muhtemelen en iyisi olacaktır.
Sizin durumunuzda, ne tür asenkronize çalışmanın tamamlandığını ve bu görevlerin ne sıklıkla ortaya çıktığını belirlemeniz gerekir.
- Her talepte ortaya çıkıyor mu? Öyleyse, istek sayısı arttıkça bellek muhtemelen bir sorun haline gelecektir.
- Bu görevler sipariş edildi mi? Öyleyse, birden fazla iş parçacığı kullanıyorsanız senkronizasyonu düşünmeniz gerekir.
- Bu görevler CPU yoğun mu? Eğer öyleyse, tek bir diş yüke ayak uydurabiliyor mu?
Basit bir cevap yok. Kullanım durumunuzun ne olduğunu göz önünde bulundurmalı ve buna göre tasarlamalısınız. Bazen eşzamansız tek iş parçacıklı bir model daha iyidir. Diğer zamanlarda, büyük paralel işleme elde etmek için çok sayıda diş kullanılması gerekir.
Diğer Hususlar
Seçtiğiniz eşzamanlılık modelinden ziyade, göz önünde bulundurmanız gereken başka konular da var. Erlang veya Clojure'u tanıyor musunuz? Uygulamanızın performansını artırabilmeniz için bu dillerden birinde güvenli çoklu iş parçacığı kodu yazabileceğinizi düşünüyor musunuz? Bu dillerden birinde hız kazanmanız uzun zaman alacak mı ve öğrendiğiniz dil gelecekte size fayda sağlayacak mı?
Bu iki sistem arasındaki iletişim ile ilgili zorluklara ne dersiniz? İki ayrı sistemi paralel olarak tutmak aşırı derecede karmaşık olacak mı? Erlang sistemi Django'dan nasıl görev alacak? Erlang bu sonuçları Django'ya nasıl iletecek? Performans, eklenen karmaşıklığın buna değeceği bir problem mi?
Son düşünceler
Django'yu her zaman yeterince hızlı buldum ve çok yoğun trafik çeken siteler tarafından kullanılıyor. Eşzamanlı istek sayısını ve yanıt süresini artırmak için yapabileceğiniz çeşitli performans optimizasyonları vardır. Kuşkusuz, şu ana kadar Celery ile hiçbir şey yapmadım, bu yüzden normal performans optimizasyonları muhtemelen bu asenkron işlerde karşılaşabileceğiniz sorunları çözmeyecektir.
Tabii ki, her zaman soruna daha fazla donanım atma önerisi vardır. Yeni bir sunucu sağlama maliyeti, tamamen yeni bir alt sistemin geliştirme ve bakım maliyetinden daha mı ucuz?
Bu noktada çok fazla soru sordum, ama niyetim buydu. Cevap, analiz olmadan ve daha fazla ayrıntı olmadan kolay olmayacak. Sorunları analiz edebilmek, sorulması gereken soruları bilmekten kaynaklanıyor.
İçimdeki hisler başka bir dilde tekrar yazmanın gereksiz olduğunu söylüyor. Karmaşıklık ve maliyet muhtemelen çok büyük olacak.
Düzenle
İzlemeye Tepki
Takipleriniz bazı ilginç kullanım durumları sunar.
1. Django HTTP istekleri dışında çalışıyor
İlk örneğiniz NFC etiketlerini okuduktan sonra veritabanını sorguladı. Bu bölümü başka bir dilde yazmanın sizin için bu kadar faydalı olacağını sanmıyorum, çünkü sadece veritabanını veya bir LDAP sunucusunu sorgulamak ağ giriş / çıkış (ve potansiyel olarak veritabanı performansı) tarafından bağlanacak. Öte yandan, her yönetim komutu kendi işlemi olarak çalıştırılacağından, eşzamanlı isteklerin sayısı sunucunun kendisi tarafından sınırlandırılacaktır. Halen çalışan bir işleme mesaj gönderemediğiniz için performansı etkileyen kurulum ve ayırma süresi olacaktır. Bununla birlikte, her biri yalıtılmış bir işlem olacağından, aynı anda birden fazla istek gönderebileceksiniz.
Bu durumda, araştırabileceğiniz iki yol görüyorum:
- Veritabanınızın bağlantı havuzuyla aynı anda birden fazla sorguyu işleme yeteneğine sahip olduğundan emin olun. (Örneğin, Oracle, Django’yu buna göre yapılandırmanızı gerektirir
'OPTIONS': {'threaded':True}
.) Veri tabanı düzeyinde veya Django düzeyinde kendi veritabanınız için ince ayar yapabileceğiniz benzer yapılandırma seçenekleri olabilir. Veritabanınızın sorgularını hangi dilde yazdığınız önemli değildir, LED'leri yakmadan önce bu verilerin geri dönmesini beklemeniz gerekecektir. Sorgulama kodunun performans olabilir (gerçi bir fark yaratmak ve Django ORM ışık hızında değil ama genelde yeterince hızlı).
- Kurulum / ayırma süresini en aza indirin. Sürekli çalışan bir işlem yapın ve mesaj gönderin. (Hatalıysam beni düzelt, ancak asıl sorunuzun odaklandığı şey budur.) Bu işlemin Python / Django'da mı yoksa başka bir dilde / çerçevede mi yazıldığını. Yönetim komutlarını çok sık kullanma fikrinden hoşlanmıyorum. Sürekli çalışan, NFC okuyucularından gelen mesajları ileti kuyruğuna iten, kerevizin daha sonra Django'ya okuduğu ve ilettiği küçük bir kod parçası olması mümkün müdür? Python'da yazılsa bile (ancak Django! Değil) küçük bir programın kurulması ve parçalanması, bir Django programının başlatılması ve durdurulmasından (tüm alt sistemleriyle) daha iyi olmalıdır.
Django için hangi web sunucusunu kullandığınızdan emin değilim. mod_wsgi
Apache için, hizmetin talep ettiği işlemler içindeki işlemlerin ve iş parçacıklarının sayısını yapılandırmanıza olanak sağlar. Servis verilebilir istek sayısını optimize etmek için web sunucunuzun ilgili konfigürasyonunu değiştirdiğinizden emin olun.
2. Django sinyalleriyle “mesaj iletme”
İkinci kullanım durumunuz da oldukça ilginç; Bunun için cevapları alıp almadığımdan emin değilim. Model örneklerini siliyorsanız ve daha sonra üzerinde çalışmak istiyorsanız, bunları seri hale getirmek JSON.dumps
ve seri hale getirmek mümkün olabilir JSON.loads
. Nesne grafiğini daha sonra tamamen yeniden oluşturmak mümkün olmaz (ilgili modellerin sorgulanması), çünkü ilgili alanlar veritabanından tembel olarak yüklenir ve bu bağlantı artık varolmaz.
Diğer seçenek, bir şekilde silmek için bir nesneyi işaretlemek ve yalnızca istek / yanıt döngüsünün sonunda (tüm sinyallerin servisi yapıldıktan sonra) silmek olacaktır. Güvenmek yerine bunu uygulamak için özel bir sinyal gerektirebilir post_delete
.