İleti kodlama konusunda dikkat edilmesi gerekenler
Birçok bulut uygulaması, sistemin bileşenleri arasında bilgi alışverişi yapmak için zaman uyumsuz iletiler kullanır. Mesajlaşmanın önemli bir yönü, yük verilerini kodlamak için kullanılan biçimdir. bir mesajlaşma teknolojisi seçtiktensonra, sonraki adım iletilerin nasıl kodlanacağını tanımlamaktır. Birçok seçenek vardır, ancak doğru seçim kullanım örneğine bağlıdır.
Bu makalede dikkat edilmesi gereken bazı noktalar açıklanmaktadır.
İleti değişimi gereksinimleri
Üretici ve tüketici gereksinimleri arasında ileti alışverişi:
- İletinin yükünü tanımlayan bir şekil veya yapı.
- Yükü temsil eden bir kodlama biçimi.
- Kodlanmış yükü okumak ve yazmak için serileştirme kitaplıkları.
İletinin üreticisi, ileti şeklini iş mantığına ve tüketicilere göndermek istediği bilgilere göre tanımlar. Şekli yapılandırmak için, bilgileri ayrık veya ilgili konulara (alanlar) bölün. Bu alanların değerlerinin özelliklerine karar verin. Aşağıdaki soruları göz önünde bulundurmanız gerekir.
- En verimli veri türü nedir?
- Yükün her zaman belirli alanları var mı?
- Yükün tek bir kaydı mı yoksa yinelenen bir değer kümesi mi var?
Ardından, ihtiyacınıza bağlı olarak bir kodlama biçimi seçin. Belirli faktörler arasında ihtiyacınız olduğunda yüksek oranda yapılandırılmış veriler oluşturma, iletiyi kodlamak ve aktarmak için geçen süre ve yükü ayrıştırma olanağı yer alır. Kodlama biçimine bağlı olarak, iyi desteklenen bir serileştirme kitaplığı seçin.
İletinin tüketicisi, gelen iletilerin nasıl okunduğunu bilmesi için bu kararların farkında olmalıdır.
İletileri aktarmak için, üretici iletiyi bir kodlama biçimine serileştirir. Alıcı sonunda, tüketici verileri kullanmak için yükü seri durumdan çıkartır. Bu şekilde her iki varlık da modeli paylaşır ve şekil değişmediği sürece mesajlaşma sorunsuz devam eder. Sözleşme değiştiğinde, kodlama biçimi tüketiciyi bozmadan değişikliği işleyebilecek şekilde olmalıdır.
JSON gibi bazı kodlama biçimleri kendi kendine açıklayıcıdır; başka bir deyişle şemaya başvurmadan ayrıştırılabilirler. Ancak, bu tür biçimler daha büyük iletiler verme eğilimindedir. Diğer biçimlerde, veriler kolayca ayrıştırılamayabilir, ancak iletiler sıkıştırılır. Bu makalede, biçim seçmenize yardımcı olabilecek bazı faktörler vurgulanmaktadır.
Kodlama biçimiyle ilgili dikkat edilmesi gerekenler
Kodlama biçimi, yapılandırılmış bir veri kümesinin bayt olarak nasıl temsil edilir tanımlar. İleti türü biçim seçimini etkileyebilir. İş işlemleriyle ilgili iletiler büyük olasılıkla yüksek oranda yapılandırılmış veriler içerir. Ayrıca, denetim amacıyla daha sonra almak isteyebilirsiniz. Bir olay akışı için, bir kayıt dizisini mümkün olan en kısa sürede okumak ve istatistiksel analiz için depolamak isteyebilirsiniz.
Kodlama biçimi seçerken göz önünde bulundurmanız gereken bazı noktalar aşağıdadır.
İnsan okunabilirliği
İleti kodlaması geniş ölçüde metin tabanlı ve ikili biçimlere ayrılabilir.
Metin tabanlı kodlama ile ileti yükü düz metin biçimindedir ve bu nedenle herhangi bir kod kitaplığı kullanmadan bir kişi tarafından denetlenebilir. İnsan tarafından okunabilir biçimler arşiv verileri için uygundur. Ayrıca, bir insan yükü okuyabildiğinden, metin tabanlı biçimlerin hata ayıklaması ve sorun giderme için günlüklere gönderilmesi daha kolaydır.
Dezavantajı, yükün daha büyük olma eğiliminde olmasıdır. Yük boyutu, gerektiğinde insan tarafından okunabilirliğe geri dönülebilir olduğu sürece, genellikle bir minifikasyon işlemiyle azaltılabilir. Yaygın metin tabanlı biçimler JSON ve YAML'dir.
Şifreleme
İletilerde hassas veriler varsa, bu iletilerin tamamen şifrelenmesi gerekip gerekmediğini düşünün. Azure Service Bus verilerinin bekleme sırasında şifrelenmesi,bu kılavuzda açıklandığı gibi gerçekleştirilmelidir. Alternatif olarak, yalnızca belirli alanların şifrelenmesini gerekiyorsa ve bulut maliyetlerini azaltmayı tercih ediyorsanız, bunun için NServiceBus gibi bir kitaplık kullanmayı göz önünde bulundurun.
Kodlama boyutu
İleti boyutu, ağ G/Ç performansını kablo üzerinde etkiler. İkili biçimler, metin tabanlı biçimlerden daha küçüktür. İkili biçimler serileştirme/deserileştirme kitaplıkları gerektirir. Şifresi çözülmedikçe yük okunamaz.
Kablo ayak izini azaltmak ve iletileri daha hızlı aktarmak istiyorsanız ikili biçim kullanın. Bu biçim kategorisi, depolama veya ağ bant genişliğinin sorun olduğu senaryolarda önerilir. İkili biçimler için seçenekler Apache Avro, Google Protokol Arabellekleri (protobuf), MessagePack ve Kısa İkili Nesne Gösterimi (CBOR) içerir. Bu biçimlerin avantajları ve dezavantajları daha sonra kodlama biçimleri içinSeçenekleri bölümünde açıklanmıştır.
Dezavantajı, yükün insan tarafından okunamıyor olmasıdır. Çoğu ikili biçim, bakımı maliyetli olabilecek karmaşık sistemler kullanır. Arşiv verilerini almak istiyorsanız ve bu verileri çözmek için özel kitaplıklara ihtiyaç varsa, bu kitaplıklar desteklenmeyebilir.
Bağlayıcı olmayan biçimler için, teknik olarak gereksiz boşlukları ve karakterleri kaldırmak için bir küçültme işlemi kullanmak, ancak yine de biçimin belirtimiyle hizalamayı korumak kodlama boyutuna yardımcı olabilir. Varsayılan olarak küçültmek için kodlayıcınızın özelliklerini değerlendirin. Örneğin, uygulamasından JsonSerializerOptions.WriteIndented
. NET'in System.Text.Json.JsonSerializer
, JSON metni oluştururken otomatik küçültmeyi denetler.
Yükü anlama
İleti yükü bayt dizisi olarak gelir. Bu sırayı ayrıştırmak için tüketicinin yükteki veri alanlarını açıklayan meta verilere erişimi olmalıdır. Meta verileri depolamak ve dağıtmak için iki ana yaklaşım vardır:
Etiketli meta verileri. Özellikle JSON gibi bazı kodlamalarda alanlar, iletinin gövdesindeki veri türü ve tanımlayıcıyla etiketlenir. Bu biçimler kendi kendini açıklayan çünkü bunlar bir şemaya başvurmadan bir değer sözlüğüne ayrıştırılabilir. Tüketicinin alanları anlamasının bir yolu, beklenen değerleri sorgulamaktır. Örneğin, üretici JSON'da bir yük gönderir. Tüketici JSON'ı bir sözlüğe ayrıştırarak yükü anlamak için alanların varlığını denetler. Bir diğer yol da tüketicinin üretici tarafından paylaşılan bir veri modelini uygulamasıdır. Örneğin, statik olarak yazılan bir dil kullanıyorsanız, birçok JSON serileştirme kitaplığı bir JSON dizesini yazılan bir sınıfa ayrıştırabilir.
şema. Şema, iletinin yapısını ve veri alanlarını resmi olarak tanımlar. Bu modelde, üretici ve tüketicinin iyi tanımlanmış bir şema aracılığıyla bir sözleşmesi vardır. Şema veri türlerini, gerekli/isteğe bağlı alanları, sürüm bilgilerini ve yükün yapısını tanımlayabilir. Üretici, yazıcı şemasına göre yükü gönderir. Tüketici, bir okuyucu şeması uygulayarak yükü alır. İleti, kodlamaya özgü kütüphaneler kullanılarak serileştirilir veya seri durumdan çıkarılır. Şemaları dağıtmanın iki yolu vardır:
Şemayı iletide ön bilgi veya üst bilgi olarak, ancak yükten ayrı olarak depolayın.
Şemayı harici olarak depolayın.
Bazı kodlama biçimleri şemayı tanımlar ve şemadan sınıf oluşturan araçları kullanır. Üretici ve tüketici, bu sınıfları ve kitaplıkları yükü serileştirmek ve ters serileştirmek için kullanır. Kitaplıklar, yazıcı ve okuyucu şeması arasında uyumluluk denetimleri de sağlar. Hem protobuf hem de Apache Avro bu yaklaşımı izler. Önemli fark, protobuf'un dilden bağımsız bir şema tanımına sahip olması, ancak Avro'nun küçük JSON kullanmasıdır. Diğer bir fark, her iki biçimin de okuyucu ve yazıcı şemaları arasında uyumluluk denetimleri sağlamasıdır.
Şemayı bir şema kayıt defterinde harici olarak depolamanın başka bir yolu. İleti, şemaya ve yüke bir başvuru içerir. Üretici iletide şema tanımlayıcısını gönderir ve tüketici bu tanımlayıcıyı bir dış depodan belirterek şemayı alır. Taraflar, iletileri okumak ve yazmak için biçime özgü kitaplıkları kullanır. Şemayı depolamanın yanı sıra, bir kayıt defteri üretici ve tüketici arasındaki sözleşmenin şema geliştikçe bozulmadığından emin olmak için uyumluluk denetimleri sağlayabilir.
Bir yaklaşım seçmeden önce neyin daha önemli olduğuna karar verin: veri aktarımı boyutu veya arşivlenen verileri daha sonra ayrıştırma olanağı.
Şemanın yükle birlikte depolanması daha büyük bir kodlama boyutu sağlar ve aralıklı iletiler için tercih edilir. Daha küçük bayt öbeklerinin aktarılması çok önemliyse veya bir kayıt dizisi bekliyorsanız bu yaklaşımı seçin. Dış şema deposunun bakımının maliyeti yüksek olabilir.
Ancak yükün isteğe bağlı olarak kod çözülmesi boyuttan daha önemliyse, yükle birlikte şemayı veya etiketli meta veri yaklaşımını dahil etmek, daha sonra kod çözmeyi sağlar. İleti boyutunda önemli bir artış olabilir ve depolama maliyetini etkileyebilir.
Şema sürümleme
İş gereksinimleri değiştikçe şeklin değişmesi beklenir ve şema gelişir. Sürüm oluşturma, üreticinin yeni özellikler içerebilecek şema güncelleştirmelerini belirtmesine olanak tanır. Sürüm oluşturmanın iki yönü vardır:
Tüketici değişikliklerin farkında olmalıdır.
Bunun bir yolu, tüketicinin şemanın değişip değişmediğini belirlemek için tüm alanları denetlemesidir. Başka bir yol, üreticinin iletiyle birlikte bir şema sürüm numarası yayımlamasıdır. Şema geliştikçe üretici sürümü artırır.
Değişiklikler tüketicilerin iş mantığını etkilememeli veya bozmamalıdır.
Mevcut şemaya bir alan eklendiğini varsayalım. Yeni sürümü kullanan tüketiciler eski sürüme göre bir yük alırsa, yeni alanın eksikliğini atlayamazlarsa mantığı bozulabilir. Ters durumu göz önünde bulundurarak, yeni şemada bir alanın kaldırıldığını varsayalım. Eski şemayı kullanan tüketiciler verileri okuyamayabilir.
Avro gibi kodlama biçimleri, varsayılan değerleri tanımlama olanağı sunar. Yukarıdaki örnekte, alan varsayılan bir değerle eklenirse, eksik alan varsayılan değerle doldurulur. Protobuf gibi diğer biçimler, gerekli ve isteğe bağlı alanlar aracılığıyla benzer işlevler sağlar.
Yük yapısı
Verilerin yükte nasıl düzenlendiğini göz önünde bulundurun. Bu bir kayıt dizisi mi yoksa ayrık tek bir yük mü? Yük yapısı şu modellerden birinde kategorilere ayırılabilir:
Dizi/sözlük/değer: Bir veya çok boyutlu dizilerdeki değerleri tutan girdileri tanımlar. Girdilerin benzersiz anahtar-değer çiftleri vardır. Karmaşık yapıları temsil etmek için genişletilebilir. Bazı örnekler şunlardır: JSON, Apache Avro ve MessagePack.
İletiler farklı şemalarla ayrı ayrı kodlanmışsa bu düzen uygundur. Birden çok kaydınız varsa, yük aşırı yedekli hale gelebilir ve bu da yükün kabarmasına neden olabilir.
Tablo verileri: Bilgiler satırlara ve sütunlara ayrılır. Her sütun bir alanı veya bilgilerin konusunu belirtir ve her satır bu alanların değerlerini içerir. Bu düzen, zaman serisi verileri gibi yinelenen bir bilgi kümesi için verimlidir.
CSV, en basit metin tabanlı biçimlerden biridir. Verileri ortak üst bilgi içeren bir kayıt dizisi olarak sunar. İkili kodlama için, Apache Avro'nun ön eki, bir CSV üstbilgisine benzer, ancak daha kompakt bir kodlama boyutu üretir.
Kitaplık desteği
İyi bilinen biçimleri özel bir model yerine kullanmalısınız. İyi bilinen biçimler, topluluk tarafından evrensel olarak desteklenen kitaplıklar aracılığıyla desteklenir. Özelleştirilmiş biçimlerle, belirli kitaplıklara ihtiyacınız vardır. İş mantığınız, kütüphaneler tarafından sağlanan bazı API tasarım seçimlerinin etrafından dolanmak zorunda kalabilir.
Şema tabanlı biçim için, okuyucu ve yazıcı şeması arasında uyumluluk denetimleri yapan bir kodlama kitaplığı seçin. Apache Avro gibi bazı kodlama kütüphaneleri, kullanıcının iletiyi seri durumdan çıkarmadan önce hem yazma hem de okuma şeması belirtmesini bekler. Bu denetim, tüketicinin şema sürümlerinin farkında olmasını sağlar.
Birlikte çalışabilirlik
Biçim seçiminiz belirli iş yüküne veya teknoloji ekosisteminize bağlı olabilir.
Mesela:
Azure Stream Analytics JSON, CSV ve Avro için yerel desteğe sahiptir. İş yükünüz Stream Analytics'i kullandığında, bu biçimlerden birini seçmek mantıklıdır.
JSON, HTTP REST API'leri için standart bir değişim biçimidir. Uygulamanız istemcilerden JSON yükleri alır ve bunları zaman uyumsuz işleme için bir ileti kuyruğuna yerleştirirse, farklı bir biçimde yeniden kodlamak yerine mesajlaşma için JSON kullanmak mantıklı olabilir.
Bunlar birlikte çalışabilirlik konusunda dikkat edilmesi gereken iki örnektir. Genel olarak, standart biçimler özel biçimlerden daha birlikte çalışabilir. Metin tabanlı seçeneklerde JSON en çok birlikte çalışabilen seçeneklerden biridir.
Kodlama biçimleri için seçenekler
Bazı popüler kodlama biçimleri aşağıdadır. Bir biçim seçmeden önce dikkat edilmesi gerekenleri dikkate alın.
JSON
JSON açık bir standarttır (IETF RFC8259). Dizi/sözlük/değer modelini izleyen metin tabanlı bir biçimdir.
JSON, meta verileri etiketlemek için kullanılabilir ve yükü şema olmadan ayrıştırabilirsiniz. JSON, ileri ve geri uyumluluğun yardımcı olduğu isteğe bağlı alanları belirtme seçeneğini destekler.
En büyük avantajı, evrensel olarak kullanılabilir olmasıdır. Birçok mesajlaşma hizmeti için en çok birlikte çalışabilir ve varsayılan kodlama biçimidir.
Metin tabanlı bir biçim olarak, kablo üzerinde verimli değildir ve depolamanın önemli olduğu durumlarda ideal bir seçim değildir. Mümkün olduğunda küçültme tekniklerini kullanın. Önbelleğe alınmış öğeleri HTTP aracılığıyla doğrudan bir istemciye döndürüyorsanız, JSON depolamak, başka bir biçimden seri durumdan çıkarma ve ardından JSON'a seri hale getirme maliyetinden tasarruf etmenizi sağlayabilir.
Tek kayıtlı iletiler veya her iletinin farklı bir şemaya sahip olduğu bir ileti dizisi için JSON kullanın. Zaman serisi verileri gibi bir kayıt dizisi için JSON kullanmaktan kaçının.
ikili JSON (BSON)gibi başka JSON varyasyonları da vardır. Bu, MongoDB ile çalışmaya hizalanmış bir ikili kodlamadır.
Comma-Separated Değerleri (CSV)
CSV, metin tabanlı bir tablosal biçimdir. Tablonun üst bilgisi alanları gösterir. Mesajın bir kayıt kümesi içerdiği durumlarda tercih edilen bir seçimdir.
Dezavantajı standardizasyon eksikliğidir. Ayırıcıları, üst bilgileri ve boş alanları ifade etmenin birçok yolu vardır.
Protokol Arabellekleri (protobuf)
Protokol Arabellekleri (veya protobuf), anahtar/değer çiftlerinde şemaları tanımlamak için güçlü bir şekilde yazılmış tanım dosyalarını kullanan bir serileştirme biçimidir. Bu tanım dosyaları daha sonra iletileri seri hale getirmek ve seri durumdan çıkarma için kullanılan dile özgü sınıflara derlenir.
İleti, daha hızlı aktarıma neden olan sıkıştırılmış bir ikili küçük yük içerir. Dezavantajı, yükün insan tarafından okunamaz olmasıdır. Ayrıca şema dış olduğundan, arşivlenmiş verileri almanız gereken durumlar için önerilmez.
Apache Avro
Apache Avro, protobuf'a benzer bir tanım dosyası kullanan ancak derleme adımı olmayan bir ikili serileştirme biçimidir. Bunun yerine, serileştirilmiş veriler her zaman bir şema ön derlemesi içerir.
Ön bilgi, üst bilgiyi veya şema tanımlayıcısını barındırabilir. Daha küçük kodlama boyutu nedeniyle, akış verileri için Avro önerilir. Ayrıca, bir dizi kayıta uygulanan bir başlığı olması nedeniyle, tablosal veriler için iyi bir seçimdir.
Apache Parquet
Apache Parquet genellikle Apache Hadoop ve ilgili veri işleme çerçeveleriyle ilişkili sütunlu bir depolama dosyası biçimidir.
biçimi veri sıkıştırmayı destekler ve şema evrimini desteklemek için bazı sınırlı özelliklere sahiptir. Bu biçim, büyük olasılıkla yalnızca iş yükünüzdeki bu verileri oluşturmak veya kullanmakla sorumlu olacak diğer büyük veri teknolojisi seçimleri nedeniyle kullanacağınız bir örnektir.
MessagePack
MessagePack, kablo üzerinden iletim için sıkıştırılacak şekilde tasarlanmış bir ikili serileştirme biçimidir. İleti şeması veya ileti türü denetimi yok. Toplu depolama için bu biçim önerilmez.
CBOR
Kısa İkili Nesne Gösterimi (CBOR) (Belirtim) küçük kodlama boyutu sunan bir ikili biçimdir. CBOR'un MessagePack'e kıyasla avantajı, RFC7049 IETF ile uyumlu olmasıdır.
Sonraki adımlar
- Azure Service Bus iletilerini, yüklerini ve seri hale getirme
- ASP.NET Core Yanıt Sıkıştırması