Bagaimana arsitektur sistem layanan mikro menghindari kemacetan jaringan?

72

Saya telah membaca banyak tentang arsitektur microservice untuk aplikasi server, dan telah bertanya-tanya bagaimana penggunaan jaringan internal bukanlah hambatan atau kelemahan yang signifikan dibandingkan dengan arsitektur monolith.

Demi ketepatan, berikut adalah interpretasi saya dari dua istilah:

  1. Arsitektur Monolith: Satu aplikasi dalam satu bahasa yang menangani semua fungsi, data, dll. Load balancer mendistribusikan permintaan dari pengguna akhir di beberapa mesin, masing-masing menjalankan satu instance dari aplikasi kami.

  2. Arsitektur microservice: Banyak aplikasi (microservices) yang menangani sebagian kecil fungsi dan data. Setiap microservice memaparkan API umum yang diakses melalui jaringan (sebagai lawan komunikasi antar-proses atau memori bersama pada mesin yang sama). Panggilan API biasanya dilakukan di server untuk menghasilkan halaman, meskipun mungkin sebagian dari pekerjaan ini dilakukan oleh klien yang meminta layanan microser individual.

Untuk imajinasi naif saya, sepertinya arsitektur layanan microser menggunakan lalu lintas jaringan yang lambat sebagai lawan dari sumber daya yang lebih cepat pada mesin yang sama (memori dan disk). Bagaimana cara memastikan bahwa permintaan API melalui jaringan internal tidak akan memperlambat keseluruhan waktu respons?

James Mishra
sumber
Jaringan internal seringkali 1 Gbps, terkadang lebih cepat. Pikirkan tentang ukuran rata-rata respons JSON dari API. Berapa banyak tanggapan seperti itu dapat ditransmisikan melalui koneksi 1 Gbps dalam satu detik?
Arseni Mourzenko
3
jika Anda pikir Anda membutuhkan layanan microser - dan Anda mungkin! - dua buku bagus untuk persiapan: amazon.com/Building-Microservices-Sam-Newman/dp/1491950358 dan amazon.com/Release-It-Production-Ready-Pragmatic-Programmers/dp/…
Steven A. Lowe
@ MainMa masalahnya bukan pada bandwidth, tetapi dalam penundaan. Dan jika Anda perlu melakukan bolak-balik, Anda akan terkejut betapa kecilnya bandwidth aktual yang dapat Anda gunakan
Stephan Eggermont

Jawaban:

61

Jaringan internal sering menggunakan koneksi 1 Gbps, atau lebih cepat. Koneksi serat optik atau ikatan memungkinkan bandwidth yang jauh lebih tinggi antara server. Sekarang bayangkan ukuran rata-rata respons JSON dari API. Berapa banyak tanggapan semacam itu dapat ditransmisikan melalui koneksi 1 Gbps dalam satu detik?

Mari kita benar-benar menghitung. 1 Gbps adalah 131 072 KB per detik. Jika respons JSON rata-rata adalah 5 KB (yang cukup banyak!), Anda dapat mengirim 26 214 respons per detik melalui kabel hanya dengan satu pasang mesin . Tidak terlalu buruk, bukan?

Inilah sebabnya mengapa koneksi jaringan biasanya bukan hambatan.

Aspek lain dari layanan microser adalah Anda dapat mengukur dengan mudah. Bayangkan dua server, satu hosting API, satu lagi memakannya. Jika koneksi menjadi penghambat, tambahkan saja dua server lain dan Anda dapat menggandakan kinerjanya.

Inilah saat 2626 respons kami sebelumnya per detik menjadi terlalu kecil untuk skala aplikasi. Anda menambahkan sembilan pasangan lain, dan sekarang Anda dapat melayani 262 140 respons.

