Monolit ve Mikro Hizmet Mimarileri

 

Üst düzey mimari, yazılımın her şeyi kapsayan kod tasarımıdır. Bir diyagramla tanımlandığında, üst düzey bir mimari genellikle tüm kod tabanını temsil eden bir soyutlama olan kısa etiketlere sahip birkaç ila düzinelerce birbirine bağlı şekil gibi görünür. Bu bölümde "mimari" terimini "üst düzey mimari" teriminin yerine kullanacağız (diğer bağlamlarda yazılım mimarisi daha düşük seviyelerdeki kod tasarımını ifade edebilir).

Bu bölümde her üst düzey mimariyi ele almayacağız. Bunun yerine, iki farklı üst düzey mimariye odaklanacağız: monolit ve mikro hizmetler. Farklı oldukları yönler hakkında konuşmak, bizi genel olarak üst düzey mimariye uygulanabilir kavramlara götürecektir.

Monolit Mimari

Monolit yazılım, ayrı ayrı çalışan ve ayrı ayrı yararlı olan birden fazla bağımsız bileşene kolayca bölünemeyen, birbirine bağlı bir kod tabanıdır.

Bir monolit örneği düşünmeye çalışıyorsanız ve aklınıza hiçbir şey gelmiyorsa, bunun nedeni muhtemelen bu mimarinin planlamaya gerek kalmadan ortaya çıkabilecek kadar yaygın olmasıdır. İlk bilgisayar programınız muhtemelen küçük bir monolitti. Daha fazla kod/dosya/sınıf/bileşen eklemeye devam ederseniz, mimariyi değiştirmediğiniz sürece yazılım daha büyük bir monolit haline gelir.

Mikro Hizmet Mimarisi

Mikro hizmetler, her biri ayrı bir süreçte çalışan ve ayrı ayrı yararlı olabilen ayrı uygulamalardır. Bu bölümde mikro hizmet mimarisini kullanan yazılımların temel özellikleri açıklanmaktadır. Alt başlıklar Lewis & Fowler'dan (2014) alınmıştır. Martin Fowler'ın Microservices Guide (Fowler, 2019) adlı kitabı ek tartışmalar sunmaktadır.

"Akıllı Uç Noktalar ve Aptal Borular"

“Dumb pipes” basit mesaj içerikleri anlamına gelmez.

Bir mikro hizmet mimarisi içindeki iletişim borusu basittir ve hizmetlerin kendileri mesajları çevirmek ve başka şekilde işlemekle ilgilenir. Örneğin, mikro hizmetler genellikle bu tür mesajlara izin veren bir REST API aracılığıyla iletişim kurar: GET, POST (oluşturma), PUT (güncelleme) veya DELETE. Mesajların içeriği karmaşık olabilir, ancak bununla başa çıkmak hizmetlerin işidir.

"Hizmetler Aracılığıyla Bileşenleştirme"

Bir hizmet sunsa da, kodunu kodunuza dahil ediyorsanız bir kütüphane bir hizmet değildir.

Bir mikro hizmet mimarisinde bileşenler hizmetlerdir. Lewis ve Fowler'ın (2014) bileşen tanımı "bağımsız olarak değiştirilebilen ve yükseltilebilen bir yazılım birimi"dir. Bir hizmet kendi sürecinde çalışırken işlevsellik sağlar. Bir monolit tipik olarak sıkı bağlantıya sahip koda ve aynı süreçte çalışan bileşenlere sahiptir.

