Arsitektur aplikasi web umum

Tip

Konten ini adalah kutipan dari e-book berjudul Architect Modern Web Applications with ASP.NET Core and Azure, yang tersedia di .NET Docs atau sebagai PDF yang dapat diunduh gratis dan dibaca secara offline.

Architect Modern Web Applications with ASP.NET Core and Azure eBook cover thumbnail.

"Jika menurut Anda arsitektur yang bagus itu mahal, cobalah dengan arsitektur yang buruk." - Brian Foote dan Joseph Yoder

Sebagian besar aplikasi .NET tradisional digunakan sebagai unit tunggal yang sesuai dengan aplikasi web yang dapat dijalankan atau aplikasi web tunggal yang berjalan dalam satu domain aplikasi IIS. Pendekatan ini adalah model penyebaran paling sederhana dan melayani banyak aplikasi publik internal dan yang lebih kecil dengan sangat baik. Tetapi, bahkan dengan unit penyebaran tunggal ini, sebagian besar aplikasi bisnis non-sepele mendapat manfaat dari beberapa pemisahan logis menjadi beberapa lapisan.

Apa itu aplikasi monolitik?

Aplikasi monolitik adalah aplikasi yang sepenuhnya mandiri, dalam hal perilakunya. Aplikasi ini berinteraksi dengan layanan lain atau penyimpanan data selama menjalankan operasinya, tetapi inti dari perilakunya berjalan dalam prosesnya sendiri dan seluruh aplikasi biasanya disebarkan sebagai satu unit. Jika aplikasi semacam itu perlu diskalakan secara horizontal, biasanya seluruh aplikasi diduplikasi di beberapa server atau mesin virtual.

Aplikasi all-in-one

Jumlah proyek terkecil yang memungkinkan untuk arsitektur aplikasi adalah satu. Dalam arsitektur ini, seluruh logika aplikasi termuat dalam satu proyek, dikompilasi menjadi satu rakitan, dan disebarkan sebagai satu unit.

Proyek Inti ASP.NET baru, baik yang dibuat di Visual Studio atau dari baris perintah, dimulai sebagai monolit "all-in-one" sederhana. Ini berisi semua perilaku aplikasi, termasuk presentasi, bisnis, dan logika akses data. Gambar 5-1 menunjukkan struktur file aplikasi proyek tunggal.

A single project ASP.NET Core app

Gambar 5-1. Satu proyek aplikasi Inti ASP.NET.

Dalam satu skenario proyek, pemisahan kekhawatiran dicapai melalui penggunaan folder. Templat default menyertakan folder terpisah untuk tanggung jawab pola MVC Model, Tampilan, dan Pengontrol, serta folder tambahan untuk Data dan Layanan. Dalam pengaturan ini, perincian presentasi harus dibatasi sebanyak mungkin ke folder Tampilan, dan perincian implementasi akses data harus dibatasi untuk kelas yang disimpan di folder Data. Logika bisnis harus berada di layanan dan kelas dalam folder Model.

Meskipun sederhana, solusi monolitik proyek tunggal memiliki beberapa kelemahan. Seiring bertambahnya ukuran dan kompleksitas proyek, jumlah file dan folder juga akan terus bertambah. Masalah antarmuka pengguna (UI) (model, tampilan, pengontrol) berada di beberapa folder, yang tidak dikelompokkan menurut abjad. Masalah ini bertambah buruk ketika konstruksi tingkat antarmuka pengguna tambahan, seperti Filter atau ModelBinders, ditambahkan di folder mereka sendiri. Logika bisnis tersebar di antara folder Model dan Layanan, dan tidak ada indikasi yang jelas tentang kelas mana di mana folder harus bergantung pada yang lain. Kurangnya organisasi di tingkat proyek ini sering menyebabkan kode spageti.

Untuk mengatasi masalah ini, aplikasi sering berkembang menjadi solusi multiproyek, di mana setiap proyek dianggap berada di lapisan aplikasi tertentu.

Apa itu lapisan?

Saat aplikasi berkembang secara kompleks, salah satu cara untuk mengelola kompleksitas itu adalah dengan memecah aplikasi sesuai dengan tanggung jawab atau masalahnya. Pendekatan ini mengikuti prinsip pemisahan kekhawatiran dan dapat membantu menjaga basis kode yang berkembang terorganisir sehingga pengembang dapat dengan mudah menemukan di mana fungsionalitas tertentu diterapkan. Arsitektur berlapis menawarkan sejumlah manfaat lebih dari sekadar organisasi kode.