Tapi mari kita kembali ke pasangan server kita dan melakukan perbandingan.

  • Jika permintaan non-cache rata-rata ke database membutuhkan 10 ms., Anda dibatasi hingga 100 kueri per detik. 100 pertanyaan. 26 214 tanggapan. Mencapai kecepatan 26 214 respons per detik membutuhkan sejumlah besar caching dan optimisasi (jika respons tersebut benar-benar perlu melakukan sesuatu yang bermanfaat, seperti meng-query database; "Hello World" - style-response tidak memenuhi syarat).

  • Di komputer saya, sekarang, DOMContentLoaded untuk beranda Google terjadi 394 ms. setelah permintaan dikirim. Itu kurang dari 3 permintaan per detik. Untuk beranda Programmers.SE, itu terjadi 603 ms. setelah permintaan dikirim. Itu bahkan 2 permintaan per detik. Omong-omong, saya memiliki koneksi internet 100 Mbps dan komputer cepat: banyak pengguna akan menunggu lebih lama.

    Jika hambatannya adalah kecepatan jaringan antara server, kedua situs tersebut dapat melakukan ribuan panggilan ke API yang berbeda saat melayani halaman.

Kedua kasus menunjukkan bahwa jaringan mungkin tidak akan menjadi hambatan Anda dalam teori (dalam praktek, Anda harus melakukan benchmark aktual dan profiling untuk menentukan lokasi yang tepat dari bottleneck dari Anda sistem tertentu host pada hardware tertentu). Waktu yang dihabiskan untuk melakukan pekerjaan yang sebenarnya (apakah itu query SQL, kompresi, apa pun) dan mengirim hasilnya ke pengguna akhir jauh lebih penting.

Pikirkan tentang basis data

Biasanya, basis data dihosting secara terpisah dari aplikasi web yang menggunakannya. Hal ini dapat menimbulkan kekhawatiran: bagaimana dengan kecepatan koneksi antara server hosting aplikasi dan server hosting database?

Tampaknya ada kasus di mana memang, kecepatan koneksi menjadi bermasalah, yaitu ketika Anda menyimpan sejumlah besar data yang tidak perlu diproses oleh database itu sendiri dan harus tersedia sekarang (itu adalah file biner besar). Tetapi situasi seperti itu jarang terjadi: dalam kebanyakan kasus, kecepatan transfer tidak sebesar itu dibandingkan dengan kecepatan pemrosesan permintaan itu sendiri.

Ketika kecepatan transfer sebenarnya penting adalah ketika sebuah perusahaan menjadi tuan rumah set data besar pada NAS, dan NAS diakses oleh banyak klien pada saat yang sama. Di sinilah SAN bisa menjadi solusi. Ini dikatakan, ini bukan satu-satunya solusi. Kabel Cat 6 dapat mendukung kecepatan hingga 10 Gbps; ikatan juga dapat digunakan untuk meningkatkan kecepatan tanpa mengubah kabel atau adapter jaringan. Solusi lain ada, yang melibatkan replikasi data di beberapa NAS.

Lupakan kecepatan; pikirkan skalabilitas

Poin penting dari aplikasi web adalah untuk dapat mengukur. Meskipun kinerja aktual penting (karena tidak ada yang mau membayar untuk server yang lebih kuat), skalabilitas jauh lebih penting, karena skalabilitas memungkinkan Anda untuk melemparkan perangkat keras tambahan saat dibutuhkan.

  • Jika Anda memiliki aplikasi yang tidak terlalu cepat, Anda akan kehilangan uang karena Anda akan memerlukan server yang lebih kuat.

  • Jika Anda memiliki aplikasi cepat yang tidak bisa menskalakan, Anda akan kehilangan pelanggan karena Anda tidak akan bisa menanggapi permintaan yang meningkat.

Dengan cara yang sama, mesin virtual satu dekade lalu dianggap sebagai masalah kinerja yang sangat besar. Memang, hosting aplikasi di server vs hosting di mesin virtual memiliki dampak kinerja yang penting. Meskipun jaraknya jauh lebih kecil hari ini, masih ada.

Meskipun kehilangan kinerja ini, lingkungan virtual menjadi sangat populer karena fleksibilitas yang mereka berikan.

Seperti halnya kecepatan jaringan, Anda mungkin menemukan bahwa VM adalah hambatan yang sebenarnya dan mengingat skala Anda yang sebenarnya, Anda akan menghemat miliaran dolar dengan hosting aplikasi Anda secara langsung, tanpa VM. Tapi ini bukan yang terjadi pada 99,9% aplikasi: kemacetannya ada di tempat lain, dan kelemahan dari hilangnya beberapa mikrodetik karena VM mudah dikompensasi oleh manfaat abstraksi perangkat keras dan skalabilitas.

