Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Petunjuk / Saran
Konten ini adalah kutipan dari eBook, Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Kontainer, tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara offline.
Dalam aplikasi monolitik yang berjalan pada satu proses, komponen memanggil satu sama lain menggunakan metode tingkat bahasa atau panggilan fungsi. Ini dapat digabungkan dengan kuat jika Anda membuat objek dengan kode (misalnya, new ClassName()
), atau dapat dipanggil dengan cara yang terpisah jika Anda menggunakan Injeksi Ketergantungan dengan merujuk pada abstraksi daripada pada instans objek konkret. Bagaimanapun, objek berjalan dalam proses yang sama. Tantangan terbesar ketika mengubah dari aplikasi monolitik ke aplikasi berbasis layanan mikro terletak pada perubahan mekanisme komunikasi. Konversi langsung dari panggilan metode dalam proses ke panggilan RPC ke layanan akan menyebabkan komunikasi yang cerewet dan tidak efisien yang tidak akan berkinerja baik di lingkungan terdistribusi. Tantangan merancang sistem terdistribusi dengan benar cukup diketahui bahwa bahkan ada kanon yang dikenal sebagai Fallacies komputasi terdistribusi yang mencantumkan asumsi yang sering dibuat pengembang saat berpindah dari monolitik ke desain terdistribusi.
Tidak ada satu solusi, tetapi beberapa. Salah satu solusinya adalah mengisolasi layanan mikro bisnis sebanyak mungkin. Anda kemudian menggunakan komunikasi asinkron antara layanan mikro internal dan mengganti komunikasi terperinci yang khas dalam komunikasi intra-proses antara objek dengan komunikasi kasar. Anda dapat melakukan ini dengan mengelompokkan panggilan, dan dengan mengembalikan data yang menggabungkan hasil beberapa panggilan internal, ke klien.
Aplikasi berbasis layanan mikro adalah sistem terdistribusi yang berjalan pada beberapa proses atau layanan, biasanya bahkan di beberapa server atau host. Setiap instans layanan biasanya merupakan proses. Oleh karena itu, layanan harus berinteraksi menggunakan protokol komunikasi antarproses seperti HTTP, AMQP, atau protokol biner seperti TCP, tergantung pada sifat setiap layanan.
Komunitas layanan mikro mempromosikan filosofi "titik akhir pintar dan pipa bisu". Slogan ini mendorong desain yang sejauh mungkin terpisah antara mikroservis, dan sekohesif mungkin dalam sebuah mikroservis. Seperti yang dijelaskan sebelumnya, setiap layanan mikro memiliki datanya sendiri dan logika domainnya sendiri. Tetapi layanan mikro yang menyusun aplikasi end-to-end biasanya hanya dikoreografi dengan menggunakan komunikasi REST daripada protokol kompleks seperti WS-* dan komunikasi berbasis peristiwa yang fleksibel alih-alih orkestrator proses bisnis terpusat.
Dua protokol yang umum digunakan adalah permintaan/respons HTTP dengan API sumber daya (saat mengkueri sebagian besar dari semuanya), dan olahpesan asinkron ringan saat mengkomunikasikan pembaruan di beberapa layanan mikro. Ini dijelaskan secara lebih rinci di bagian berikut.
Jenis komunikasi
Klien dan layanan dapat berkomunikasi melalui berbagai jenis komunikasi, masing-masing menargetkan skenario dan tujuan yang berbeda. Awalnya, jenis komunikasi tersebut dapat diklasifikasikan dalam dua sumbu.
Sumbu pertama menentukan apakah protokol sinkron atau asinkron:
Protokol sinkron. HTTP adalah protokol sinkron. Klien mengirim permintaan dan menunggu respons dari layanan. Itu independen dari eksekusi kode klien yang bisa sinkron (utas diblokir) atau asinkron (utas tidak diblokir, dan respons akan mencapai panggilan balik pada akhirnya). Poin penting di sini adalah bahwa protokol (HTTP/HTTPS) sinkron dan kode klien hanya dapat melanjutkan tugasnya ketika menerima respons server HTTP.
Protokol asinkron. Protokol lain seperti AMQP (protokol yang didukung oleh banyak sistem operasi dan lingkungan cloud) menggunakan pesan asinkron. Kode klien atau pengirim pesan biasanya tidak menunggu respons. Ini hanya mengirim pesan seperti saat mengirim pesan ke antrean RabbitMQ atau broker pesan lainnya.
Sumbu kedua menentukan apakah komunikasi memiliki satu penerima atau beberapa penerima:
Penerima tunggal. Setiap permintaan harus diproses oleh satu penerima atau layanan. Contoh komunikasi ini adalah pola Perintah.
Beberapa penerima. Setiap permintaan dapat diproses oleh nol hingga beberapa penerima. Jenis komunikasi ini harus asinkron. Contohnya adalah mekanisme terbitkan/berlangganan yang digunakan dalam pola seperti arsitektur Berbasis peristiwa. Ini didasarkan pada antarmuka event-bus atau broker pesan saat menyebarkan pembaruan data antara beberapa layanan mikro melalui event; biasanya diimplementasikan melalui bus layanan atau perangkat serupa seperti Azure Service Bus menggunakan topik dan langganan.
Aplikasi berbasis layanan mikro akan sering menggunakan kombinasi gaya komunikasi ini. Jenis yang paling umum adalah komunikasi penerima tunggal dengan protokol sinkron seperti HTTP/HTTPS saat memanggil layanan HTTP API Web reguler. Layanan mikro juga biasanya menggunakan protokol olahpesan untuk komunikasi asinkron antar layanan mikro.
Sumbu ini baik untuk diketahui sehingga Anda memiliki kejelasan tentang kemungkinan mekanisme komunikasi, tetapi mereka bukan masalah penting saat membangun layanan mikro. Baik sifat asinkron dari eksekusi utas klien maupun dari protokol yang dipilih bukanlah poin penting saat mengintegrasikan layanan mikro. Yang penting adalah dapat mengintegrasikan layanan mikro Anda secara asinkron sambil menjaga kemandirian layanan mikro, seperti yang dijelaskan di bagian berikut.
Integrasi layanan mikro asinkron memberlakukan otonomi layanan mikro
Seperti disebutkan, poin penting ketika membangun aplikasi berbasis layanan mikro adalah cara Anda mengintegrasikan layanan mikro Anda. Idealnya, Anda harus mencoba meminimalkan komunikasi antara layanan mikro internal. Semakin sedikit komunikasi antara layanan mikro, semakin baik. Tetapi dalam banyak kasus, Anda harus mengintegrasikan layanan mikro. Ketika Anda perlu melakukan itu, aturan penting di sini adalah bahwa komunikasi antara layanan mikro harus asinkron. Itu tidak berarti bahwa Anda harus menggunakan protokol tertentu (misalnya, olahpesan asinkron versus HTTP sinkron). Ini hanya berarti bahwa komunikasi antara layanan mikro harus dilakukan hanya dengan menyebarkan data secara asinkron, tetapi cobalah untuk tidak bergantung pada layanan mikro internal lainnya sebagai bagian dari operasi permintaan/respons HTTP layanan awal.
Jika memungkinkan, jangan pernah bergantung pada komunikasi sinkron (permintaan/respons) antara beberapa layanan mikro, bahkan untuk kueri. Tujuan dari setiap layanan mikro adalah untuk menjadi otonom dan tersedia untuk konsumen klien, bahkan jika layanan lain yang merupakan bagian dari aplikasi end-to-end tidak berfungsi atau tidak sehat. Jika Menurut Anda, Anda perlu melakukan panggilan dari satu layanan mikro ke layanan mikro lainnya (seperti melakukan permintaan HTTP untuk kueri data) untuk dapat memberikan respons terhadap aplikasi klien, Anda memiliki arsitektur yang tidak akan tangguh ketika beberapa layanan mikro gagal.
Selain itu, memiliki dependensi HTTP antara layanan mikro, seperti saat membuat siklus permintaan/respons yang panjang dengan rantai permintaan HTTP, seperti yang ditunjukkan pada bagian pertama dari Gambar 4-15, tidak hanya membuat layanan mikro Anda tidak otonom tetapi juga performanya terdampak segera setelah salah satu layanan dalam rantai itu tidak berkinerja baik.
Semakin banyak Anda menambahkan dependensi sinkron antara layanan mikro, seperti permintaan kueri, semakin buruk waktu respons keseluruhan untuk aplikasi klien.
Gambar 4-15. Pola negatif dan pola pada komunikasi antar layanan mikro
Seperti yang ditunjukkan pada diagram di atas, dalam komunikasi sinkron, "rantai" permintaan dibuat di antara layanan mikro saat melayani permintaan klien. Ini adalah pola kontra. Dalam layanan mikro komunikasi asinkron menggunakan pesan asinkron atau polling http untuk berkomunikasi dengan layanan mikro lainnya, tetapi permintaan klien segera dilayani.
Jika layanan mikro Anda perlu meningkatkan tindakan tambahan di layanan mikro lain, jika memungkinkan, jangan melakukan tindakan tersebut secara sinkron dan sebagai bagian dari permintaan layanan mikro asli dan operasi balasan. Sebagai gantinya, lakukan secara asinkron (menggunakan olahpesan asinkron atau peristiwa integrasi, antrean, dll.). Sebisa mungkin, jangan memanggil tindakan secara sinkron sebagai bagian dari operasi permintaan dan balasan sinkron asli.
Dan akhirnya (dan di sinilah sebagian besar masalah muncul saat membangun layanan mikro), jika layanan mikro awal Anda membutuhkan data yang awalnya dimiliki oleh layanan mikro lainnya, jangan mengandalkan membuat permintaan sinkron untuk data tersebut. Sebagai gantinya, replikasi atau sebarkan data tersebut (hanya atribut yang Anda butuhkan) ke dalam database layanan awal dengan menggunakan konsistensi akhir (biasanya dengan menggunakan peristiwa integrasi, seperti yang dijelaskan di bagian mendatang).
Seperti disebutkan sebelumnya dalam bagian Mengidentifikasi batas model domain untuk setiap layanan mikro , menduplikasi beberapa data di beberapa layanan mikro bukanlah desain yang salah—sebaliknya, saat melakukannya Anda dapat menerjemahkan data ke dalam bahasa atau istilah tertentu dari domain tambahan tersebut atau Konteks Terikat. Misalnya, dalam aplikasi eShopOnContainers Anda memiliki layanan mikro bernama identity-api
yang bertanggung jawab atas sebagian besar data pengguna dengan entitas bernama User
. Namun, ketika Anda perlu menyimpan data tentang pengguna dalam Ordering
layanan mikro, Anda menyimpannya sebagai entitas berbeda bernama Buyer
. Entitas Buyer
berbagi identitas yang sama dengan entitas asli User
, tetapi mungkin hanya memiliki beberapa atribut yang diperlukan oleh Ordering
domain, dan bukan seluruh profil pengguna.
Anda dapat menggunakan protokol apa pun untuk berkomunikasi dan menyebarluaskan data secara asinkron di seluruh layanan mikro untuk memiliki konsistensi akhir. Seperti disebutkan, Anda dapat menggunakan event integrasi dengan bus event atau broker pesan, atau bahkan gunakan HTTP dengan melakukan polling pada layanan lain sebagai gantinya. Tidak masalah. Aturan pentingnya adalah tidak membuat dependensi sinkron antara layanan mikro Anda.
Bagian berikut menjelaskan beberapa gaya komunikasi yang dapat Anda pertimbangkan untuk digunakan dalam aplikasi berbasis layanan mikro.
Gaya komunikasi
Ada banyak protokol dan pilihan yang dapat Anda gunakan untuk komunikasi, tergantung pada jenis komunikasi yang ingin Anda gunakan. Jika Anda menggunakan mekanisme komunikasi berbasis permintaan/respons yang sinkron, protokol seperti pendekatan HTTP dan REST adalah yang paling umum, terutama jika Anda menerbitkan layanan Anda di luar host Docker atau kluster layanan mikro. Jika Anda berkomunikasi antara layanan secara internal (dalam host Docker atau kluster layanan mikro), Anda mungkin juga ingin menggunakan mekanisme komunikasi format biner (seperti WCF menggunakan TCP dan format biner). Atau, Anda dapat menggunakan mekanisme komunikasi berbasis pesan asinkron seperti AMQP.
Ada juga beberapa format pesan seperti JSON atau XML, atau bahkan format biner, yang bisa lebih efisien. Jika format biner yang Anda pilih bukan standar, mungkin bukan ide yang baik untuk menerbitkan layanan Anda secara publik menggunakan format tersebut. Anda dapat menggunakan format non-standar untuk komunikasi internal antara layanan mikro Anda. Anda dapat melakukan ini saat berkomunikasi antara layanan mikro dalam host Docker atau kluster layanan mikro Anda (misalnya, orkestrator Docker), atau untuk aplikasi klien eksklusif yang berbicara dengan layanan mikro.
Komunikasi permintaan/respons dengan HTTP dan REST
Ketika klien menggunakan komunikasi permintaan/respons, klien mengirimkan permintaan ke layanan, maka layanan memproses permintaan dan mengirim kembali respons. Komunikasi permintaan/respons sangat cocok untuk mengkueri data untuk UI real time (antarmuka pengguna langsung) dari aplikasi klien. Oleh karena itu, dalam arsitektur layanan mikro, Anda mungkin akan menggunakan mekanisme komunikasi ini untuk sebagian besar kueri, seperti yang ditunjukkan pada Gambar 4-16.
Gambar 4-16. Menggunakan komunikasi permintaan/respons HTTP (sinkron atau asinkron)
Ketika klien menggunakan komunikasi permintaan/respons, ia mengasumsikan bahwa respons akan tiba dalam waktu singkat, biasanya kurang dari satu detik, atau paling banyak beberapa detik. Untuk respons tertunda, Anda perlu menerapkan komunikasi asinkron berdasarkan pola olahpesan dan teknologi olahpesan, yang merupakan pendekatan berbeda yang kami jelaskan di bagian berikutnya.
Gaya arsitektur populer untuk komunikasi permintaan/respons adalah REST. Pendekatan ini didasarkan pada, dan digabungkan erat dengan, protokol HTTP , merangkul kata kerja HTTP seperti GET, POST, dan PUT. REST adalah pendekatan komunikasi arsitektur yang paling umum digunakan saat membuat layanan. Anda dapat menerapkan layanan REST saat mengembangkan layanan ASP.NET Core Web API.
Ada nilai tambahan saat menggunakan layanan HTTP REST sebagai bahasa definisi antarmuka Anda. Misalnya, jika Anda menggunakan metadata Swagger untuk menjelaskan API layanan, Anda dapat menggunakan alat yang menghasilkan stub klien yang dapat langsung menemukan dan menggunakan layanan Anda.
Sumber daya tambahan
Martin Fowler. Model Kematangan Richardson Deskripsi model REST.
https://martinfowler.com/articles/richardsonMaturityModel.htmlSwagger Situs resmi.
https://swagger.io/
Pemberitahuan push dan komunikasi real-time yang berbasis HTTP
Kemungkinan lain (biasanya untuk tujuan yang berbeda dari REST) adalah komunikasi real time dan satu-ke-banyak dengan kerangka kerja tingkat yang lebih tinggi seperti ASP.NET SignalR dan protokol seperti WebSocket.
Seperti yang ditunjukkan Gambar 4-17, komunikasi HTTP real-time berarti Anda dapat memiliki kode server yang mendorong konten ke klien yang terhubung saat data tersedia, daripada meminta server menunggu klien meminta data baru.
Gambar 4-17. Komunikasi pesan waktu nyata asinkron satu-ke-banyak
SignalR adalah cara yang baik untuk mencapai komunikasi real-time dengan mengirimkan konten ke klien dari server back-end. Karena komunikasi secara real time, aplikasi klien menunjukkan perubahan hampir seketika. Ini biasanya ditangani oleh protokol seperti WebSockets, menggunakan banyak koneksi WebSockets (satu per klien). Contoh umumnya adalah ketika layanan mengkomunikasikan perubahan skor permainan olahraga ke banyak aplikasi web klien secara bersamaan.