Cara menskalakan dari 1 hingga 100 pengguna

Banyak startup yang mengalami hal ini: banyak pengguna baru yang mendaftar setiap hari, dan tim pengembangan berjuang untuk menjaga layanan tetap berjalan.

Ini adalah masalah yang bagus untuk dimiliki, tetapi hanya ada sedikit informasi yang jelas di web tentang cara menskalakan aplikasi web secara hati-hati dari tidak ada menjadi ratusan ribu pengguna. Biasanya terdapat solusi kebakaran atau solusi kemacetan (dan seringkali keduanya). Oleh karena itu, orang menggunakan teknik yang agak klise untuk mengubah proyek amatir mereka menjadi sesuatu yang sangat serius.

Mari kita coba menyaring informasinya dan menuliskan rumus dasarnya. Kami akan meningkatkan skala situs berbagi foto baru kami Graminsta selangkah demi selangkah dari 1 menjadi 100 pengguna.

Mari kita tuliskan tindakan spesifik apa yang perlu dilakukan ketika jumlah penonton bertambah menjadi 10, 100, 1000, 10, dan 000 orang.

1 pengguna: 1 mesin

Hampir setiap aplikasi, baik itu situs web atau aplikasi seluler, memiliki tiga komponen utama:

  • API
  • basis data
  • klien (aplikasi seluler itu sendiri atau situs web)

Basis data menyimpan data persisten. API melayani permintaan ke dan sekitar data ini. Klien mengirimkan data ke pengguna.

Saya sampai pada kesimpulan bahwa akan lebih mudah untuk membicarakan penskalaan aplikasi jika, dari sudut pandang arsitektur, klien dan entitas API benar-benar terpisah.

Saat pertama kali kita mulai membangun sebuah aplikasi, ketiga komponen tersebut dapat dijalankan di server yang sama. Dalam beberapa hal, ini mirip dengan lingkungan pengembangan kami: seorang insinyur menjalankan database, API, dan klien pada mesin yang sama.

Secara teori, kami dapat menerapkannya di cloud pada satu instans DigitalOcean Droplet atau AWS EC2, seperti yang ditunjukkan di bawah ini:
Cara menskalakan dari 1 hingga 100 pengguna
Oleh karena itu, jika ada lebih dari satu pengguna di sebuah situs, hampir selalu masuk akal untuk mendedikasikan lapisan database.

10 pengguna: memindahkan database ke level terpisah

Memisahkan database menjadi layanan terkelola seperti Amazon RDS atau Digital Ocean Managed Database akan bermanfaat bagi kami untuk waktu yang lama. Ini sedikit lebih mahal daripada hosting mandiri pada satu mesin atau instans EC2, tetapi dengan layanan ini Anda mendapatkan banyak ekstensi berguna yang akan berguna di masa depan: pencadangan multi-wilayah, replika baca, otomatis cadangan, dan banyak lagi.

Inilah tampilan sistemnya sekarang:
Cara menskalakan dari 1 hingga 100 pengguna

100 pengguna: memindahkan klien ke level terpisah

Untungnya, pengguna pertama kami sangat menyukai aplikasi kami. Lalu lintas menjadi lebih stabil, jadi inilah saatnya memindahkan klien ke level terpisah. Perlu dicatat bahwa pemisahan entitas adalah aspek kunci dalam membangun aplikasi yang skalabel. Saat satu bagian sistem menerima lebih banyak lalu lintas, kita dapat mempartisinya untuk mengontrol bagaimana layanan diskalakan berdasarkan pola lalu lintas tertentu.

Inilah sebabnya saya suka menganggap klien terpisah dari API. Hal ini membuatnya sangat mudah untuk memikirkan pengembangan untuk berbagai platform: web, web seluler, iOS, Android, aplikasi desktop, layanan pihak ketiga, dll. Semuanya hanyalah klien yang menggunakan API yang sama.

Misalnya, saat ini pengguna kami paling sering meminta untuk merilis aplikasi seluler. Jika Anda memisahkan klien dan entitas API, hal ini menjadi lebih mudah.

Seperti inilah sistemnya:

Cara menskalakan dari 1 hingga 100 pengguna

1000 pengguna: tambahkan penyeimbang beban

Segalanya membaik. Pengguna Graminsta semakin banyak mengunggah foto. Jumlah pendaftarannya pun semakin bertambah. Satu-satunya server API kami kesulitan mengikuti semua lalu lintas. Butuh lebih banyak zat besi!