Arseni Mourzenko
sumber
Tentu, kita dapat mengatakan bahwa respons JSON kecil, tetapi bagaimana dengan kuantitasnya ? Saya merasa seperti sebuah situs web di bawah beban berat akan memiliki lebih banyak lalu lintas jaringan dalam arsitektur microservice daripada arsitektur monolitik (di mana satu-satunya lalu lintas jaringan adalah ke / dari server basis data). Caching dapat membantu, tetapi untuk waktu nyata dan / atau konten yang dihasilkan secara dinamis, saya tidak tahu seberapa jauh caching akan berlangsung.
James Mishra
@JamesMishra: Saya mengedit jawaban saya untuk mengatasi masalah Anda.
Arseni Mourzenko
Jawaban Anda sempurna . Anda tidak hanya menjawab setiap keberatan yang dapat saya pikirkan, Anda menjawab keberatan yang tidak saya pikirkan.
James Mishra
5
2 Cents saya dari dunia nyata: Sebuah sistem yang terdiri dari layanan microser yang sangat cerewet dapat mengalami masalah kinerja murni karena jaringan yang tercekik. Caching dan desain berbasis aliran acara adalah teman Anda dalam kasus tersebut. Selain jaringan, CPU dan memori, sistem berbasis microservice juga perlu memasukkan ketahanan dalam desainnya: apa yang terjadi jika layanan mikro turun? Bagaimana Anda membangun retries, transaksi terdistribusi, penyembuhan diri, pemantauan - Saya sarankan mencari "Anda harus setinggi ini untuk menggunakan layanan microser"
Sudhanshu Mishra
4
Harap perbaiki saya jika saya salah, tetapi sejauh yang saya tahu, jika Anda memiliki jaringan 1Gbps, itu berarti Anda secara teoritis dapat mengirim data senilai 1Gb per detik melalui jaringan itu. Terlepas dari jumlah koneksi. Semakin tinggi jumlah koneksi, semakin rendah bandwidth untuk setiap koneksi. Jadi, batas Anda yang sebenarnya tanpa memutakhirkan jaringan Anda untuk mendukung bandwidth yang lebih tinggi adalah 26.214 respons per detik. Menambahkan lebih banyak server tidak akan meningkatkan bandwidth jaringan Anda. Jika satu cluster dapat memuntahkan jumlah lalu lintas itu, menambahkan lebih banyak server menghasilkan lebih banyak data akan memadatkan jaringan Anda.
Sebbe
7

Saya pikir Anda terlalu banyak membaca bagian 'mikro'. Itu tidak berarti mengganti setiap kelas dengan layanan jaringan, tetapi komponen aplikasi monolitik menjadi komponen berukuran masuk akal, masing-masing berurusan dengan aspek program Anda. Layanan tidak akan berbicara satu sama lain, jadi paling buruk Anda telah membagi permintaan jaringan besar menjadi beberapa yang lebih kecil. Data yang dikembalikan tidak akan jauh berbeda dengan apa yang Anda terima (meskipun Anda mungkin mengembalikan lebih banyak data dan menggabungkannya di klien)

gbjbaanb
sumber
3
"Layanan tidak akan berbicara satu sama lain." Saya membayangkan bahwa layanan microser mungkin memiliki dependensi bersama (otentikasi, mungkin?) Bahwa seseorang dapat memisahkan ke layanan microser lain. LDAP, dalam arti tertentu, adalah microservice otentikasi dan saya membayangkan bahwa semua microservices lain berbicara dengannya. Atau ... apakah otentikasi hanya terjadi sekali? Bagaimana setiap microservice memeriksa izin terhadap otentikasi untuk mencegah serangan Akses Objek Langsung?
James Mishra
2
@ JamesMishra yah .. itu tergantung. Ketika saya terakhir menggunakan arsitektur microservice, setiap layanan benar-benar independen dari yang lain untuk tujuan keamanan (tetapi juga alasan korporasi silo). Auth ditangani oleh masing-masing secara berbeda, meskipun dikendalikan oleh kebijakan arsitektur. Namun, tidak ada alasan mereka tidak dapat berbicara dengan auth misalnya, atau hanya memiliki auth berdasarkan perpustakaan. Tapi .. Saya mencoba mengatakan bahwa mereka seharusnya tidak melakukan banyak panggilan di antara mereka sendiri, bukan bahwa mereka tidak boleh mengkonsumsi layanan sebagai klien sendiri.
gbjbaanb
@JamesMishra, auth seringkali merupakan layanannya sendiri di lingkungan ini, sehingga setiap layanan harus memanfaatkannya daripada melakukan implementasi penuh sendiri.
Paul
2