Dengan mengatur kode ke dalam lapisan, fungsionalitas tingkat rendah yang umum dapat digunakan kembali di seluruh aplikasi. Penggunaan kembali ini bermanfaat karena berarti lebih sedikit kode yang perlu ditulis dan karena dapat memungkinkan aplikasi untuk menstandardisasi pada satu implementasi, mengikuti prinsip don't repeat yourself (DRY).

Dengan arsitektur berlapis, aplikasi dapat memberlakukan pembatasan lapisan mana saja yang dapat berkomunikasi dengan lapisan lain. Arsitektur ini membantu mencapai enkapsulasi. Saat lapisan diubah atau diganti, ini hanya memengaruhi lapisan yang bekerja dengannya. Dengan membatasi lapisan mana yang bergantung pada lapisan lain, dampak perubahan dapat dikurangi sehingga satu perubahan tidak berdampak pada seluruh aplikasi.

Lapisan (dan enkapsulasi) memudahkan untuk mengganti fungsionalitas dalam aplikasi. Misalnya, aplikasi mungkin awalnya menggunakan database SQL Servernya sendiri untuk persistensi, tetapi kemudian dapat memilih untuk menggunakan strategi persistensi berbasis cloud, atau strategi di belakang API web. Jika aplikasi telah mengenkapsulasi penerapan persistensinya dengan benar dalam lapisan logis, lapisan khusus SQL Server itu dapat diganti dengan yang baru yang menerapkan antarmuka publik yang sama.

Selain potensi pertukaran penerapan sebagai tanggapan terhadap perubahan persyaratan di masa mendatang, lapisan aplikasi juga dapat mempermudah pertukaran penerapan untuk tujuan pengujian. Alih-alih harus menulis pengujian yang beroperasi terhadap lapisan data nyata atau lapisan antarmuka pengguna aplikasi, lapisan ini dapat diganti pada waktu pengujian dengan penerapan palsu yang memberikan respons yang diketahui terhadap permintaan. Pendekatan ini biasanya membuat pengujian lebih mudah untuk ditulis dan lebih cepat dijalankan jika dibandingkan dengan menjalankan pengujian terhadap infrastruktur aplikasi yang sebenarnya.

Pelapisan logis adalah teknik umum untuk meningkatkan organisasi kode dalam aplikasi perangkat lunak perusahaan, dan ada beberapa cara di mana kode dapat diatur ke dalam lapisan.

Catatan

Lapisan mewakili pemisahan logis dalam aplikasi. Jika logika aplikasi didistribusikan secara fisik ke server atau proses terpisah, target penyebaran fisik terpisah ini disebut sebagai tingkatan. Ini memungkinkan, dan cukup umum, untuk memiliki aplikasi N-Layer yang disebarkan ke satu tingkat.

Aplikasi arsitektur "Tingkat N" tradisional

Organisasi logika aplikasi paling umum ke dalam lapisan ditunjukkan pada Gambar 5-2.

Typical application layers

Gambar 5-2. Lapisan aplikasi umum.

Lapisan-lapisan ini sering disingkat sebagai UI, BLL (Lapisan Logika Bisnis), dan DAL (Lapisan Akses Data). Dengan menggunakan arsitektur ini, pengguna membuat permintaan melalui lapisan antarmuka pengguna, yang hanya berinteraksi dengan BLL. BLL, pada gilirannya dapat memanggil DAL untuk permintaan akses data. Lapisan antarmuka pengguna tidak boleh membuat permintaan apa pun ke DAL secara langsung, juga tidak boleh berinteraksi dengan persistensi secara langsung melalui cara lain. Demikian juga BLL seharusnya hanya berinteraksi dengan ketekunan melalui DAL. Dengan cara ini, setiap lapisan memiliki tanggung jawab sendiri yang sudah dikenal.

Salah satu kekurangan dari pendekatan lapisan tradisional ini adalah dependensi waktu kompilasi berjalan dari atas ke bawah. Artinya, lapisan antarmuka pengguna tergantung pada BLL, yang tergantung pada DAL. Ini berarti bahwa BLL, yang biasanya memegang logika terpenting dalam aplikasi, tergantung pada perincian implementasi akses data (dan seringkali pada keberadaan database). Menguji logika bisnis dalam arsitektur seperti itu seringkali sulit, membutuhkan database pengujian. Prinsip inversi ketergantungan dapat digunakan untuk mengatasi masalah ini, seperti yang akan Anda lihat di bagian berikutnya.