Penyeimbang beban adalah konsep yang sangat kuat. Ide utamanya adalah kami menempatkan penyeimbang beban di depan API, dan ini mendistribusikan lalu lintas ke masing-masing instans layanan. Inilah cara kami melakukan penskalaan secara horizontal, artinya kami menambahkan lebih banyak server dengan kode yang sama, sehingga meningkatkan jumlah permintaan yang dapat kami proses.

Kami akan menempatkan penyeimbang beban terpisah di depan klien web dan di depan API. Ini berarti Anda dapat menjalankan beberapa instance yang menjalankan kode API dan kode klien web. Penyeimbang beban akan mengarahkan permintaan ke server yang bebannya lebih sedikit.

Di sini kita mendapatkan keuntungan penting lainnya - redundansi. Ketika satu instance gagal (mungkin kelebihan beban atau crash), yang tersisa hanyalah instance lain yang terus merespons permintaan masuk. Jika hanya ada satu contoh yang berfungsi, maka jika terjadi kegagalan, seluruh sistem akan crash.

Penyeimbang beban juga menyediakan penskalaan otomatis. Kita dapat mengonfigurasinya untuk menambah jumlah instance sebelum beban puncak, dan menguranginya saat semua pengguna sedang tidur.

Dengan penyeimbang beban, level API dapat diskalakan hampir tanpa batas waktu, cukup dengan menambahkan instance baru seiring dengan meningkatnya jumlah permintaan.

Cara menskalakan dari 1 hingga 100 pengguna

Catatan. Saat ini sistem kami sangat mirip dengan apa yang ditawarkan oleh perusahaan PaaS seperti Heroku atau Elastic Beanstalk di AWS (itulah sebabnya mereka sangat populer). Heroku menempatkan database pada host terpisah, mengelola penyeimbang beban penskalaan otomatis, dan memungkinkan Anda menghosting klien web secara terpisah dari API. Ini adalah alasan bagus untuk menggunakan Heroku untuk proyek tahap awal atau startup - Anda mendapatkan semua layanan dasar langsung dari kotaknya.

10 pengguna: CDN

Mungkin kita seharusnya melakukan ini sejak awal. Memproses permintaan dan menerima foto baru mulai membebani server kami.

Pada tahap ini, Anda perlu menggunakan layanan cloud untuk menyimpan konten statis - gambar, video, dan banyak lagi (AWS S3 atau Digital Ocean Spaces). Secara umum, API kami harus menghindari penanganan hal-hal seperti menyajikan gambar dan mengunggah gambar ke server.

Keuntungan lain dari cloud hosting adalah CDN (AWS menyebut add-on ini Cloudfront, tetapi banyak penyedia penyimpanan cloud menawarkannya secara langsung). CDN secara otomatis menyimpan gambar kami dalam cache di berbagai pusat data di seluruh dunia.

Meskipun pusat data utama kami mungkin berlokasi di Ohio, jika seseorang meminta gambar dari Jepang, penyedia cloud akan membuat salinan dan menyimpannya di pusat data Jepang mereka. Orang berikutnya yang meminta gambar ini di Jepang akan menerimanya lebih cepat. Hal ini penting ketika kita bekerja dengan file besar, seperti foto atau video, yang membutuhkan waktu lama untuk diunduh dan dikirim ke seluruh dunia.

Cara menskalakan dari 1 hingga 100 pengguna

100 pengguna: menskalakan lapisan data

CDN telah banyak membantu: lalu lintas tumbuh dengan kecepatan penuh. Blogger video terkenal Mavid Mobrick baru saja mendaftar dengan kami dan memposting β€œceritanya”, seperti yang mereka katakan. Berkat penyeimbang beban, penggunaan CPU dan memori di server API tetap rendah (sepuluh instance API berjalan), namun kami mulai mendapatkan banyak waktu tunggu pada permintaan... dari mana datangnya penundaan ini?

Menggali sedikit metriknya, kita melihat bahwa CPU di server database terisi 80-90%. Kita berada pada batasnya.

Menskalakan lapisan data mungkin merupakan bagian tersulit dari persamaan ini. Server API melayani permintaan tanpa kewarganegaraan, jadi kami cukup menambahkan lebih banyak instance API. Hidung mayoritas database tidak dapat melakukan hal ini. Kita akan berbicara tentang sistem manajemen basis data relasional yang populer (PostgreSQL, MySQL, dll.).

