Konuşkan arayüzlerden nasıl kaçınılır


10

Arka plan: Bir sunucu uygulaması tasarlıyorum ve farklı alt sistemler için ayrı dll'ler oluşturuyorum. İşleri basitleştirmek için iki alt sistemim olduğunu varsayalım: 1) Users2)Projects

Kullanıcıların genel arayüzünün aşağıdaki gibi bir yöntemi vardır:

IEnumerable<User> GetUser(int id);

Ve Projects'in genel arayüzünün aşağıdaki gibi bir yöntemi vardır:

IEnumerable<User> GetProjectUsers(int projectId);

Örneğin, belirli bir proje için kullanıcıları göstermemiz gerektiğinde, arayabiliriz GetProjectUsersve bu, bir veri ızgarasında veya benzerinde gösterilecek yeterli bilgiye sahip nesneleri geri verir.

Sorun: İdeal olarak, Projectsalt sistem de kullanıcı bilgilerini depolamamalı ve sadece bir projeye katılan kullanıcıların Kimlikleri'ni saklamalıdır. Sunmak için GetProjectUsers, kendi veritabanında saklanan her kullanıcı kimliği GetUseriçin Userssistemi çağırması gerekir . Ancak, bu GetUser, Useralt sistem içinde çok sayıda ayrı sql sorgusuna neden olan çok sayıda ayrı çağrı gerektirir . Bunu gerçekten test etmedim ama bu konuşkan tasarıma sahip olmak sistemin ölçeklenebilirliğini etkileyecek.

Ben kenara alt sistemlerin ayrılmasını koyarsanız, ben olabilir iki sistemde tek bir şema erişilebilir tüm bilgileri saklamak ve Projectssadece yapabileceği JOINtek sorguda tüm proje kullanıcılarını alır. Projectsayrıca Usersorgu sonuçlarından nasıl nesne üretileceğini de bilmelidir . Ancak bu, birçok avantajı olan ayrılığı kırar.

Soru: Sırasındaki tüm bu bireysel GetUsergörüşmelerden kaçınırken ayrılığı korumanın bir yolunu önerebilir GetProjectUsersmi?


Örneğin, sahip olduğum bir fikir Kullanıcılar için harici sistemlere kullanıcıları bir etiket-değer çiftiyle "etiketleme" ve belirli bir değere sahip kullanıcılardan talep etme yeteneği vermekti.

void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);

Ardından Projeler sistemi her kullanıcıyı projeye eklendikçe etiketleyebilir:

AddUserTag(userId,"project id", myProjectId.ToString());

ve GetProjectUsers sırasında, tüm proje kullanıcılarını tek bir çağrıda isteyebilir:

var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());

emin değilim bölüm: evet, Kullanıcılar projelerin agnostik ama gerçekten proje üyeliği hakkında bilgi Projeler değil, Kullanıcılar sisteminde saklanır. Kendimi doğal hissetmiyorum, bu yüzden burada eksik olduğum büyük bir dezavantaj olup olmadığını belirlemeye çalışıyorum.

Yanıtlar:


10

Sisteminizde eksik olan önbellektir.

Diyorsun:

Ancak, bu GetUser, Useralt sistem içinde çok sayıda ayrı sql sorgusuna neden olan çok sayıda ayrı çağrı gerektirir .

Bir yönteme yapılan çağrıların sayısının SQL sorgularının sayısıyla aynı olması gerekmez. Bir kez kullanıcı hakkında bilgi almak, neden olur sorgusu aynı bilgileri için değişiklik olmadı yine olur? Büyük olasılıkla, bellekteki tüm kullanıcıları önbelleğe alabilirsiniz, bu da sıfır SQL sorgularına neden olur (kullanıcı değişmedikçe).

Öte yandan, Projectshem projeleri hem de kullanıcıları ile alt sistem sorgusu yaparak INNER JOIN, ek bir sorun ortaya çıkarırsınız: kodunuzdaki iki farklı konumda aynı bilgi parçasını sorgulayarak önbellek geçersiz kılmayı son derece zorlaştırırsınız. Sonuç olarak:

  • Ya daha sonra hiçbir zaman önbellek kullanmayacaksınız,

  • Veya bir bilgi değiştiğinde nelerin geçersiz kılınacağını incelemek için haftalar veya aylar harcayacaksınız,

  • Veya basit yerlere önbellek geçersiz kılma ekleyeceksiniz, diğerlerini unutup bulmak zor hatalara yol açacaksınız.