Gambar 5-3 menunjukkan contoh solusi, memecah aplikasi menjadi tiga proyek berdasarkan tanggung jawab (atau lapisan).

A simple monolithic application with three projects

Gambar 5-3. Aplikasi monolitik sederhana dengan tiga proyek.

Meskipun aplikasi ini menggunakan beberapa proyek untuk tujuan organisasi, aplikasi masih digunakan sebagai satu unit dan kliennya akan berinteraksi dengannya sebagai aplikasi web tunggal. Hal ini memungkinkan untuk proses penyebaran yang sangat sederhana. Gambar 5-4 menunjukkan bagaimana aplikasi tersebut dapat dihosting menggunakan Azure.

Simple deployment of Azure Web App

Gambar 5-4. Penyebaran sederhana Azure Web App

Seiring berkembangnya kebutuhan aplikasi, mungkin perlu solusi penerapan yang lebih kompleks dan kuat. Gambar 5-5 menunjukkan contoh rencana penerapan yang lebih kompleks yang mendukung kemampuan tambahan.

Deploying a web app to an Azure App Service

Gambar 5-5. Menyebarkan aplikasi web Java ke Azure App Service

Secara internal, organisasi proyek ini menjadi beberapa proyek berdasarkan tanggung jawab meningkatkan pemeliharaan aplikasi.

Unit ini dapat ditingkatkan atau diturunkan untuk memanfaatkan skalabilitas berdasarkan permintaan berbasis cloud. Meningkatkan skala berarti menambahkan CPU, memori, ruang disk, atau sumber daya tambahan lainnya ke server yang menghosting aplikasi Anda. Memperlua skala berarti menambahkan contoh tambahan dari server tersebut, apakah ini server fisik, mesin virtual, atau kontainer. Saat aplikasi Anda dihosting di beberapa instans, penyeimbang beban digunakan untuk menetapkan permintaan ke masing-masing instans aplikasi.

Pendekatan paling sederhana untuk menskalakan aplikasi web di Azure adalah mengonfigurasi penskalaan secara manual di Paket App Service aplikasi. Gambar 5-6 menunjukkan layar dasbor Azure yang sesuai untuk mengonfigurasi berapa banyak instans yang melayani aplikasi.

App Service Plan scaling in Azure

Gambar 5-6. Paket App Service menskalakan di Azure.

Arsitektur bersih

Aplikasi yang mengikuti Prinsip Inversi Ketergantungan serta prinsip Desain Berbasis Domain (DDD) cenderung sampai pada arsitektur yang serupa. Arsitektur ini telah memiliki banyak nama selama bertahun-tahun. Salah satu nama pertama adalah Arsitektur Heksagonal, diikuti oleh Ports-and-Adapter. Baru-baru ini, itu telah dikutip sebagai Arsitektur Bawang atau Arsitektur Bersih. Nama terakhir, Arsitektur Bersih, digunakan sebagai nama untuk arsitektur ini dalam e-book ini.

Aplikasi referensi eShopOnWeb menggunakan pendekatan Arsitektur Bersih dalam mengatur kodenya ke dalam proyek. Anda dapat menemukan templat solusi yang dapat Anda gunakan sebagai titik awal untuk solusi ASP.NET Core Anda sendiri di repositori ardalis/cleanarchitecture GitHub atau dengan memasang templat dari NuGet.

Arsitektur bersih meletakkan logika bisnis dan model aplikasi di pusat aplikasi. Alih-alih memiliki logika bisnis yang bergantung pada akses data atau masalah infrastruktur lainnya, ketergantungan ini dibalik: perincian infrastruktur dan implementasi bergantung pada Inti Aplikasi. Fungsionalitas didapatkan dengan menentukan abstraksi, atau antarmuka, di Inti Aplikasi, yang kemudian diterapkan oleh jenis yang ditentukan di lapisan Infrastruktur. Cara umum memvisualisasikan arsitektur ini adalah dengan menggunakan serangkaian lingkaran konsentris, mirip dengan bawang. Gambar 5-7 menunjukkan contoh gaya representasi arsitektur ini.

Clean Architecture; onion view

