Banyak layanan menggunakan pola pembatasan untuk mengontrol sumber daya yang mereka konsumsi, batasan diberlakukan pada tingkat di mana aplikasi atau layanan lain dapat mengaksesnya. Anda dapat menggunakan pola pembatas tarif untuk membantu Anda menghindari atau meminimalkan kesalahan pelambatan yang terkait dengan limit pembatasan ini dan untuk membantu Anda memprediksi throughput secara lebih akurat.
Pola pembatas tarif sesuai dalam banyak skenario, tetapi sangat membantu untuk tugas otomatis berulang skala besar seperti pemrosesan batch.
Konteks dan masalah
Melakukan sejumlah besar operasi menggunakan layanan yang dibatasi dapat mengakibatkan peningkatan lalu lintas dan throughput, karena Anda harus melacak permintaan yang ditolak dan kemudian mencoba kembali operasi tersebut. Ketika jumlah operasi meningkat, batas throttling mungkin memerlukan beberapa kali pengiriman ulang data, sehingga menghasilkan dampak kinerja yang lebih besar.
Sebagai contoh, pertimbangkan upaya naif berikut pada proses kesalahan untuk menyerap data ke Azure Cosmos DB:
- Aplikasi Anda perlu menyerap 10.000 rekaman ke Azure Cosmos DB. Setiap catatan biaya 10 Unit Permintaan (RUs) untuk menelan, membutuhkan total 100.000 RUs untuk menyelesaikan pekerjaan.
- Instans Azure Cosmos DB Anda memiliki kapasitas yang disediakan 20.000 RU.
- Anda mengirim semua 10.000 rekaman ke Azure Cosmos DB. 2.000 rekaman berhasil ditulis dan 8.000 rekaman ditolak.
- Anda mengirim 8.000 rekaman yang tersisa ke Azure Cosmos DB. 2.000 rekaman berhasil ditulis dan 6.000 rekaman ditolak.
- Anda mengirim 6.000 rekaman yang tersisa ke Azure Cosmos DB. 2.000 rekaman berhasil ditulis dan 4.000 rekaman ditolak.
- Anda mengirim 4.000 rekaman yang tersisa ke Azure Cosmos DB. 2.000 rekaman berhasil ditulis dan 2.000 rekaman ditolak.
- Anda mengirim 2.000 rekaman yang tersisa ke Azure Cosmos DB. Semuanya ditulis dengan sukses.
Pekerjaan penyerapan berhasil diselesaikan, tetapi hanya setelah mengirim 30.000 rekaman ke Azure Cosmos DB meskipun seluruh himpunan data hanya terdiri dari 10.000 rekaman.
Ada faktor-faktor tambahan yang perlu dipertimbangkan dalam contoh di atas:
- Sejumlah besar kesalahan juga dapat mengakibatkan pekerjaan tambahan untuk mencatat kesalahan ini dan memproses data log yang dihasilkan. Pendekatan naif ini akan menangani 20.000 kesalahan, dan mencatat kesalahan ini dapat membebankan biaya pemrosesan, memori, atau sumber daya penyimpanan.
- Tidak diketahui batas throttling dari layanan konsumsi, pendekatan naif tidak memiliki cara untuk menetapkan ekspektasi tentang berapa lama pemrosesan data akan berlangsung. Pembatasan tarif dapat memungkinkan Anda menghitung waktu yang diperlukan untuk konsumsi.
Solusi
Pembatasan tarif dapat mengurangi lalu lintas Anda dan berpotensi meningkatkan throughput dengan mengurangi jumlah catatan yang dikirim ke layanan selama periode waktu tertentu.
Layanan mungkin dibatasi berdasarkan metrik yang berbeda dari waktu ke waktu, seperti:
- Jumlah operasi (misalnya, 20 permintaan per detik).
- Jumlah data (misalnya, 2 GiB per menit).
- Biaya operasi relatif (misalnya, 20.000 RUs per detik).
Terlepas dari metrik yang digunakan untuk throttling, implementasi pembatasan tarif Anda akan melibatkan pengendalian jumlah dan / atau ukuran operasi yang dikirim ke layanan selama periode waktu tertentu, optimalkan penggunaan layanan Anda sementara tidak melebihi kapasitas pelambatannya.
Dalam skenario di mana API Anda dapat menangani permintaan lebih cepat daripada yang diizinkan oleh layanan pembatasan penyerapan, Anda harus mengelola seberapa cepat Anda dapat menggunakan layanan ini. Namun, hanya memperlakukan throttling sebagai masalah ketidakcocokan tingkat data, dan hanya menyangga permintaan konsumsi Anda sampai layanan yang dibatasi dapat mengejar ketinggalan, ini berisiko. Jika aplikasi Anda macet dalam skenario ini, Anda berisiko kehilangan data buffer ini.
Untuk menghindari risiko ini, pertimbangkan untuk mengirim catatan Anda ke sistem pesan tahan lama yang dapat menangani tingkat konsumsi Anda secara penuh. (Layanan seperti Azure Event Hubs dapat menangani jutaan operasi per detik). Anda kemudian dapat menggunakan satu atau lebih prosesor pekerjaan untuk membaca catatan dari sistem pesan pada tingkat terkendali yang berada dalam batas layanan yang dibatasi. Mengirimkan catatan ke sistem olahpesan dapat menyimpan memori internal dengan memungkinkan Anda untuk menghapus catatan tertentu yang dapat diproses selama interval waktu tertentu.
Azure menyediakan beberapa layanan pesan tahan lama yang dapat Anda gunakan dengan pola ini, termasuk:
Saat Anda mengirim rekaman, periode waktu yang Anda gunakan untuk merilis rekaman mungkin lebih terperinci daripada periode pembatasan layanan. Sistem sering mengatur pembatasan berdasarkan rentang waktu yang dapat Anda pahami dan kerjakan dengan mudah. Namun, untuk komputer yang menjalankan layanan, kerangka waktu ini mungkin sangat panjang dibandingkan dengan seberapa cepat ia dapat memproses informasi. Misalnya, sistem mungkin dibatasi per detik atau per menit, tetapi umumnya kode diproses pada urutan nanodetik atau milidetik.
Meskipun tidak diperlukan, sering disarankan untuk mengirim catatan dalam jumlah yang lebih kecil dan lebih sering untuk meningkatkan throughput. Jadi alih-alih mencoba mengumpulkan semuanya untuk rilis sekali sedetik atau sekali semenit, Anda bisa lebih terperinci daripada itu untuk menjaga konsumsi sumber daya Anda (memori, CPU, jaringan, dan sebagainya) mengalir pada tingkat yang lebih merata, mencegah potensi hambatan karena ledakan permintaan yang tiba-tiba. Misalnya, jika layanan memungkinkan 100 operasi per detik, penerapan pembatas tarif bahkan dapat mengeluarkan permintaan dengan melepaskan 20 operasi setiap 200 milidetik, seperti yang ditunjukkan pada grafik berikut.
Selain itu, kadang-kadang itu diperlukan untuk beberapa proses yang tidak terkoordinasi untuk berbagi layanan yang dibatasi. Untuk menerapkan pembatasan tarif dalam skenario ini, Anda dapat secara logis mempartisi kapasitas layanan dan kemudian menggunakan sistem pengecualian bersama terdistribusi untuk mengelola kunci eksklusif pada partisi tersebut. Proses yang tidak terkoordinasi kemudian dapat bersaing untuk mengunci partisi tersebut kapan pun mereka membutuhkan kapasitas. Untuk setiap partisi yang dikunci ole suatu proses, itu diberikan sejumlah kapasitas.
Misalnya, jika sistem yang dicekik memungkinkan 500 permintaan per detik, Anda dapat membuat 20 partisi senilai masing-masing 25 permintaan per detik. Jika proses diperlukan untuk mengeluarkan 100 permintaan, mungkin meminta sistem pengecualian bersama terdistribusi untuk empat partisi. Sistem mungkin memberikan dua partisi selama 10 detik. Proses kemudian akan menilai batas hingga 50 permintaan per detik, menyelesaikan tugas dalam dua detik, dan kemudian melepaskan kunci.
Salah satu cara untuk menerapkan pola ini adalah dengan menggunakan Azure Storage. Dalam skenario ini, Anda membuat satu gumpalan 0-byte per partisi logis dalam kontainer. Aplikasi Anda kemudian dapat memperoleh sewa eksklusif langsung terhadap blob tersebut untuk waktu yang singkat (misalnya, 15 detik). Untuk setiap sewa aplikasi diberikan, itu akan dapat menggunakan kapasitas partisi itu. Aplikasi kemudian perlu melacak waktu sewa sehingga, ketika berakhir, ia dapat berhenti menggunakan kapasitas yang diberikannya. Saat menerapkan pola ini, Anda akan sering ingin setiap proses mencoba menyewa partisi acak ketika membutuhkan kapasitas.
Untuk lebih mengurangi latensi, Anda mungkin mengalokasikan sejumlah kecil kapasitas eksklusif untuk setiap proses. Sebuah proses kemudian hanya akan berusaha untuk mendapatkan sewa pada kapasitas bersama jika perlu melebihi kapasitas yang dipesan.
Sebagai alternatif untuk Azure Storage, Anda juga dapat menerapkan sistem manajemen sewa semacam ini menggunakan teknologi seperti Zookeeper, Consul, etcd, Redis/Redsync, dan lainnya.
Masalah dan pertimbangan
Pertimbangkan poin-poin berikut saat memutuskan cara menerapkan pola ini:
- Sementara pola pembatas tarif dapat mengurangi jumlah kesalahan throttling, aplikasi Anda masih perlu menangani kesalahan throttling dengan benar yang mungkin terjadi.
- Jika aplikasi Anda memiliki beberapa aliran kerja yang mengakses layanan terbatas yang sama, Anda harus mengintegrasikan semuanya ke dalam strategi pembatasan tarif Anda. Misalnya, Anda mungkin mendukung pemuatan rekaman massal ke dalam database tetapi juga mengkueri untuk rekaman dalam database yang sama. Anda dapat mengelola kapasitas dengan memastikan semua aliran kerja terjaga keamanannya melalui mekanisme pembatas tarif yang sama. Atau, Anda dapat memesan kumpulan kapasitas terpisah untuk setiap aliran kerja.
- Layanan yang dibatasi dapat digunakan dalam beberapa aplikasi. Dalam beberapa kasus — tetapi tidak semua — dimungkinkan untuk mengkoordinasikan penggunaan itu (seperti yang ditunjukkan di atas). Jika Anda mulai melihat jumlah kesalahan throttling yang lebih besar dari yang diharapkan, ini mungkin merupakan tanda pertentangan antar aplikasi yang mengakses layanan. Jika demikian, Anda mungkin perlu mempertimbangkan untuk sementara mengurangi throughput yang dikenakan oleh mekanisme pembatasan tarif Anda sampai penggunaan dari aplikasi lain menurun.
Kapan menggunakan pola ini
Gunakan pola ini untuk:
- Kurangi kesalahan throttling yang diangkat oleh layanan throttle terbatas.
- Kurangi lalu lintas dibandingkan dengan percobaan ulang yang naif pada pendekatan kesalahan.
- Kurangi konsumsi memori dengan mengantri catatan hanya ketika ada kapasitas untuk memprosesnya.
Desain beban kerja
Arsitek harus mengevaluasi bagaimana pola Pembatasan Tarif dapat digunakan dalam desain beban kerja mereka untuk mengatasi tujuan dan prinsip yang tercakup dalam pilar Azure Well-Architected Framework. Contohnya:
Pilar | Bagaimana pola ini mendukung tujuan pilar |
---|---|
Keputusan desain keandalan membantu beban kerja Anda menjadi tahan terhadap kerusakan dan untuk memastikan bahwa keputusan tersebut pulih ke status berfungsi penuh setelah kegagalan terjadi. | Taktik ini melindungi klien dengan mengakui dan menghormati batasan dan biaya berkomunikasi dengan layanan ketika layanan ingin menghindari penggunaan yang berlebihan. - RE:07 Pelestarian Mandiri |
Seperti halnya keputusan desain apa pun, pertimbangkan tradeoff terhadap tujuan pilar lain yang mungkin diperkenalkan dengan pola ini.
Contoh
Contoh aplikasi berikut memungkinkan pengguna untuk mengirimkan berbagai jenis catatan ke API. Ada prosesor pekerjaan yang unik untuk setiap jenis catatan yang melakukan langkah-langkah berikut:
- Validasi
- Pengayaan
- Penyisipan rekaman ke dalam database
Semua komponen aplikasi (API, prosesor pekerjaan A, dan prosesor pekerjaan B) adalah proses terpisah yang dapat diskalakan secara independen. Proses tidak secara langsung berkomunikasi satu sama lain.
Diagram ini menggabungkan alur kerja berikut:
- Pengguna mengirimkan 10.000 catatan tipe A ke API.
- API mengantri 10.000 rekaman tersebut di Antrian A.
- Pengguna mengirimkan 5.000 rekaman tipe B ke API.
- API mengantri 5.000 rekaman tersebut di Antrian B.
- Job Processor A melihat Queue A memiliki catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 2.
- Job Processor B melihat Queue B memiliki catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 2.
- Job Processor A gagal mendapatkan sewa.
- Job Processor B mendapatkan sewa pada blob 2 selama 15 detik. Sekarang dapat menilai permintaan batas ke database pada tingkat 100 per detik.
- Job Processor B dequeues 100 catatan dari Antrian B dan menulisnya.
- Satu detik berlalu.
- Job Processor A melihat Queue A memiliki lebih banyak catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 6.
- Job Processor B melihat Queue B memiliki lebih banyak catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 3.
- Job Processor A mendapatkan sewa pada blob 6 selama 15 detik. Sekarang dapat menilai permintaan batas ke database pada tingkat 100 per detik.
- Job Processor B mendapatkan sewa pada blob 3 selama 15 detik. Sekarang dapat menilai permintaan batas ke database pada tingkat 200 per detik. (Ini juga memegang sewa untuk blob 2.)
- Job Processor A dequeues 100 catatan dari Antrian A dan menulisnya.
- Job Processor B dequeues 200 catatan dari Antrian B dan menulisnya.
- Satu detik berlalu.
- Job Processor A melihat Queue A memiliki lebih banyak catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 0.
- Job Processor B melihat Queue B memiliki lebih banyak catatan dan mencoba untuk mendapatkan sewa eksklusif pada blob 1.
- Job Processor A mendapatkan sewa pada blob 0 selama 15 detik. Sekarang dapat menilai permintaan batas ke database pada tingkat 200 per detik. (Ini juga memegang sewa untuk blob 6.)
- Job Processor B mendapatkan sewa pada blob 1 selama 15 detik. Sekarang dapat menilai permintaan batas ke database pada tingkat 300 per detik. (Ini juga memegang sewa untuk blob 2 dan 3.)
- Job Processor A dequeues 200 catatan dari Antrian A dan menulisnya.
- Job Processor B dequeues 300 catatan dari Antrian B dan menulisnya.
- Dan seterusnya...
Setelah 15 detik, satu atau kedua pekerjaan masih belum akan selesai. Ketika sewa berakhir, prosesor juga harus mengurangi jumlah permintaan yang dequeues dan ditulis.
Implementasi pola ini tersedia dalam bahasa pemrograman yang berbeda:
Sumber daya terkait
Pola dan panduan berikut mungkin relevan saat menerapkan pola ini:
- Pembatasan. Pola pembatas tarif yang dibahas di sini biasanya diterapkan sebagai respons terhadap layanan yang dibatasi.
- Coba lagi. Ketika permintaan untuk layanan yang dibatasi menghasilkan kesalahan throttling, umumnya tepat untuk mencoba kembali setelah interval yang sesuai.
Queue-Based Load Leveling serupa tetapi berbeda dari pola Batas Tarif dalam beberapa cara utama:
- Pembatasan tarif tidak perlu menggunakan antrean untuk mengelola beban, tetapi perlu menggunakan layanan pesan yang tahan lama. Misalnya, pola pembatasan tarif dapat menggunakan layanan seperti Apache Kafka atau Azure Event Hubs.
- Pola pembatas tarif memperkenalkan konsep sistem pengecualian bersama terdistribusi pada partisi, yang memungkinkan Anda mengelola kapasitas untuk beberapa proses yang tidak terkoordinasi yang berkomunikasi dengan layanan throttle yang sama.
- Pola queue-based load leveling berlaku kapan saja ada ketidakcocokan kinerja antara layanan atau untuk meningkatkan ketahanan. Ini menjadikannya pola yang lebih luas daripada membatasi tarif, yang lebih khusus berkaitan dengan mengakses layanan yang dibatasi secara efisien.