Sorunuzu yeniden okurken, ilk kez kaçırdığım bir anahtar kelimeyi farkettim: ölçeklenebilirlik . Genel bir kural olarak, bir sonraki kalıbı takip edebilirsiniz:

  1. Sistemin yavaş olup olmadığını kendinize sorun (yani işlevsel olmayan bir performans gereksinimini ihlal ediyor mu, yoksa sadece bir kabus mu kullanıyorsunuz).

    Sistem yavaş değilse , performanstan rahatsız olmayın. Temiz kod, okunabilirlik, sürdürülebilirlik, test, şube kapsamı, temiz tasarım, ayrıntılı ve anlaşılması kolay belgeler, iyi kod yorumları hakkında rahatsız olun.

  2. Evetse, darboğaz arayın. Bunu tahmin ederek değil, profil oluşturarak yaparsınız . Profil oluşturarak, darboğazın tam yerini belirlersiniz ( tahmin ettiğinizde neredeyse her seferinde yanlış anlayabileceğiniz göz önüne alındığında ) ve şimdi kodun bu kısmına odaklanabilirsiniz.

  3. Darboğaz bulunduğunda, çözüm arayın. Bunu tahmin, kıyaslama, profil oluşturma, alternatifler yazma, derleyici optimizasyonlarını anlama, size bağlı optimizasyonları anlama, Yığın Taşması ile ilgili sorular sorma ve düşük düzeyli dillere (gerekirse Assembler dahil) geçme yoluyla yapabilirsiniz.

ProjectsAlt sistemle ilgili alt sisteme bilgi sormanın asıl sorunu nedir Users?

Gelecekteki nihai ölçeklenebilirlik sorunu? Bu bir sorun değil. Her şeyi tek bir monolitik çözümle birleştirmeye veya aynı verileri birden fazla konumdan sorgulamaya başlarsanız ölçeklenebilirlik kabus haline gelebilir (önbellek oluşturma zorluğu nedeniyle aşağıda açıklandığı gibi).

Varsa zaten o zaman fark edilebilir bir performans sorunu, adım 2, darboğaz araştırın.

Görünüşe göre, darboğaz var ve alt sistem üzerinden (ve veritabanı sorgulama düzeyinde yer alıyor) Projectskullanıcı istekleri nedeniyle Users, ancak o zaman bir alternatif aramak gerekir.

En yaygın alternatif, önbellek uygulamak ve sorgu sayısını önemli ölçüde azaltmak olacaktır. Önbelleğe almanın yardımcı olmadığı bir durumdaysanız, daha fazla profil oluşturma size sorgu sayısını azaltmanız veya veritabanı dizinleri eklemeniz (veya kaldırmanız) veya daha fazla donanım atmanız veya tüm sistemi tamamen yeniden tasarlamanız gerektiğini gösterebilir. .


Seni yanlış anlamadığım sürece, "bireysel GetUser çağrılarını saklayın, ancak db gidiş-dönüşlerinden kaçınmak için önbellekleme kullanın" diyorsunuz.
Eren Ersönmez

@ ErenErsönmez: GetUserveritabanını sorgulamak yerine önbelleğe bakacak. Bu GetUser, veritabanı yerine bellekten veri yükleyeceği için (önbellek geçersiz kılınmadıkça), aslında kaç kez arayacağınız önemli olmadığı anlamına gelir .
Arseni Mourzenko

ana sistemi vurgulayan iyi bir iş yapmadığım için bu iyi bir öneri. Kullanıcı ve Projeler örneğim doğal olarak sizi nispeten az sayıda ve nadiren değişen kullanıcı olduğuna inandırır. Belki daha iyi bir örnek Belgeler ve Projeler olabilirdi. Birkaç milyon belgeniz olduğunu, her gün binlerce kişinin eklendiğini ve Proje sisteminin belgelerini saklamak için Belge sistemini kullandığını düşünün. Yine de önbelleğe almayı tavsiye eder misiniz? Muhtemelen hayır, değil mi?
Eren Ersönmez

@ ErenErsönmez: Ne kadar çok veriye sahip olursanız, önbellek o kadar kritik görünür. Genel bir kural olarak, okuma sayısını yazma sayısıyla karşılaştırın. Günde "binlerce" belge eklenirse ve günde milyonlarca selectsorgu varsa önbelleğe almayı daha iyi kullanırsınız. Öte yandan, bir veritabanına milyarlarca varlık ekliyorsanız, ancak selectçok seçici wheres içeren yalnızca birkaç bin s alıyorsanız , önbellekleme o kadar yararlı olmayabilir.
Arseni Mourzenko

muhtemelen haklısın - muhtemelen henüz sahip olmadığım bir sorunu düzeltmeye çalışıyorum. Muhtemelen olduğu gibi uygulayacağım ve gerekirse daha sonra geliştirmeye çalışacağım. Önbellekleme uygun değilse, örneğin varlıkların eklendikten sonra yalnızca 1-2 kez okunması muhtemelse, soruya eklediğim olası I çözümünün işe yarayabileceğini düşünüyor musunuz? Bununla ilgili büyük bir sorun görüyor musunuz?
Eren Ersönmez
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.