Gambar 5-7. Arsitektur Bersih; tampilan bawang

Dalam diagram ini, ketergantungan mengalir menuju lingkaran terdalam. Inti Aplikasi mengambil namanya dari posisinya di inti diagram ini. Anda dapat melihat pada diagram bahwa Inti Aplikasi tidak tergantung pada lapisan aplikasi lain. Entitas dan antarmuka aplikasi berada di pusat. Tepat di luarnya, tetapi masih di dalam Inti Aplikasi, adalah layanan domain, yang biasanya menerapkan antarmuka yang ditentukan dalam lingkaran dalam. Di luar Inti Aplikasi, baik antarmuka pengguna dan lapisan Infrastruktur tergantung pada Inti Aplikasi, tetapi tidak bergantung satu sama lain (seharusnya).

Gambar 5-8 menunjukkan diagram lapisan horizontal yang lebih tradisional yang mencerminkan ketergantungan antara UI dan lapisan lainnya dengan lebih baik.

Clean Architecture; horizontal layer view

Gambar 5-8. Arsitektur Bersih; tampilan lapisan horizontal

Perhatikan bahwa panah padat mewakili dependensi waktu kompilasi, sedangkan panah putus-putus mewakili ketergantungan runtime-saja. Dengan arsitektur bersih, lapisan antarmuka pengguna bekerja dengan antarmuka yang ditentukan dalam Inti Aplikasi pada waktu kompilasi, dan idealnya tidak mengetahui tentang jenis implementasi yang ditentukan di lapisan Infrastruktur. Pada durasi, jenis implementasi ini diperlukan agar aplikasi dapat dijalankan, sehingga harus ada dan terhubung ke antarmuka Inti Aplikasi melalui injeksi dependensi.

Gambar 5-9 menunjukkan tampilan yang lebih rinci dari arsitektur aplikasi Inti ASP.NET saat dibangun mengikuti rekomendasi ini.

ASP.NET Core architecture diagram following Clean Architecture

Gambar 5-9. Arsitektur Inti ASP.NET mengikuti Arsitektur Bersih.

Karena Inti Aplikasi tidak tergantung pada Infrastruktur, sangat mudah untuk menulis pengujian unit otomatis untuk lapisan ini. Gambar 5-10 dan 5-11 menunjukkan bagaimana pengujian cocok dengan arsitektur ini.

UnitTestCore

Gambar 5-10. Unit pengujian Inti Aplikasi dalam isolasi.

IntegrationTests

Gambar 5-11. Pengujian integrasi implementasi Infrastruktur dengan dependensi eksternal.

Karena lapisan antarmuka pengguna tidak memiliki ketergantungan langsung pada jenis yang ditentukan dalam proyek Infrastruktur, sangat mudah untuk menukar implementasi, baik untuk memfasilitasi pengujian atau sebagai respons terhadap perubahan persyaratan aplikasi. Penggunaan dan dukungan bawaan inti ASP.NET untuk injeksi ketergantungan menjadikan arsitektur ini cara yang paling tepat untuk menyusun aplikasi monolitik non-trivial.

Untuk aplikasi monolitik, proyek Inti Aplikasi, Infrastruktur, dan antarmuka pengguna semuanya dijalankan sebagai satu aplikasi. Arsitektur aplikasi runtime mungkin terlihat seperti Gambar 5-12.

ASP.NET Core Architecture 2

Gambar 5-12. Contoh arsitektur runtime aplikasi Inti ASP.NET.

Mengatur kode dalam Arsitektur Bersih

Dalam solusi Arsitektur Bersih, setiap proyek memiliki tanggung jawab yang jelas. Dengan demikian, jenis tertentu termasuk dalam setiap proyek dan Anda akan sering menemukan folder yang sesuai dengan jenis ini di proyek yang sesuai.

Inti Aplikasi

Inti Apliaksi memegang model bisnis, yang mencakup entitas, layanan, dan antarmuka. Antarmuka ini mencakup abstraksi untuk operasi yang akan dilakukan menggunakan Infrastruktur, seperti akses data, akses sistem file, panggilan jaringan, dll. Terkadang layanan atau antarmuka yang ditentukan pada lapisan ini perlu bekerja dengan jenis non-entitas yang tidak memiliki ketergantungan pada antarmuka pengguna atau Infrastruktur. Ini dapat didefinisikan sebagai Objek Transfer Data (DTO) sederhana.

