Di salah satu majikan saya, kami mengerjakan API REST (tetapi juga berlaku untuk SOAP). Klien, yang merupakan UI aplikasi, akan melakukan panggilan melalui web (LAN dalam penyebaran produksi biasa) ke API. API akan melakukan panggilan ke basis data.
Satu tema yang berulang dalam diskusi kami adalah kinerja: beberapa orang di tim percaya bahwa Anda tidak boleh memiliki beberapa panggilan basis data (biasanya dibaca) dari satu panggilan API karena kinerja; Anda harus mengoptimalkannya sehingga setiap panggilan API hanya memiliki (tepatnya) satu panggilan basis data.
Tetapi apakah itu benar-benar penting? Pertimbangkan bahwa UI harus membuat panggilan jaringan ke API; itu cukup besar (urutan besarnya milidetik). Database dioptimalkan untuk menjaga hal-hal dalam memori dan mengeksekusi membaca sangat, sangat cepat (mis. SQL Server memuat dan menyimpan semuanya dalam RAM dan mengkonsumsi hampir semua RAM gratis Anda jika bisa).
TLDR: Apakah benar-benar penting untuk khawatir tentang beberapa panggilan basis data ketika kita sudah melakukan panggilan jaringan melalui LAN? Jika demikian, mengapa?
Untuk lebih jelas, saya berbicara tentang urutan besarnya - Saya tahu bahwa itu tergantung pada spesifikasi (perangkat keras mesin, pilihan API dan DB, dll.) Jika saya memiliki panggilan yang membutuhkan O (milidetik), apakah mengoptimalkan untuk DB panggilan yang mengurangi urutan besarnya, sebenarnya penting? Atau ada lebih banyak masalah daripada ini?
Sunting: untuk anak cucu, saya pikir cukup konyol untuk membuat klaim bahwa kita perlu meningkatkan kinerja dengan menggabungkan panggilan basis data dalam kondisi ini - terutama dengan kurangnya profil. Namun, itu bukan keputusan saya apakah kami melakukan ini atau tidak; Saya ingin tahu apa alasan di balik berpikir ini adalah cara yang benar untuk mengoptimalkan panggilan API web.
sumber
Jawaban:
Logika
Secara teori, Anda benar. Namun, ada beberapa kelemahan dengan alasan ini:
Dari apa yang Anda nyatakan, tidak jelas apakah Anda benar-benar menguji / membuat profil aplikasi Anda. Dengan kata lain, apakah Anda benar - benar tahu bahwa transfer jaringan dari aplikasi ke API adalah komponen yang paling lambat? Karena itu intuitif, mudah untuk menganggap itu. Namun, ketika membahas kinerja, Anda tidak boleh berasumsi. Di perusahaan saya, saya yang memimpin kinerja. Ketika saya pertama kali bergabung, orang-orang terus berbicara tentang CDN, replikasi, dll berdasarkan intuisi tentang apa yang harus menjadi hambatan. Ternyata, masalah kinerja terbesar kami adalah kueri basis data yang berkinerja buruk.
Anda mengatakan bahwa karena basis data bagus dalam mengambil data, bahwa basis data harus berjalan pada kinerja puncak, digunakan secara optimal, dan tidak ada yang dapat dilakukan untuk memperbaikinya. Dengan kata lain, database dirancang untuk menjadi cepat, jadi saya tidak perlu khawatir tentang hal itu. Garis pemikiran berbahaya lainnya. Itu seperti mengatakan mobil dimaksudkan untuk bergerak cepat, jadi saya tidak perlu mengganti oli.
Cara berpikir ini mengasumsikan satu proses pada satu waktu, atau dengan kata lain, tanpa konkurensi. Diasumsikan bahwa satu permintaan tidak dapat memengaruhi kinerja permintaan lainnya. Sumber daya dibagikan, seperti disk I / O, bandwidth jaringan, kumpulan koneksi, memori, siklus CPU, dll. Oleh karena itu, mengurangi satu panggilan database menggunakan sumber daya bersama dapat mencegahnya menyebabkan permintaan lain melambat. Ketika saya pertama kali bergabung dengan majikan saya saat ini, manajemen percaya bahwa menyetel kueri basis data 3 detik adalah buang-buang waktu. 3 detik sangat sedikit, mengapa membuang waktu? Bukankah kita akan lebih baik dengan CDN atau kompresi atau yang lainnya? Tetapi jika saya dapat membuat kueri 3 detik berjalan dalam 1 detik, katakanlah dengan menambahkan indeks, yaitu 2/3 lebih sedikit pemblokiran, 2/3 lebih sedikit waktu yang dihabiskan untuk menempati utas, dan yang lebih penting, lebih sedikit data yang dibaca dari disk,
Teori
Ada konsep umum bahwa kinerja perangkat lunak hanya tentang kecepatan .
Dari perspektif kecepatan murni, Anda benar. Suatu sistem hanya secepat komponennya yang paling lambat. Jika Anda telah membuat profil kode Anda dan menemukan bahwa Internet adalah komponen yang paling lambat, maka yang lainnya jelas bukan bagian yang paling lambat.
Namun, mengingat hal di atas, saya harap Anda dapat melihat bagaimana pertentangan sumber daya, kurangnya pengindeksan, kode yang ditulis dengan buruk, dll. Dapat menciptakan perbedaan kinerja yang mengejutkan.
Asumsinya
Satu hal terakhir. Anda menyebutkan bahwa panggilan basis data harus murah dibandingkan dengan panggilan jaringan dari aplikasi ke API. Tetapi Anda juga menyebutkan bahwa aplikasi dan server API berada di LAN yang sama. Karena itu, bukankah keduanya sebanding dengan panggilan jaringan? Dengan kata lain, mengapa Anda mengasumsikan bahwa transfer API adalah urutan besarnya lebih lambat daripada transfer basis data ketika mereka berdua memiliki bandwidth yang tersedia yang sama? Tentu saja protokol dan struktur datanya berbeda, saya mengerti, tetapi saya membantah anggapan bahwa mereka adalah urutan besarnya berbeda.
Di mana itu mendapat murkey
Seluruh pertanyaan ini adalah tentang panggilan basis data "banyak" versus "tunggal". Tetapi tidak jelas berapa banyak yang multipel. Karena apa yang saya katakan di atas, sebagai aturan umum, saya sarankan membuat panggilan database sesedikit mungkin. Tapi itu hanya aturan praktis.
Inilah alasannya:
TL; DR
Ya, tetapi hanya sampai batas tertentu. Anda harus mencoba meminimalkan jumlah panggilan basis data saat praktis, tetapi jangan gabungkan panggilan yang tidak ada hubungannya satu sama lain hanya untuk menggabungkannya. Juga, hindari memanggil basis data dalam satu lingkaran di semua biaya.
sumber
Sepertinya tim Anda mengoptimalkan sebelum mereka punya alasan untuk itu. Sudahkah Anda mengukur waktu untuk melaksanakan permintaan ini? Peluang yang memaksa paradigma ini akan menciptakan kinerja yang lebih buruk bagi pengguna akhir karena perjalanan pulang-pergi ke server web akan memiliki latensi yang jauh lebih tinggi daripada waktu koneksi dari server web ke database. Selain itu, sebagian besar peramban web hanya akan membuat 2 koneksi bersamaan ke satu server web, jadi untuk laman yang rumit, Anda mungkin akan menemui hambatan di sana.
Either way, keputusan optimasi tidak boleh dibuat tanpa data untuk mendukungnya. Ukur dan temukan yang terbaik untuk aplikasi Anda.
sumber
Kami tidak bisa memberi tahu Anda.
Kami tidak melihat seperti apa pertanyaan Anda. Kami tidak tahu berapa lama waktu yang dibutuhkan untuk menyelesaikannya. Kami tidak tahu berapa banyak overhead yang terlibat dalam setiap permintaan ke server API Anda. Kami tidak tahu seberapa tersebar klien Anda secara geografis. Dll
Jika ini adalah skenario yang memerlukan pengoptimalan dan merupakan salah satu di mana Anda dapat memutuskan apakah akan membagi atau menggabungkan panggilan, Anda perlu membandingkannya dengan dua cara : Tentukan untuk apa Anda mengoptimalkan (latensi UI, beban server CPU, pertengkaran, dll.) dan pilih salah satu yang lebih baik mencapai sasaran pengoptimalan Anda.
Selain itu, satu-satunya satu hal yang saya dapat menambahkan dengan pasti relatif ini:
Dalam satu permintaan, Anda harus melakukan semua pertanyaan yang perlu Anda lakukan untuk membangun respons.
Dengan kata lain, jika respons tidak dapat dihasilkan sampai semua N query dilakukan, biasanya tidak masuk akal untuk memisahkannya. Jika Anda dapat menghasilkan hasil yang bermakna, baik peralihan atau selesai, setelah setiap kueri, mulai membuat tolok ukur.
sumber
Dua pemikiran:
Pertama, kepada konsumen yang menggunakan API, ia melakukan satu panggilan untuk menyelesaikan tugas. Apa yang terjadi setelah server Anda menerima panggilan untuk mengisi permintaan tidak boleh terlalu kaku. Jika satu panggilan dari konsumen membutuhkan 10 item sub-kerja untuk mengumpulkan data dan mengembalikannya, maka itu harus diterima.
Kedua: Apakah Anda melihat masalah kinerja database aktual dengan proses yang dimaksud? Pengalaman saya menunjukkan bahwa sering mencoba memasukkan semua aspek permintaan basis data ke dalam satu panggilan tunggal dapat menghasilkan panggilan yang kurang efisien daripada hanya membuat tiga atau empat panggilan untuk data. Database modern sangat efisien dalam caching dan rencana eksekusi. Seringkali, ketika Anda mencoba untuk melakukan terlalu banyak Anda akan melihat prosedur dengan kursor (sangat buruk untuk kinerja karena data bertindak secara baris demi baris, bukan sebagai satu set sekaligus) dan kode yang menghasilkan rencana yang kurang efisien daripada jika Anda telah melanggar panggilan menjadi beberapa langkah mudah kecil.
Di luar pengaturan kode yang sederhana, saya setuju bahwa setiap panggilan API mungkin harus memanggil prosedur tersimpan tunggal (atau fungsi db) yang pada gilirannya bertanggung jawab untuk mengisi permintaan. Mungkin ada lebih dari satu langkah dalam prosedur.
sumber
SELECT
.Jika basis data ada di server yang berbeda dari layanan REST Anda, setiap panggilan basis data akan menghasilkan bolak-balik jaringan dan itu dapat sangat merusak kinerja:
Saya pernah mengamati satu panggilan layanan web diterjemahkan ke sekitar 500 permintaan basis data - ini bukan masalah ketika layanan web dan basis data terletak pada mesin yang sama, tetapi berubah menjadi waktu respons 6-7 detik ketika mereka berada di berbeda mesin.
Jelas, 500 perjalanan pulang pergi ke basis data cukup ekstrem. Saya tidak yakin apa persyaratan kinerja Anda, tetapi sebagai aturan praktis saya akan mengatakan bahwa jika Anda tetap di bawah sekitar 10 permintaan basis data per panggilan-REST Anda tidak akan mengalami hit kinerja yang signifikan.
sumber
Kami memiliki beberapa aplikasi yang sangat, sangat cerewet. Ada panggilan basis data untuk setiap. Tunggal. Sedikit. Benda. Melayani data referensi berulang kali adalah bagian utama dari beban kerja pada sistem. Semua penjadwalan thread pekerja, memperoleh dan menjatuhkan kunci, memeriksa rencana cache dll menambahkan bahkan jika tidak ada IO disk yang sebenarnya. Pertentangan lebih tinggi karena transaksi harus menahan kunci di beberapa panggilan DB dan karenanya throughput jauh lebih rendah daripada yang seharusnya. Tim-tim itu sekarang melihat harus membeli server DB yang baru dan sangat mahal karena hal ini.
Jadi, meskipun sebagian besar waktu yang berlalu dalam konfigurasi sistem Anda saat ini diambil dengan panggilan REST API, mengabaikan kinerja di tingkat DB menyimpan masalah untuk masa depan.
sumber
Jalur optimasi yang disajikan hanyalah cara yang salah untuk melihat sesuatu.
Panggilan API harus berupa atom. Dengan kata lain, saya harus dapat membuat 1 panggilan web API untuk melakukan tindakan yang saya inginkan. Apakah itu untuk mengambil data, memperbarui catatan atau apa pun. Seharusnya TIDAK PERNAH mengambil lebih dari 1 panggilan untuk menyebabkan tindakan. Dan mencoba untuk meningkatkan transaksi di beberapa panggilan harus dijauhi seperti wabah.
Terkadang satu tindakan agak rumit. Misalnya, mengambil data yang digabungkan dari beberapa sumber: sekali lagi, ini harus menjadi satu panggilan. Entah semuanya bekerja atau semuanya gagal.
Sekarang, mengatakan bahwa panggilan API tunggal seharusnya hanya mengeksekusi satu permintaan DB agak bodoh. Seperti yang telah Anda tunjukkan, biaya overhead untuk membuat panggilan di seluruh jaringan sering kali lebih mahal dalam hal waktu keseluruhan.
Saya agak bisa memahami pernyataan mereka bahwa satu query berjalan dapat lebih cepat daripada beberapa; tetapi ini memberikan kesan yang salah karena mengabaikan total DB dan beban jaringan. Hanya dengan membuat profil berbagai cara untuk menarik data dari DB, Anda dapat mengetahui apa masalahnya sebenarnya. Saya yakin semua orang memiliki cerita di mana permintaan tertentu dieksekusi 100 kali lebih sering daripada yang diperkirakan membunuh sistem sampai indeks yang tepat diberlakukan ...
Pada akhirnya Anda tidak akan bisa meyakinkan mereka hanya dengan bicara. Buat test case untuk pendekatan dan profil mereka. Perhatikan total waktu untuk memperoleh data yang Anda butuhkan, jumlah lalu lintas jaringan yang dihasilkan, jumlah dan waktu panggilan basis data, dll. Ambil pendekatan holistik - artinya Anda melihat keseluruhan sistem - dan Anda harus memiliki banyak data untuk memakan gagak atau menunjukkan kepada mereka jalur emas.
sumber