Bileşenleri hizmetlere ayırmanın avantajları:

  • Bağımsızlık: Her bir hizmet, yazılımın diğer bileşenlerinden aynı şeyi gerektirmeden güncellenebilir, test edilebilir, başlatılabilir ve durdurulabilir. Buna karşılık, bazı monolitik yazılımlarda, bir geliştirici her değişiklik yaptığında tüm testlerin çalıştırılması gerekir ve bu da uzun bir beklemeye neden olabilir. Bir hizmet başarısız olursa, ona bağlı olan herhangi bir yazılım bu hizmetten yoksun kalır, ancak yazılımın geri kalanının etkilenmesi gerekmez.
  • Standartlaştırılmış bileşen iletişimi: Servis iletişim boruları basit ve her seferinde aynı olabilir. Bu, iki bileşeni bağlarken daha az düşünmeyi, daha az hata yapmayı ve kapsüllemeyi daha az ihlal etmeyi sağlayabilir - sadece veri yolunu kullanın.

Bileşenleri hizmetlere bölmenin dezavantajları:

  • Daha pahalı iletişim: Bir monolitteki bileşenler doğrudan çağrılar yoluyla iletişim kurabilir (hızlı, hafif); bunun aksine, mikro hizmetler genellikle bir ağ üzerinden iletişim kurar. Mikro hizmet isteklerinin tipik olarak istek meta verilerini içermesi gerekir ve borular "aptal" olduğu için yanıtlar ekstra veri (daha yavaş, daha ağır) içerebilir.
  • Potansiyel olarak daha az güvenli iletişim: Bir ağ üzerinden iletişim, dinlenmeye ve değiştirilmeye daha yatkın olabilir.

"İş Yeteneklerine Göre Organize Edilmiş"

İstemci tarafı yazılımın birden fazla örneğinin bir veritabanı ile iletişim kuran sunucu tarafı yazılımla iletişim kurduğu istemci-sunucu mimarisini duymuş olabilirsiniz. Bu mimari teknoloji etrafında düzenlenmiştir. Bunu başka bir şekilde ifade etmek gerekirse: istemci tarafı yazılım, sunucu tarafı yazılım ve veritabanı arasındaki farklara aşina olmayan biri bu mimarinin bir diyagramını görmekten pek bir şey anlamayacaktır.

Buna karşılık, mikro hizmetler iş yetenekleri etrafında organize edilir. Bu terimin birden fazla tanımı vardır. Michell'in (2011) bütünleşik iş kabiliyeti tanımı bizim bahsettiğimiz şeye uymaktadır: "Bir iş kaynağının (veya kaynak gruplarının), diğer maddi ve maddi olmayan kaynakları kullanan bir süreç aracılığıyla çevreleri üzerinde hareket ederek müşteri değeri üretme potansiyeli."

İş yeteneklerine örnekler:

  • Üretici, 20 metreye 40 metrelik bir dikdörtgen buğday hamurunu 1,2 saniyede 0,5 cm'lik şeritler halinde dilimleyebiliyor ve bu şeritler daha sonra bir kişinin markette öğle yemeği için satın alabileceği paketlenmiş erişteler haline geliyor.
  • Bir kredi memuru, müşteriyi kredi alma sürecinde yönlendirerek müşterinin küçük bir işletme kurmasını sağlayabilir.
  • Bir evcil hayvan maması distribütörü, ülke çapındaki mağazalara düzenli olarak beslenme açısından dengeli kedi maması gönderebilir.
  • Yazılım, bir video dosyasını mobil cihazlarla uyumlu hale getirebilir.

İş yeteneklerine odaklanmanın bir sonucu, her mikro hizmetin kendi teknoloji yığınına (kendi veritabanı dahil) sahip olabilmesidir.

"Merkezi Olmayan Veri Yönetimi"

Bir mikro hizmet mimarisinde, merkezi bir veritabanını paylaşmak yerine her hizmetin tipik olarak kendi veritabanı vardır. Bu, yazılım bileşenlerinin ayrıştırılmasının bir parçasıdır ve hata önleme de dahil olmak üzere birçok faydası vardır. İki mikro hizmetin veri paylaşması gerekiyorsa, bu verilerin iki kopyasının tutarsız hale gelebilmesi bir dezavantajdır (örneğin, bir veritabanı henüz güncellemeyi almadığı için). Mikro hizmet veritabanlarının nihai tutarlılığa sahip olduğu söylenir, bu da zamanla her mikro hizmetin en güncel bilgilere sahip olacağı anlamına gelir, ancak bu arada bir uyumsuzluk olabilir (belki de insan kullanıcıları rahatsız edecek veya yanlış yönlendirecek bir uyumsuzluk).