Dengan menyusun kode dan akses sumber daya Anda sehingga sistem yang dihasilkan dapat cukup fleksibel untuk dijalankan sebagai aplikasi monolitik atau aplikasi terdistribusi melalui konfigurasi. Jika Anda menghapus abstrak mekanisme komunikasi di balik beberapa antarmuka umum dan Anda membangun sistem Anda dengan mempertimbangkan konkurensi, Anda dapat dengan mudah mengoptimalkan semuanya setelah Anda membuat profil sistem Anda dan menemukan leher botol yang sebenarnya.

mortalapeman
sumber
Contoh untuk menjelaskan apa yang saya asumsikan bahwa @malapalapeman berarti: Anda memiliki antarmuka java / c # IProductAvailibitiy di mana semua konsumen IProductAvailibitiy terhubung. Ada juga ProductAvailibitiyImpl kelas yang mengimplementasikan antarmuka ini dan ProductAvailibitiyMicroservice yang menggunakan ProductAvailibitiyImpl. Konsumen dapat dikonfigurasikan untuk menggunakan ProductAvailibitiyImpl lokal atau proxy jarak jauh ke ProductAvailibitiyMicroservice
k3b
2

Saya ingin menambahkan perspektif yang berbeda, dari industri yang berbeda dengan asumsi yang sangat berbeda - simulasi distribusi (entitas-level). Secara konseptual, ini sangat mirip dengan video game FPS yang didistribusikan. Perbedaan utama: semua pemain berbagi keadaan: di mana naga itu sekarang; tidak ada panggilan basis data; semuanya disimpan dalam RAM untuk kecepatan dan latensi rendah, throughput kurang relevan (tapi saya kira Anda tidak bisa mengabaikannya juga).

Anda dapat menganggap setiap aplikasi yang berpartisipasi baik sebagai monolith (yang mewakili semua sisi pemain), atau sebagai layanan mikro (yang hanya mewakili satu pemain di tengah kerumunan).

Ada ketertarikan dari kolega saya untuk memecah satu aplikasi yang berpartisipasi itu sendiri, lebih jauh ke dalam layanan microser kecil yang mungkin dibagikan, misalnya kerusakan arbitrase atau perhitungan line-of-sight, hal-hal yang biasanya dimasukkan ke dalam simulasi.

Masalahnya adalah latensi pengiriman panggilan dan menunggu permintaan. Bandwidth tidak relevan dan berlimpah, seperti yang ditunjukkan orang lain. Tetapi jika perhitungan line-of-sight berjalan dari 1 microsec ke 100 microsec (katakanlah, karena antrian dalam microservice baru yang dibagikan di antara semua aplikasi pemain), itu adalah kerugian besar (mungkin perlu beberapa atau banyak perhitungan line-of-sight untuk setiap pembaruan, beberapa pembaruan / detik).

Pikirkan baik-baik tentang cara kerja layanan, kapan mereka dipanggil, dan data apa yang dipertukarkan. Aplikasi kami sudah tidak bertukar hanya info posisi, mereka bertukar info perhitungan mati - Saya di posisi x, menuju ke arah y dengan kecepatan q. Dan saya tidak perlu memperbarui info saya sampai asumsi-asumsi itu berubah. Banyak pembaruan yang lebih sedikit, dan latensi (walaupun masih merupakan masalah) muncul secara lebih jarang secara proporsional.

Jadi, alih-alih meminta layanan dengan butiran halus pada frekuensi yang lebih tinggi, coba turunkan frekuensinya dengan:

  1. mengubah data mana yang diminta dan menggunakan perhitungan lokal
  2. mengirim parameter kueri atau pemicu untuk respons asinkron
  3. permintaan batching
  4. mengantisipasi permintaan dan menyiapkan tanggapan di muka, pada spekulasi (kebalikan dari evaluasi malas)
  5. sedapat mungkin, hindari layanan-layanan microser yang memanggil layanan-layanan microser lainnya; ini menambah masalah, jelas. Saya mengerti ini adalah insentif untuk membuat layanan microser lebih besar dan agak mengalahkan intinya, tetapi layanan microser tidak bersahabat dengan latensi. Mungkin akui saja dan lupakan.