Jenis Inti Aplikasi
  • Entitas (kelas model bisnis yang dipertahankan)
  • Agregat (grup entitas)
  • Antarmuka
  • Layanan Domain
  • Spesifikasi
  • Pengecualian Kustom dan Klausul Pelindung
  • Peristiwa dan Penanganan Domain

Infrastruktur

Proyek Infrastruktur biasanya mencakup implementasi akses data. Dalam aplikasi web Inti ASP.NET yang khas, penerapan ini termasuk Entity Framework (EF) DbContext, objek Migration Inti EF yang telah ditentukan, dan kelas penerapan akses data. Cara paling umum untuk mengabstraksi kode implementasi akses data adalah melalui penggunaan pola desain Repositori.

Selain implementasi akses data, proyek Infrastruktur harus berisi implementasi layanan yang harus berinteraksi dengan masalah infrastruktur. Layanan ini harus menerapkan antarmuka yang ditentukan dalam Inti Aplikasi, sehingga Infrastruktur harus memiliki referensi ke proyek Inti Aplikasi.

Jenis infrastruktur
  • Jenis Inti EF (DbContext, Migration)
  • Jenis implementasi akses data (Repositori)
  • Layanan khusus infrastruktur (misalnya, FileLogger atau SmtpNotifier)

Lapisan antarmuka pengguna

Lapisan antarmuka pengguna dalam aplikasi MVC Inti ASP.NET adalah titik masuk untuk aplikasi. Proyek ini harus mereferensikan proyek Inti Aplikasi, dan jenisnya harus berinteraksi dengan infrastruktur secara ketat melalui antarmuka yang ditentukan dalam Inti Aplikasi. Tidak ada instansiasi langsung atau panggilan statis ke jenis lapisan Infrastruktur yang harus diizinkan di lapisan antarmuka pengguna.

Jenis Lapisan Antarmuka Pengguna
  • Pengontrol
  • Filter Kustom
  • Middleware Kustom
  • Tampilan
  • ViewModels
  • Startup

File Startup kelas atau Program.cs bertanggung jawab untuk mengonfigurasi aplikasi, dan untuk menghubungkan jenis implementasi ke antarmuka. Tempat di mana logika ini dilakukan dikenal sebagai akar komposisi aplikasi, dan inilah yang memungkinkan injeksi dependensi berfungsi dengan baik pada durasi.

Catatan

Untuk menghubungkan injeksi ketergantungan selama startup aplikasi, proyek lapisan antarmuka pengguna mungkin perlu merujuk proyek Infrastruktur. Dependensi ini dapat dihilangkan, paling mudah dengan menggunakan kontainer DI khusus yang memiliki dukungan bawaan untuk memuat jenis dari rakitan. Untuk tujuan sampel ini, pendekatan paling sederhana adalah mengizinkan proyek antarmuka pengguna untuk mereferensikan proyek Infrastruktur (tetapi pengembang harus membatasi referensi aktual untuk jenis dalam proyek Infrastruktur ke akar komposisi aplikasi).

Aplikasi dan kontainer monolitik

Anda dapat membangun Aplikasi atau Layanan Web berbasis penyebaran tunggal dan monolitik dan menyebarkannya sebagai kontainer. Dalam aplikasi, mungkin tidak monolitik tetapi diatur ke dalam beberapa perpustakaan, komponen, atau lapisan. Secara eksternal, ini adalah kontainer tunggal dengan proses tunggal, aplikasi web tunggal, atau layanan tunggal.

Untuk mengelola model ini, Anda menerapkan satu kontainer untuk mewakili aplikasi. Untuk menskalakan, cukup tambahkan salinan tambahan dengan penyeimbang beban di depan. Kesederhanaan berasal dari mengelola satu penyebaran dalam satu kontainer atau mesin virtual.

Figure 5-13

Anda dapat memasukkan beberapa komponen/pustaka atau lapisan internal dalam setiap kontainer, seperti yang diilustrasikan pada Gambar 5-13. Tetapi, mengikuti prinsip wadah "sebuah kontainer melakukan satu hal, dan melakukannya dalam satu proses", pola monolitik dapat menjadi konflik.