"Merkezi Olmayan Yönetişim"

Mikro hizmetlerin yalnızca arayüzlerinde (iletişim borusu) uyumlu olması gerekir, böylece her birinin nasıl uygulanacağı konusunda esneklik sağlanır. Örneğin, her hizmet farklı bir dilde yazılabilir, böylece teknoloji yığını kararlarının ağırlığı azalır ve bu kararlardan ödün verme ihtiyacı azalır. Ekipler her bir hizmet için en uygun programlama dilini, çerçeveyi, mimariyi ve daha fazlasını seçebilir. Her bir mikro hizmetin teknolojileri bağımsız olarak değiştirilebilir. Tersine, bir monolitte, ekiplerin yalnızca küçük bir teknoloji setini sürdürmesi gerekebilir (örneğin, yalnızca bir çerçeve varsa, yalnızca bir çerçevenin güncellenmesi gerekecektir) ve geniş bir uzmanlığa ihtiyaç duymayabilir (örneğin, beş programlama dilinde çalışma bilgisine sahip olmak). Ayrıca, kod aşağı yukarı aynı kod tabanının bir parçası olduğunda, kod genelinde aynı standartları korumak daha kolay olabilir.

"Başarısızlık için Tasarım"

Hizmetler farklı makinelerde farklı süreçlerde çalıştığında ve farklı ekipler tarafından farklı teknolojiler ve standartlar kullanılarak oluşturulduğunda, bu durum geliştiricilerin düşünme şeklini değiştirebilir. Tüm gemiyi su üstünde tutmak yerine, hizmete özel izleme, günlük kaydı ve bir hizmet başarısız olduğunda ne yapılacağına ilişkin tasarım kararlarına (kullanıcıya ne söyleneceği de dahil olmak üzere) odaklanılabilir. Buna karşılık, bir monolitte, bir dağıtım başarısız olursa (çünkü başarısızlık monolitin hiçbir parçasının çalışmadığı anlamına gelebilir) nasıl hızlı bir şekilde geri dönüleceği üzerine daha fazla düşünülebilir. Monolitler de başarısızlık için tasarlanabilir, ancak bu mikro hizmetlerde olduğu kadar doğal bir eğilim değildir.

Mikro Hizmetlerle Karşılaştırıldığında Monolit

Bu bölümde monolit ve mikro hizmet mimarileri arasındaki farklar özetlenmekte ve genişletilmektedir (Fowler, 2015; Lewis & Fowler, 2014).

İletişim Bir Monolit İçinde ve Mikro Hizmetler Arasında Nasıl Gerçekleşir?

Bir monolitte, iletişim (örneğin, sınıflar ve bileşenler arasında) doğrudan çağrılar ve bir ağ üzerinden de dahil olmak üzere birçok şekilde gerçekleşebilir. Mikro hizmetlerde iletişim tipik olarak HTTP istekleri/cevapları gibi bir ağ üzerinden, "aptal", standartlaştırılmış iletişim veri yolları aracılığıyla gerçekleşir. Mikro hizmetlerin iletişim yolları daha az karmaşık olsa da, bu uç noktaların daha akıllı olması gerektiği anlamına gelir. Ayrıca, bir ağ üzerinden iletişim daha az güvenilir ve daha az güvenli olabilir.

Bir Monolit Mikro Hizmetlere Karşı Nasıl Dağıtılır?

Monolitik yazılımların genellikle tek seferde dağıtılması gerekir. Mikro hizmetler bağımsız olarak dağıtılabilir ve bağlı hizmetler durdurulmadan potansiyel olarak durdurulabilir.