Sekarang ingatlah untuk memeriksa asumsi Anda tentang sistem Anda. Jika Anda lebih mementingkan throughput daripada latensi, atau tidak memiliki status berbagi, dll., Tentu saja, gunakan layanan microsoft di mana mereka masuk akal. Saya hanya mengatakan mungkin jangan menggunakannya di tempat yang tidak masuk akal.

Kapten Aporam
sumber
1

Imajinasi naif Anda benar. Dan seringkali itu tidak masalah. Mesin modern cepat. Keuntungan utama dari arsitektur layanan mikro terlihat dalam pengembangan dan upaya pemeliharaan dan waktu.

Dan tentu saja tidak ada aturan yang mengatakan Anda tidak dapat menggunakan memori bersama atau bahkan secara fisik menggunakan beberapa layanan dalam satu yang dapat dieksekusi. Selama Anda mendesainnya, jangan bergantung pada itu.

Stephan Eggermont
sumber
CPU cepat. Memori cepat. SSD cepat. Tetapi apakah kartu jaringan dan router dan switch "cepat"? Jawaban lain bersikeras demikian, tetapi saya tidak yakin.
James Mishra
Jelas mudah untuk mengalami masalah kecepatan jaringan. Jalankan satu layanan di San Francisco, yang lain di Amsterdam, dan konsumsilah di Sydney. Keterlambatan adalah kuncinya, bukan bandwidth. Jadi jangan lakukan itu. Dan buat layanan sebesar yang masuk akal
Stephan Eggermont
1

Seperti yang banyak orang sebutkan, ini bukan tentang kemacetan jaringan. Ini lebih tentang kerapuhan jaringan. Jadi langkah pertama adalah menghindari komunikasi yang sinkron. Lebih mudah daripada kedengarannya. Yang Anda butuhkan adalah layanan dengan batas yang benar. Batas kanan menghasilkan layanan yang otonom, longgar, dan sangat kohesif. Layanan yang baik tidak memerlukan informasi dari layanan lain, sudah ada. Satu-satunya cara komunikasi yang baik adalah melalui acara. Layanan yang baik pada akhirnya juga konsisten, sehingga tidak ada transaksi yang didistribusikan.

Cara untuk mencapai kebaikan ini adalah mengidentifikasi kemampuan bisnis Anda terlebih dahulu. Kemampuan bisnis adalah tanggung jawab bisnis tertentu. Beberapa kontribusi untuk nilai bisnis secara keseluruhan. Jadi, inilah urutan langkah saya yang saya ambil ketika memikirkan batasan sistem:

  1. Identifikasi tanggung jawab bisnis tingkat tinggi. Akan ada beberapa dari mereka. Perlakukan layanan ini sebagai langkah yang harus dilalui organisasi Anda untuk mencapai tujuan bisnisnya.
  2. Menggali lebih dalam dalam setiap layanan. Identifikasi layanan tingkat bawah yang terdiri dari layanan induk.
  3. Bersamaan dengan dua poin pertama pikirkan tentang komunikasi layanan. Mereka harus melakukannya terutama melalui acara, hanya untuk saling memberi tahu tentang hasil proses bisnis mereka. Acara tidak boleh dianggap sebagai konveyor data.

Perlu diingat bahwa layanan bisnis mencakup orang, aplikasi, proses bisnis. Biasanya hanya sebagian yang direpresentasikan sebagai otoritas teknis.

Ini mungkin terdengar agak abstrak, jadi mungkin contoh identifikasi batas layanan akan menarik.

Zapadlo
sumber
0

Hanya faktor lain untuk ditambahkan ke jawaban saat ini. Dengan layanan berbutir kasar . Anda ingin menghindari latensi dari semua panggilan jadi alih-alih membuat 10 panggilan, Anda membuat panggilan yang mendapatkan 10 data yang dibutuhkan dalam DTO.

Dan ingat bahwa layanan mikro tidak mikro seperti yang orang pikirkan.

Borjab
sumber