Kelemahan dari pendekatan ini muncul jika/ketika aplikasi berkembang, dan perlu diskalakan. Jika seluruh aplikasi diskalakan, itu tidak terlalu menjadi masalah. Tetapi, dalam banyak kasus, beberapa bagian aplikasi merupakan titik tersedak yang memerlukan penskalaan, sedangkan komponen lain lebih jarang digunakan.

Dengan menggunakan contoh e-Niaga biasa, yang mungkin Anda perlukan adalah menskalakan komponen informasi produk. Lebih banyak pelanggan menelusuri produk dibandingkan membelinya. Lebih banyak pelanggan menggunakan keranjang mereka dibandingkan menggunakan saluran pembayaran. Lebih sedikit pelanggan menambahkan komentar atau melihat riwayat pembelian mereka. Dan Anda mungkin hanya memiliki beberapa karyawan, di satu wilayah, yang harus mengelola konten dan kampanye pemasaran. Dengan menskalakan desain monolitik, semua kode disebarkan beberapa kali.

Selain masalah "skalakan-semuanya", perubahan pada satu komponen memerlukan pengujian ulang lengkap dari seluruh aplikasi, dan pemindahan lengkap semua instans.

Pendekatan monolitik adalah umum, dan banyak organisasi berkembang dengan pendekatan arsitektur ini. Banyak yang memiliki hasil yang cukup baik, sementara yang lain mencapai batas. Banyak yang mendesain aplikasi mereka dalam model ini, karena alat dan infrastruktur terlalu sulit untuk membangun arsitektur berorientasi layanan (SOA), dan mereka tidak melihat kebutuhan hingga aplikasi berkembang. Jika Anda telah mencapai batas pendekatan monolitik, memecah aplikasi untuk memungkinkannya memanfaatkan kontainer dan layanan mikro dengan lebih baik mungkin merupakan langkah logis berikutnya.

Figure 5-14

Menyebarkan aplikasi monolitik di Microsoft Azure dapat dicapai menggunakan mesin virtual khusus untuk setiap instans. Dengan menggunakan Azure Virtual Machine Scale Sets, Anda dapat dengan mudah menskalakan mesin virtual. Azure App Services dapat menjalankan aplikasi monolitik dan dengan mudah menskalakan instans tanpa harus mengelola mesin virtual. Azure App Services juga dapat menjalankan satu instans kontainer Docker, menyederhanakan penyebaran. Dengan menggunakan Docker, Anda dapat menyebarkan satu VM sebagai host Docker, dan menjalankan beberapa instans. Menggunakan penyeimbang Azure, seperti yang ditunjukkan pada Gambar 5-14, Anda dapat mengelola penskalakan.

Penyebaran ke berbagai host dapat dikelola dengan teknik penyebaran tradisional. Host Docker dapat dikelola dengan perintah seperti eksekusi docker yang dilakukan secara manual, atau melalui otomatisasi seperti alur Pengiriman Berkelanjutan (CD).

Aplikasi monolitik yang disebarkan sebagai kontainer

Terdapat manfaat menggunakan kontainer untuk mengelola penerapan aplikasi monolitik. Menskalakan instans kontainer jauh lebih cepat dan lebih mudah dibandingkan menyebarkan mesin virtual tambahan. Bahkan saat menggunakan set skala komputer virtual untuk menskalakan mesin virtual, mereka membutuhkan waktu untuk membuatnya. Saat disebarkan sebagai instans aplikasi, konfigurasi aplikasi dikelola sebagai bagian dari mesin virtual.

Menyebarkan pembaruan sebagai gambar Docker jauh lebih cepat dan efisien jaringan. Gambar Docker biasanya dimulai dalam hitungan detik, mempercepat peluncuran. Membongkar instans Docker semudah menerbitkan perintah docker stop, biasanya selesai dalam waktu kurang dari satu detik.

Karena container secara inheren tidak dapat diubah berdasarkan desain, Anda tidak perlu mengkhawatirkan mesin virtual yang rusak, sedangkan skrip pembaruan mungkin lupa memperhitungkan beberapa konfigurasi atau file tertentu yang tertinggal di disk.

Anda dapat menggunakan wadah Docker untuk penyebaran monolitik aplikasi web yang lebih sederhana. Pendekatan ini meningkatkan integrasi berkelanjutan dan jalur penyebaran berkelanjutan serta membantu mencapai keberhasilan penyebaran hingga produksi. Tidak ada lagi "Ini berfungsi pada mesin saya, mengapa tidak berfungsi dalam produksi?”