Bir Monolit Mikro Hizmetlere Karşı Nasıl Ölçeklendirilir?

Monolitik yazılımınız, kullanım miktarını destekleyebilmek için daha fazla kaynağa ihtiyaç duyuyorsa, birden fazla makineye kopyalanabilir. Her makine tüm monoliti desteklemek için yeterli alana, belleğe, işlem hızına ve benzerlerine sahip olmalıdır.

Mikro hizmet yazılımınızın daha fazla kaynağa ihtiyacı varsa, daha fazla seçeneğiniz vardır. Örneğin, daha fazla kullanılan hizmetler daha fazla kez çoğaltılabilir.

Bir Monolit Mikro Hizmetlere Karşı Nasıl Test Edilir?

Mikro hizmet yazılımlarında her hizmet bağımsız olarak test edilebilir. Bir monolitte, test etme şekliniz kod içindeki bağımlılıklardan etkilenir ve bu da yazılımın geneline ulaşabilir (ve yavaş testlere neden olabilir).

Bir Monolit Mikro Hizmetlere Karşı Nasıl Yükseltilir?

Her bir mikro hizmet farklı bir dilde yazılabilir (örneğin, biri Python, diğeri Java, bir diğeri C++, vb.) ve farklı bağlamlarda çalışabilir (örneğin, farklı işletim sistemlerine, kütüphanelere, kütüphane sürümlerine vb. sahip makineler). Teorik olarak bu, bağımsız olarak yükseltilebilecekleri anlamına gelir.

Bir monolit ile yükseltme daha fazla özen gerektirebilir. Her bileşen yeni bağlamla uyumlu olmalıdır (ancak bu bazen mikro hizmetler için de geçerlidir).

Veritabanı Monolit ve Mikro Hizmetlerde Nasıl Kullanılır?

Monolitik yazılımlar tek bir veritabanına sahip olabilir, bu da potansiyel olarak çok büyük bir veritabanı olabilir. Bu durum, yazılımın birden fazla parçasının veritabanına paralel olarak erişmesi gerektiğinde bir darboğaz yaratabilir ve diğer dezavantajların yanı sıra veritabanı yedeklemelerinin/geri yüklemelerinin yavaşlamasına neden olabilir. Ancak yalnızca bir veritabanınız varsa, bu yalnızca veritabanı erişim hesaplarını yönetmek için tek bir yer ve bakım/yedekleme/geri yükleme/vb. için tek bir veritabanı anlamına gelir. Buna karşılık, her mikro hizmetin tipik olarak kendi veri depolama alanı vardır.

Özet

Monolit ve mikro hizmet mimarilerinin farklı avantajları ve dezavantajları vardır. Bir mikro hizmet mimarisinde, her hizmet kendi uygulamasıdır ve bağımsız olarak yönetilebilir. Modüller arasındaki iletişim mekanizmaları standartlaştırılabilir. Ancak bir monolitte, kod tabanı bir kerede dağıtılabilir ve bileşenler doğrudan iletişim kurabilir; bu da daha güvenilir, daha ucuz olabilir ve bir ağ üzerinden birden fazla uygulama arasında iletişim kurmaktan daha iyi tutarlılık sağlayabilir.

Örnek Olay İncelemesi: Mikro Hizmet Mimarisi

Oregon Eyalet Üniversitesi (OSU) Uygulamalı Sistemler ve Yazılım Merkezi (CASS), Oregon Ulaştırma Bakanlığı (ODOT) gibi müşterilerle yaptığı çalışmalarla öğrencilere gerçek dünyada yazılım geliştirme deneyimi kazandıran kâr amacı gütmeyen bir kuruluştur.

CASS ve ODOT, ODOT'un eyalet çapındaki bilgisayar destekli sevkiyat yazılımı olan Ulaştırma Operasyon Merkezi Sistemini (TOCS) bir monolitten mikro hizmetlere dönüştürmeye karar verdi. TOCS, sevk görevlilerinin yol acil durum bilgilerini müdahale ekipleri ve halkla paylaşmasına yardımcı olur. TOCS'un CASS ile başlayan kısmı modası geçmiş ana ekranıydı.

