Saya telah bertanya apa yang sekarang menjadi pertanyaan Komunitas-dihapus pada SO tentang mengapa seseorang menggunakan javascript Promise.race
, dan pengguna rep tinggi berkomentar:
Jika Anda memiliki dua layanan yang menghitung beberapa nilai, Anda dapat meminta keduanya secara paralel dan menggunakan nilai mana yang pernah dikembalikan terlebih dahulu, daripada meminta satu, menunggu kegagalan, dan kemudian meminta yang kedua.
Saya sudah googled tentang redundansi dan use case ini secara umum tetapi saya tidak dapat menemukan apa pun dan, dari POV saya, tidak pernah merupakan ide yang baik untuk hanya menambahkan beban kerja ke server / layanan jika Anda tidak akan menggunakan respons.
programming-practices
Adelin
sumber
sumber
Jawaban:
Saya berpendapat bahwa ini lebih merupakan pertanyaan ekonomi. Namun, itu adalah panggilan penilaian yang harus mampu dilakukan oleh insinyur. Karenanya, saya menjawab.
Saya membagi jawaban saya menjadi empat bagian:
Manajemen risiko
Jadi, terkadang klien Anda gagal mendapatkan respons dari server. Saya akan menganggap ini bukan karena kesalahan program (jika tidak solusinya adalah memperbaikinya, jadi lakukanlah itu). Sebaliknya, itu pasti karena situasi kebetulan di luar kendali Anda ...
Namun tidak di luar pengetahuan Anda. Kamu harus tahu:
Misalnya, jika gagal dan coba ulang hanya terjadi sekitar 2% dari waktu, mungkin tidak layak untuk mengatasinya. Jika itu terjadi sekitar 80% dari waktu, yah ... tergantung ...
Berapa lama klien harus menunggu? Dan bagaimana hal itu diterjemahkan ke dalam biaya ... Anda tahu, Anda memiliki sedikit keterlambatan dalam aplikasi reguler, mungkin itu bukan masalah besar. Jika ini penting, dan Anda memiliki aplikasi waktu nyata atau permainan video online, ini akan membuat pengguna menjauh, dan Anda mungkin lebih baik berinvestasi di server yang lebih banyak atau lebih baik. Jika tidak, Anda mungkin dapat menaruh pesan "memuat" atau "menunggu server". Kecuali, penundaannya sangat besar (dalam urutan puluhan detik), maka itu bisa terlalu banyak bahkan untuk aplikasi reguler.
Strategi
Seperti yang saya katakan di atas, ada lebih dari satu cara untuk mengatasi masalah ini. Saya akan menganggap Anda sudah memiliki penerapan coba-gagal-coba loop. Jadi, mari kita lihat ...
Sekarang, perhatikan saya katakan ini masih bisa gagal. Jika kami menganggap bahwa permintaan ke server memiliki peluang kegagalan 80%, maka permintaan paralel ke dua server memiliki peluang kegagalan 64%. Jadi, Anda mungkin masih harus mencoba lagi.
Keuntungan bonus memilih server yang lebih cepat dan terus menggunakannya, adalah bahwa server yang lebih cepat juga lebih kecil kemungkinannya gagal karena masalah jaringan.
Yang mengingatkan saya, jika Anda dapat mengetahui mengapa permintaan gagal, lakukanlah. Ini dapat membantu Anda mengelola situasi dengan lebih baik, bahkan jika Anda tidak dapat mencegah kegagalan tersebut. Misalnya, apakah Anda memerlukan lebih banyak kecepatan transfer di sisi server?
Lebih lagi:
Dan siapa bilang Anda hanya perlu melakukan satu ini? Anda dapat menempatkan pesan pemuatan, permintaan beberapa server yang tersebar di seluruh dunia untuk memilih yang lebih cepat dan hanya menggunakannya dari sana, pada kegagalan coba lagi pada satu lingkaran, dan minta masing-masing server tersebut menjadi sekelompok mesin dengan penyeimbangan beban . Kenapa tidak? Ya, biaya ...
Biaya
Ada empat biaya:
Anda harus menyeimbangkannya.
Misalnya, katakanlah Anda menghasilkan sekitar satu dolar per pengguna yang puas. Anda memiliki 3000 pengguna per hari. Bahwa permintaan gagal sekitar 50% dari waktu. Dan 2% dari pengguna tersebut pergi tanpa membayar saat permintaan gagal. Ini berarti Anda kehilangan (3000 * 50% * 2%) 30 dolar per hari. Sekarang, katakanlah bahwa mengembangkan fitur baru akan dikenakan biaya 100 dolar AS dan menyebarkan server akan dikenakan biaya 800 dolar AS - dan mengabaikan biaya runtime - ini berarti Anda akan mendapatkan pengembalian investasi dalam ((100 + 800) / 30 ) 30 hari. Sekarang, Anda dapat memeriksa anggaran Anda dan memutuskan.
Jangan menganggap nilai-nilai ini mewakili kenyataan, saya memilihnya untuk kenyamanan matematika.
Adendum:
Masalahnya adalah, jika Anda mempertimbangkan masalah dalam hal biaya balacing, Anda dapat membuat estimasi biaya untuk strategi yang Anda pertimbangkan, dan menggunakan analisis ini untuk memutuskan.
Intuisi
Intuisi jika ditumbuhkan oleh pengalaman. Saya tidak menyarankan untuk melakukan analisis semacam ini setiap waktu. Beberapa orang melakukannya, dan itu tidak masalah. Saya menyarankan Anda untuk memiliki pemahaman tentang hal ini, dan mengembangkan intuisi untuk itu.
Selanjutnya, dalam bidang teknik, selain dari pengetahuan yang kita dapatkan dari sains yang sebenarnya, kita juga belajar dalam praktik dan menyusun pedoman tentang apa yang berhasil dan yang tidak. Oleh karena itu, sering kali bijaksana untuk melihat keadaan seni ... meskipun, kadang-kadang Anda perlu melihat di luar area Anda.
Dalam hal ini, saya akan melihat video game online. Mereka memiliki layar muat, mereka memiliki beberapa server, mereka akan memilih server berdasarkan latensi, dan mereka bahkan dapat memungkinkan pengguna untuk berpindah server. Kami tahu itu berhasil.
Saya menyarankan untuk melakukan itu daripada memboroskan lalu lintas jaringan dan waktu server pada setiap permintaan, juga menyadari bahwa bahkan dengan server berlebihan, kegagalan dapat terjadi.
sumber
Ini dapat diterima, jika waktu klien lebih berharga daripada waktu di server.
Jika klien harus cepat dan akurat. Anda dapat membenarkan permintaan beberapa server. Dan bagus untuk membatalkan permintaan jika jawaban yang valid diterima.
Dan tentu saja selalu bijaksana untuk berkonsultasi dengan pemilik / pengelola server.
sumber
Teknik ini dapat mengurangi latensi. Waktu respons server tidak deterministik. Pada skala kemungkinan akan ada setidaknya satu server yang menunjukkan waktu respons yang buruk. Oleh karena itu, apa pun yang menggunakan server itu juga akan memiliki waktu respons yang buruk. Dengan mengirimkan ke beberapa server, seseorang mengurangi risiko berbicara dengan server yang berkinerja buruk.
Biaya termasuk lalu lintas jaringan tambahan, pemrosesan server yang terbuang dan kompleksitas aplikasi (pikir ini bisa disembunyikan di perpustakaan). Biaya ini dapat dikurangi dengan membatalkan permintaan yang tidak digunakan, atau menunggu sebentar sebelum mengirim permintaan kedua.
Ini satu kertas , dan satu lagi . Saya ingat pernah membaca makalah Google implementasi mereka juga.
sumber
Saya sebagian besar setuju dengan jawaban lain, tetapi saya pikir ini harus sangat jarang dalam praktek. Saya ingin membagikan contoh yang jauh lebih umum dan masuk akal untuk kapan Anda akan menggunakan
Promise.race()
, sesuatu yang kebetulan saya gunakan untuk beberapa minggu yang lalu (baik, setara python).Katakanlah Anda memiliki daftar tugas yang panjang, beberapa yang dapat dijalankan secara paralel, dan beberapa yang harus dijalankan sebelum yang lain. Anda dapat memulai semua tugas tanpa ketergantungan, lalu tunggu daftar itu dengan
Promise.race()
. Segera setelah tugas pertama selesai, Anda dapat memulai tugas apa pun yang bergantung pada tugas pertama itu, danPromise.race()
sekali lagi pada daftar baru dikombinasikan dengan tugas-tugas yang belum selesai dari daftar asli. Terus ulangi sampai semua tugas selesai.Catatan API Javascript tidak dirancang secara ideal untuk ini. Ini adalah jumlah minimum yang bisa digunakan, dan Anda harus menambahkan sedikit kode lem. Namun, maksud saya adalah bahwa fungsi seperti
race()
jarang digunakan untuk redundansi. Mereka ada terutama ketika Anda benar-benar menginginkan hasil dari semua janji, tetapi tidak ingin menunggu semuanya selesai sebelum mengambil tindakan selanjutnya.sumber
new Promise
dipanggil, dan tidak dimulai kembali ketikaPromise.race()
dipanggil. Beberapa implementasi janji malas, tetapi bersemangat jauh lebih umum. Anda dapat menguji dengan membuat janji di konsol yang masuk ke konsol. Anda akan segera melihatnya log. Kemudian sampaikan janji itu kepadaPromise.race()
. Anda akan melihatnya tidak masuk lagi.Selain pertimbangan teknis, Anda mungkin ingin menggunakan pendekatan ini ketika itu merupakan bagian dari model bisnis Anda yang sebenarnya.
Variasi pada pendekatan ini relatif umum dalam penawaran waktu nyata pada iklan. Dalam model ini, penerbit (penyedia ruang iklan) akan meminta pengiklan (penyedia iklan) untuk menawar tayangan oleh pengguna tertentu. Jadi untuk setiap tayangan tersebut, Anda akan meminta setiap pengiklan berlangganan, mengirimkan pertanyaan dengan detail tayangan ke titik akhir yang disediakan oleh masing-masing pengiklan (atau sebagai alternatif, skrip yang disediakan oleh pengiklan yang berjalan sebagai titik akhir di server Anda sendiri), balapan semua permintaan ini hingga batas waktu (mis. 100 ms) dan kemudian mengambil tawaran tertinggi, mengabaikan yang lain.
Variasi khusus dari ini yang membantu mengurangi waktu tunggu klien adalah membuat penerbit mengizinkan nilai sasaran minimum untuk tawaran tersebut, sehingga tawaran pengiklan pertama yang melampaui nilai itu akan segera diterima (atau, jika tidak ada tawaran yang melampaui nilai, yang max akan diambil). Jadi, dalam variasi ini, kueri pertama yang tiba bisa menang dan yang lainnya dibuang, meskipun mereka sama bagus atau bahkan lebih baik.
sumber