caching

Salah satu cara termudah untuk meningkatkan kinerja database kami adalah dengan memperkenalkan komponen baru: lapisan cache. Metode caching yang paling umum adalah penyimpanan rekaman nilai kunci dalam memori, seperti Redis atau Memcached. Sebagian besar cloud memiliki versi terkelola dari layanan berikut: Elasticache di AWS dan Memorystore di Google Cloud.

Cache berguna ketika layanan melakukan banyak panggilan berulang ke database untuk mengambil informasi yang sama. Intinya, kita mengakses database hanya sekali, menyimpan informasi di cache, dan tidak menyentuhnya lagi.

Misalnya, di layanan Graminsta kami, setiap kali seseorang membuka halaman profil bintang Mobrik, server API menanyakan database untuk informasi dari profilnya. Hal ini terjadi lagi dan lagi. Karena informasi profil Mobrik tidak berubah pada setiap permintaan, informasi ini sangat baik untuk cache.

Kami akan menyimpan hasil dari database di Redis dengan kunci user:id dengan masa berlaku 30 detik. Nah kalau ada yang masuk ke profil Mobrik, kita cek dulu di Redis, dan kalau datanya ada, kita tinggal transfer langsung dari Redis. Sekarang permintaan ke profil paling populer di situs ini praktis tidak memuat database kami.

Keuntungan lain dari sebagian besar layanan caching adalah lebih mudah untuk diskalakan dibandingkan server database. Redis memiliki mode Klaster Redis bawaan. Mirip dengan penyeimbang beban1, ini memungkinkan Anda mendistribusikan cache Redis ke beberapa mesin (ke ribuan server jika diperlukan).

Hampir semua aplikasi skala besar menggunakan caching; ini merupakan bagian integral dari API cepat. Pemrosesan kueri yang lebih cepat dan kode yang lebih produktif semuanya penting, namun tanpa cache hampir tidak mungkin untuk menskalakan layanan ke jutaan pengguna.

Baca Replika

Ketika jumlah kueri ke database telah meningkat pesat, satu hal lagi yang dapat kita lakukan adalah menambahkan replika baca di sistem manajemen database. Dengan layanan terkelola yang dijelaskan di atas, hal ini dapat dilakukan dalam satu klik. Replika baca akan tetap ada di database utama dan tersedia untuk pernyataan SELECT.

Inilah sistem kami sekarang:

Cara menskalakan dari 1 hingga 100 pengguna

Langkah selanjutnya

Saat aplikasi terus berkembang, kami akan terus memisahkan layanan untuk menskalakannya secara mandiri. Misalnya, jika kita mulai menggunakan Websockets, maka masuk akal untuk menarik kode pemrosesan Websockets ke layanan terpisah. Kami dapat menempatkannya pada instance baru di belakang penyeimbang beban kami sendiri, yang dapat ditingkatkan dan diturunkan skalanya berdasarkan koneksi Websockets terbuka dan berapa pun jumlah permintaan HTTP.

Kami juga akan terus melawan pembatasan di tingkat basis data. Pada tahap inilah saatnya mempelajari partisi dan sharding database. Kedua pendekatan tersebut memerlukan overhead tambahan, namun memungkinkan Anda menskalakan database hampir tanpa batas.

Kami juga ingin memasang layanan pemantauan dan analitik seperti New Relic atau Datadog. Ini akan membantu Anda mengidentifikasi kueri yang lambat dan memahami di mana perbaikan diperlukan. Saat kami melakukan penskalaan, kami ingin fokus untuk menemukan hambatan dan menghilangkannyaβ€”sering kali menggunakan beberapa ide dari bagian sebelumnya.

sumber

Postingan ini terinspirasi oleh salah satu postingan favorit saya tentang skalabilitas tinggi. Saya ingin membuat artikel ini sedikit lebih spesifik untuk tahap awal proyek dan melepaskannya dari satu vendor. Pastikan untuk membaca jika Anda tertarik dengan topik ini.

Catatan kaki

  1. Meskipun serupa dalam hal distribusi beban di beberapa instans, implementasi mendasar dari klaster Redis sangat berbeda dari penyeimbang beban. [kembali]

Cara menskalakan dari 1 hingga 100 pengguna

Sumber: www.habr.com

Tambah komentar