Kullanıcı perspektifinden bakıldığında, TOCS ana ekranının temel sorunu esnek olmamasıydı. Oregon'un farklı bölgelerindeki sevkiyat merkezlerinin farklı ihtiyaçları vardı (örneğin, bazı merkezler daha fazla buzlu yolla ilgilenirken, diğerleri daha fazla çamurluk kazasıyla uğraşıyordu) ancak kolayca yapılandırılamayan aynı ana ekranı kullanmak zorundaydılar.

Geliştirici perspektifinden bakıldığında, monolitin TOCS kullanıcılarının ihtiyaçlarına yanıt vermeyi zorlaştıran çok sayıda teknolojik dezavantajı vardı:

  • Özellikle yazılım üzerinde birçok farklı geliştirici çalıştığı için yazılım bileşenlerini birbirinden ayrı tutmak zordu. Teknik borç biriktiriyorlardı, bu da geliştiricilerin yeni TOCS özelliklerini uygulamak yerine bu borcu temizlemeye odaklanmaları gerekebileceği anlamına geliyordu.
  • CASS, TOCS'u yılda sadece birkaç kez devreye sokabiliyordu çünkü yazılımın bütünüyle test edilmesi ve devreye sokulması gerekiyordu (uzun bir süreç) ve özellikle yılın daha fazla hava ve yol tehlikesi olan zamanlarında yazılımın kararlı kalması çok önemliydi. Bu, sevkiyat merkezlerinin yeni özellikler (örneğin, kişiselleştirilmiş ana ekranlar) için uzun süre beklemek zorunda kalması anlamına geliyordu.
  • Tüm sevkiyat merkezlerindeki TOCS yazılımı aynı veri tabanıyla işlem yaptığı ve performans sorunlarına neden olduğu için veri tabanı üzerinde çok fazla baskı vardı.
  • Teknoloji seçenekleri sınırlıydı çünkü yazılımın her parçasının .NET Framework ile uyumlu olması gerekiyordu. Daha da kötüsü, Microsoft 4.8 sürümünden sonra .NET Framework güncellemelerini yayınlamayı bıraktığı için teknoloji yığınları kullanımdan kalkıyordu. CASS tüm bu sorunlara çözüm olarak mikro hizmet mimarisini seçti.

Şekil 5.1, monolit ile entegre olan TOCS ana sayfasının yeni mimarisini göstermektedir. WinGui Ağ Geçidi uygulaması, Yeni Ana Ekran Kullanıcı Arayüzü tarafından kullanılabilmesi için hizmetlerden gelen verilerin hazırlanmasından sorumludur. Geliştiricilere modern özelliklere erişim sağlayan .NET 6 yığınını kullanır. Message Broker (Apache ActiveMQ) uygulaması hizmetlerle ve Ağ Geçidi ile konuşur. Mesaj Aracısı standart bir protokol olan AMQP kullandığından, gelecekte Mesaj Aracısı teknolojisini değiştirmek mümkün olacaktır. Her hizmet aynı zamanda ayrı bir uygulamadır ve kendi veritabanına sahiptir. CASS, özel bir veritabanının bir avantajının Profil Hizmeti için JSON kullanabilmeleri olduğunu ve bunun monolit içinde kullanılan ilişkisel veritabanından daha uygun olduğunu keşfetti.

Şekil 5.1 ODOT'un TOCS Ana Ekranının Mikro Hizmet Mimarisi

Bu proje hakkında daha fazla bilgi için, projeyi ayrıntılı olarak anlatan bir video için Fern'e (2022) bakınız.




Yorumlar

Bu blogdaki popüler yayınlar

Gelişim ve Kalıtım Eleştirel Düşünme Soruları

Periodonsiyum Klinik Uygulamalar

Dentin Oluşumu