Arsitektur berbasis layanan mikro memiliki banyak manfaat, tetapi manfaat itu harus dibayar dengan kompleksitas yang meningkat. Dalam beberapa kasus, biayanya lebih besar daripada manfaatnya, jadi aplikasi penyebaran monolitik yang berjalan dalam satu kontainer atau hanya dalam beberapa kontainer adalah pilihan yang lebih baik.

Aplikasi monolitik mungkin tidak mudah diuraikan menjadi layanan mikro yang terpisah dengan baik. Layanan mikro harus bekerja secara independen satu sama lain untuk menyediakan aplikasi yang lebih tangguh. Jika Anda tidak dapat memberikan potongan fitur independen dari aplikasi, memisahkan fitur hanya akan menambah kerumitan.

Aplikasi mungkin belum perlu menskalakan fitur secara independen. Banyak aplikasi, ketika mereka perlu menskalakan di luar instans tunggal, dapat melakukannya melalui proses yang relatif sederhana dengan mengkloning seluruh instans tersebut. Pekerjaan tambahan untuk memisahkan aplikasi ke dalam layanan diskrit memberikan manfaat minimal saat menskalakan instans penuh aplikasi sederhana dan hemat biaya.

Di awal pengembangan aplikasi, Anda mungkin tidak memiliki gagasan yang jelas tentang batas-batas fungsional alami. Saat Anda mengembangkan produk minimum yang layak, pemisahan alami mungkin belum muncul. Beberapa kondisi ini mungkin bersifat sementara. Anda mungkin mulai dengan membuat aplikasi monolitik, dan kemudian memisahkan beberapa fitur untuk dikembangkan dan disebarkan sebagai layanan mikro. Kondisi lainnya mungkin penting untuk ruang masalah aplikasi, yang berarti aplikasi mungkin tidak akan dipecah menjadi beberapa layanan mikro.

Memisahkan aplikasi ke dalam banyak proses diskrit juga menimbulkan overhead. Akan lebih rumit untuk memisahkan fitur ke dalam proses yang berbeda. Protokol komunikasi menjadi lebih kompleks. Alih-alih panggilan metode, Anda harus menggunakan komunikasi asinkron antar layanan. Saat Anda pindah ke arsitektur layanan mikro, Anda perlu menambahkan banyak blok penyusun yang diimplementasikan dalam versi layanan mikro dari aplikasi eShopOnContainers: penanganan bus peristiwa, ketahanan dan percobaan ulang pesan, konsistensi akhirnya, dan banyak lagi.

Aplikasi referensi eShopOnWeb yang jauh lebih sederhana mendukung penggunaan kontainer monolitik satu kontainer. Aplikasi ini mencakup satu aplikasi web yang mencakup tampilan MVC tradisional, API web, dan Halaman Razor. Secara opsional, Anda dapat menjalankan komponen admin aplikasi berbasis Blazor, yang juga memerlukan proyek API terpisah untuk dijalankan.

Aplikasi dapat diluncurkan dari akar solusi menggunakan perintah docker-compose build dan docker-compose up. Perintah ini mengonfigurasi kontainer untuk instans web, menggunakan Dockerfile yang ditemukan di akar proyek web, dan menjalankan kontainer pada port yang ditentukan. Anda dapat mengunduh sumber untuk aplikasi ini dari GitHub dan menjalankannya secara lokal. Bahkan aplikasi monolitik ini mendapat manfaat dari disebarkan di lingkungan kontainer.

Untuk satu hal, penyebaran kontainer berarti bahwa setiap instans aplikasi berjalan di lingkungan yang sama. Pendekatan ini mencakup lingkungan pengembang tempat pengujian dan pengembangan awal berlangsung. Tim pengembangan dapat menjalankan aplikasi dalam lingkungan kontainer yang cocok dengan lingkungan produksi.

Selain itu, aplikasi kontainer diskalakan dengan biaya yang lebih rendah. Menggunakan lingkungan kontainer memungkinkan berbagi sumber daya yang lebih besar daripada lingkungan mesin tradisional.

Terakhir, kontainerisasi aplikasi memaksa pemisahan antara logika bisnis dan server penyimpanan. Seiring skala aplikasi, banyak kontainer semuanya akan tergantung pada satu media penyimpanan fisik. Media penyimpanan ini biasanya akan menjadi server ketersediaan tinggi yang menjalankan database SQL Server.

Dukungan Docker

Proyek eShopOnWeb berjalan di .NET. Oleh karena itu, ini dapat berjalan dalam wadah berbasis Linux atau berbasis Windows. Perhatikan bahwa untuk penyebaran Docker, Anda ingin menggunakan jenis host yang sama untuk SQL Server. Kontainer berbasis Linux memungkinkan jejak yang lebih kecil dan lebih disukai.

Anda dapat menggunakan Visual Studio 2017 atau versi lebih baru untuk menambahkan dukungan Docker ke aplikasi yang ada dengan mengeklik kanan proyek di Penjelajah Solusi dan memilih Tambahkan>Dukungan Docker. Langkah ini menambahkan file yang diperlukan dan memodifikasi proyek untuk menggunakannya. Sampel eShopOnWeb saat ini sudah memiliki file-file ini.

File docker-compose.yml tingkat solusi berisi informasi tentang gambar apa yang akan dibangun dan kontainer apa yang akan diluncurkan. File ini memungkinkan Anda menggunakan perintah docker-compose untuk meluncurkan beberapa aplikasi secara bersamaan. Dalam hal ini, aplikasi hanya meluncurkan proyek Web. Anda juga dapat menggunakannya untuk mengonfigurasi dependensi, seperti kontainer database terpisah.

version: '3'

services:
  eshopwebmvc:
    image: eshopwebmvc
    build:
      context: .
      dockerfile: src/Web/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "5106:5106"

networks:
  default:
    external:
      name: nat

File docker-compose.yml mereferensikan Dockerfile dalam proyek Web. Dockerfile digunakan untuk menentukan kontainer dasar mana yang akan digunakan dan bagaimana aplikasi akan dikonfigurasi di dalamnya. Web' Dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

COPY *.sln .
COPY . .
WORKDIR /app/src/Web
RUN dotnet restore

RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/Web/out ./

ENTRYPOINT ["dotnet", "Web.dll"]

Pemecahan masalah Docker

Setelah Anda menjalankan aplikasi kontainer, aplikasi terus berjalan hingga Anda menghentikannya. Anda dapat melihat kontainer yang berjalan dengan perintah docker ps. Anda dapat menghentikan kontainer yang sedang berjalan dengan menggunakan perintah docker stop dan menentukan ID kontainer.

Perhatikan bahwa menjalankan kontainer Docker mungkin terikat ke port yang mungkin Anda coba gunakan di lingkungan pengembangan Anda. Jika Anda mencoba menjalankan atau mendebug aplikasi menggunakan port yang sama dengan kontainer Docker yang sedang berjalan, Anda akan mendapatkan pesan kesalahan yang menyatakan bahwa server tidak dapat mengikat ke port tersebut. Sekali lagi, menghentikan kontainer seharusnya menyelesaikan masalah.

Jika Anda ingin menambahkan dukungan Docker ke aplikasi Anda menggunakan Visual Studio, pastikan Docker Desktop berjalan saat Anda melakukannya. Wizard tidak akan berjalan dengan benar jika Docker Desktop tidak berjalan saat Anda memulai wizard. Selain itu, wizard memeriksa pilihan kontainer Anda saat ini untuk menambahkan dukungan Docker yang benar. Jika Anda ingin menambahkan, dukungan untuk kontainer Windows, Anda perlu menjalankan wizard saat Anda memiliki Docker Desktop yang berjalan dengan kontainer Windows dikonfigurasi. Jika Anda ingin menambahkan, dukungan untuk kontainer Linux, jalankan wizard saat Anda memiliki Docker yang berjalan dengan kontainer Linux yang dikonfigurasi.

Gaya arsitektur aplikasi web lainnya

  • Web-Queue-Worker: Komponen inti arsitektur ini adalah ujung depan web yang melayani permintaan klien, dan pekerja yang melakukan tugas intensif sumber daya, alur kerja yang berjalan lama, atau pekerjaan batch. Ujung depan web berkomunikasi dengan pekerja melalui antrean pesan.
  • N-tingkat: Arsitektur N-tingkat membagi aplikasi menjadi lapisan logis dan tingkat fisik.
  • Layanan mikro: Arsitektur layanan mikro terdiri dari kumpulan layanan kecil dan otonom. Setiap layanan mandiri dan harus menerapkan kemampuan bisnis tunggal dalam konteks terbatas.

Referensi – Arsitektur web umum