Kelahiran platform



Dunia telah berubah. Saya merasakannya di dalam air, melihatnya di tanah, merasakannya di udara. Segala sesuatu yang pernah ada hilang, dan tidak ada lagi yang mengingatnya.
Dari film "The Lord of the Rings: The Fellowship of the Ring"

Ada 100500 artikel dan laporan di Internet dengan topik "bagaimana kita melihat monolit", dan saya tidak punya keinginan untuk menulis yang lain. Saya mencoba untuk melangkah lebih jauh dan mengatakan bagaimana perubahan teknologi menyebabkan munculnya produk yang sama sekali baru (spoiler: kami menulis kotak, dan menulis platform). Artikel ini sebagian besar merupakan ulasan, tanpa rincian teknis. Detail akan muncul nanti.

Ini akan tentang situs panel kontrol dan server Vepp. Ini adalah produk sistem ISP di mana saya memimpin pengembangan. Baca tentang kemampuan panel baru di artikel lain , di sini - hanya tentang teknologi. Tapi pertama-tama, seperti biasa, sedikit sejarah.

Bagian 1. Anda perlu mengubah sesuatu


Perusahaan kami telah menulis perangkat lunak untuk otomatisasi layanan hosting selama lebih dari 15 tahun. Selama masa ini, beberapa generasi produk kami telah berubah. Ketika kami beralih dari yang kedua ke yang keempat, kami mengubah Perl menjadi C ++ dan memulai penjualan perangkat lunak kami secara gratis ... Ketika kami beralih dari yang keempat ke yang kelima, dalam mengejar kecepatan kami beralih dari aplikasi single-threaded ke multi-threaded (dari monolit yang berisi semua produk kami ke kerangka kerja).

Tapi, tidak hanya kami yang berubah, pelanggan dan pesaing kami juga berubah. Jika 10-15 tahun yang lalu pemilik situs berpengalaman secara teknis (yang lain sangat tertarik dengan Internet), sekarang ini bisa menjadi orang yang tidak terhubung dengan TI dengan cara apa pun. Ada banyak solusi yang bersaing. Di bawah kondisi seperti itu, hanya mengerjakan suatu produk tidak cukup, perlu bahwa itu mudah dan menyenangkan untuk digunakan.

Desain ulang heroik


Perubahan ini telah menjadi hal yang paling nyata. Selama ini, antarmuka produk kami tetap tidak berubah dan disatukan. Kami sudah menulis tentang ini secara terpisah - pandangan dari UX. Pada produk generasi kelima, API menentukan tampilan formulir dan daftar. Yang, di satu sisi, memungkinkan untuk mengimplementasikan banyak hal tanpa melibatkan pengembang frontend, di sisi lain, hal itu memunculkan panggilan kompleks yang sangat kompleks, kadang-kadang memengaruhi sebagian besar sistem, dan sangat membatasi kemampuan untuk mengubah antarmuka. Bagaimanapun, perubahan apa pun pasti merupakan perubahan dalam API. Dan itu saja, halo ke integrasi!

Misalnya: membuat pengguna di ISPmanager juga dapat mengarah pada pembuatan pengguna FTP, domain email, kotak surat, catatan DNS, situs. Dan semua ini dilakukan secara atom, dan karenanya memblokir perubahan dalam komponen yang terdaftar sampai operasi selesai.

Di API baru, kami beralih ke operasi atom kecil dan sederhana, dan pengembang Frontend dibiarkan dengan tindakan kompleks yang kompleks. Ini memungkinkan Anda untuk mengimplementasikan antarmuka yang kompleks dan mengubahnya tanpa memengaruhi API inti dan, karenanya, tanpa memutus integrasi.

Untuk pengembang frontend, kami telah menerapkan mekanisme eksekusi permintaan batch dengan kemampuan untuk melakukan tindakan terbalik jika terjadi kesalahan. Seperti yang ditunjukkan oleh praktik, dalam kebanyakan kasus, kueri kompleks adalah permintaan untuk membuat sesuatu, dan kreasi cukup mudah dibatalkan dengan melakukan penghapusan.

Kurangi waktu respons dan pemberitahuan instan


Kami menolak permintaan modifikasi yang lama. Versi sebelumnya dari produk kami dapat bertahan lama, mencoba memenuhi permintaan pengguna. Kami memutuskan bahwa untuk setiap tindakan lebih sulit untuk mengubah data dalam database secara sepele, kami akan membuat tugas dalam sistem dan merespons klien secepat mungkin, memungkinkannya untuk terus bekerja dan tidak melihat proses pemuatan tanpa akhir.

Tetapi bagaimana jika Anda membutuhkan hasilnya, apa yang disebut di sini dan sekarang? Saya pikir banyak orang yang akrab dengan situasi ketika Anda memuat ulang halaman berulang-ulang dengan harapan operasi akan segera berakhir.

Dalam produk generasi baru, kami menggunakan websocket untuk pengiriman acara instan.

Implementasi pertama menggunakan longpoll, tetapi pengembang frontend tidak nyaman dengan pendekatan ini.

Komunikasi internal HTTP


HTTP sebagai transportasi dimenangkan. Sekarang, dalam bahasa apa pun, server HTTP diimplementasikan dalam hitungan detik (jika Anda google, lalu dalam hitungan menit). Bahkan secara lokal, lebih mudah untuk membentuk permintaan HTTP daripada memblokir protokol Anda.

Pada generasi sebelumnya, ekstensi (plugin) adalah aplikasi yang, jika perlu, diluncurkan sebagai CGI. Tetapi untuk menulis ekstensi yang berumur panjang, saya harus berusaha keras: menulis plug-in di C ++ dan membangunnya kembali dengan setiap pembaruan produk.

Oleh karena itu, pada generasi keenam, kami beralih ke interaksi internal melalui HTTP, dan ekstensi, pada kenyataannya, menjadi server WEB kecil.

API baru (tidak cukup REST)


Dalam produk generasi sebelumnya, kami melewati semua parameter melalui GET atau POST. Jika tidak ada masalah khusus dengan GET - ukurannya kecil, maka dalam kasus POST tidak ada cara untuk memeriksa akses atau mengarahkan permintaan sampai benar-benar dibaca.

Bayangkan betapa menyedihkannya: untuk menerima beberapa ratus megabyte atau gigabytes, dan kemudian menemukan bahwa mereka dituangkan oleh pengguna yang tidak sah atau bahwa mereka sekarang harus ditransfer ke server itu!

Sekarang nama fungsi diteruskan dalam URI, dan otorisasi secara eksklusif di header. Dan ini memungkinkan Anda untuk melakukan sebagian dari cek sebelum membaca badan permintaan.

Selain itu, fungsi API menjadi lebih sederhana. Ya, sekarang kami tidak menjamin keaslian pembuatan pengguna, surat, situs web, dan sejenisnya. Tetapi kami memberikan kesempatan untuk menggabungkan operasi ini seperlunya.

Kami telah menerapkan kemampuan untuk melakukan eksekusi permintaan batch. Bahkan, ini adalah layanan terpisah yang menerima daftar permintaan dan secara berurutan mengeksekusinya. Dia juga dapat memutar kembali operasi yang sudah selesai jika terjadi kesalahan.

SSH umur panjang!


Keputusan lain yang kami buat berdasarkan pengalaman kami sebelumnya adalah bekerja dengan server hanya melalui SSH (bahkan jika itu adalah server lokal). Awalnya, kami bekerja dengan server lokal di VMmanager dan ISPmanager, dan baru setelah itu kami memungkinkan untuk menambahkan yang jauh tambahan. Ini mengarah pada kebutuhan untuk mendukung dua implementasi.

Dan ketika kami menolak untuk bekerja dengan server lokal, alasan terakhir untuk menggunakan perpustakaan asli dari sistem operasi pengguna menghilang. Bersama mereka, kami telah disiksa sejak berdirinya perusahaan. Tidak, perpustakaan asli memiliki kelebihan mereka, tetapi ada lebih banyak kerugian.

Nilai tambah absolut adalah lebih sedikit konsumsi disk dan memori, dan untuk bekerja di dalam VDS ini bisa sangat signifikan. Dari kekurangan - menggunakan perpustakaan yang versinya tidak Anda kontrol dapat menghasilkan hasil yang tidak terduga, yang sangat meningkatkan beban pengembangan dan pengujian. Kelemahan lain adalah ketidakmampuan untuk menggunakan perpustakaan versi terbaru dan C ++ modern (misalnya, pada CentOS 6 bahkan C ++ 11 tidak sepenuhnya didukung).

Kebiasaan lama


Mengubah pendekatan dan beralih ke teknologi baru, kami terus bertindak dengan cara lama. Ini menyebabkan kesulitan.

Topik sensasi dengan layanan microser tidak melewati kami. Kami juga memutuskan untuk membagi aplikasi menjadi komponen layanan yang terpisah. Hal ini memungkinkan untuk memperketat kontrol atas interaksi dan melakukan pengujian setiap bagian dari aplikasi. Dan untuk mengendalikan interaksi lebih erat, kami menaruhnya dalam wadah, yang, bagaimanapun, selalu dapat disatukan dalam satu tumpukan.

Dalam aplikasi monolitik, Anda dapat dengan mudah mengakses hampir semua data. Tetapi bahkan jika Anda membagi produk menjadi beberapa aplikasi dan meninggalkannya di dekat Anda, mereka, sebagai yang hidup, dapat membentuk tautan. Misalnya, dalam bentuk file bersama atau permintaan langsung satu sama lain.

Beralih ke layanan microser tidak mudah. Pola lama โ€œmenulis perpustakaan dan menghubungkannya di mana pun dibutuhkanโ€ telah menghantui kami cukup lama. Misalnya, kami memiliki layanan yang bertanggung jawab untuk melakukan operasi "panjang". Awalnya, ini diimplementasikan sebagai perpustakaan yang terhubung ke aplikasi yang membutuhkannya.

Kebiasaan lain dapat digambarkan sebagai berikut: mengapa menulis layanan lain, jika Anda dapat mengajar yang sudah ada ini. Hal pertama yang kami lihat dari monolit kami adalah mekanisme otorisasi. Tetapi kemudian godaan muncul untuk mendorong semua komponen umum ke dalam layanan ini, seperti dalam COREmanager (kerangka dasar untuk produk generasi kelima).

Bagian 2. Menggabungkan yang tidak kompatibel


Pada awalnya, permintaan membaca dan menulis dilakukan dengan satu proses. Biasanya, permintaan menulis memblokir permintaan, tetapi permintaannya sangat cepat: Saya menulis ke database, membuat tugas, dan menjawab. Dengan permintaan membaca, ceritanya berbeda. Membuat tugas itu sulit. Ini dapat menghasilkan respons yang agak banyak, dan apa yang harus dilakukan dengan jawaban ini jika klien tidak kembali setelah itu? Berapa banyak yang menyimpannya? Tetapi pada saat yang sama, pemrosesan permintaan membaca diparalelkan dengan sempurna. Perbedaan-perbedaan ini menyebabkan masalah dengan memulai kembali proses tersebut. Siklus hidup mereka tidak sesuai!

Kami membagi aplikasi menjadi dua bagian: membaca dan menulis. Benar, segera menjadi jelas bahwa ini sangat tidak nyaman dari sudut pandang pengembangan. Membaca daftar yang Anda lakukan di satu tempat, mengedit di tempat lain. Dan di sini hal utama - jangan lupa untuk memperbaiki yang kedua, jika Anda mengubah yang pertama. Ya, dan beralih di antara file setidaknya mengganggu. Oleh karena itu, kami membuka aplikasi yang berjalan dalam dua mode: membaca dan menulis.

Generasi sebelumnya dari produk kami menggunakan benang secara ekstensif. Tetapi, seperti yang ditunjukkan oleh latihan, mereka tidak menyelamatkan kita banyak. Karena banyaknya kunci, beban pada CPU jarang melebihi 100%. Munculnya sejumlah besar layanan terpisah yang cukup cepat telah memungkinkan untuk meninggalkan multithreading demi pekerjaan asinkron dan single-threaded.

Selama proses pengembangan, kami mencoba menggunakan stream bersama dengan asynchrony (boost :: Asio memungkinkan ini). Tetapi pendekatan ini kemungkinan besar membawa pada proyek Anda semua kekurangan dari kedua pendekatan daripada memberikan keuntungan yang terlihat: Anda harus menggabungkan kebutuhan untuk kontrol ketika mengakses objek bersama dan kesulitan menulis kode asinkron.

Bagian 3. Saat kami menulis kotak, dan menulis platform


Semua layanan diatur dalam wadah dan bekerja dengan server klien dari jarak jauh. Dan mengapa kemudian meletakkan aplikasi di server klien? Itulah pertanyaan yang saya tanyakan kepada manajemen ketika tiba saatnya untuk mengemas produk yang dihasilkan untuk instalasi di server.

Apa itu platform? Pertama, kami menggunakan SaaS, layanan yang berjalan di server kami dan memungkinkan Anda untuk mengonfigurasi server Anda. Jika Anda menggunakan panel kontrol server dan membelinya sendiri - ini adalah solusi untuk Anda. Tapi itu tidak sesuai dengan penyedia: mereka tidak siap untuk memberikan akses ke server klien mereka ke perusahaan pihak ketiga, dan saya mengerti mereka dengan sangat baik. Ini menimbulkan pertanyaan tentang keamanan dan toleransi kesalahan. Oleh karena itu, kami memutuskan untuk memberi mereka seluruh SaaS kami sehingga mereka dapat menggunakannya di rumah. Ini seperti Amazon, yang dapat Anda jalankan di pusat data Anda sendiri dan terhubung ke sistem penagihan Anda. Kami menyebut solusi ini platform.

Penempatan pertama tidak berjalan sangat lancar. Untuk setiap pengguna aktif, kami mengangkat wadah terpisah. Kontainer Docker naik dengan cepat, tetapi penemuan layanan tidak bekerja secara instan: ini tidak dimaksudkan untuk menaikkan / menghentikan kontainer secara dinamis dalam sedetik. Dan dari saat kenaikan hingga saat layanan dapat digunakan, terkadang beberapa menit berlalu !!!

Saya sudah menulis bahwa pengguna hosting telah banyak berubah selama dekade terakhir. Sekarang bayangkan: ia membeli hosting dari Anda - dan mendapatkan akses ke shell. WTF?!?! Untuk menggunakannya, pertama-tama ia harus menemukan beberapa klien SSH (di Windows ini dapat menjadi masalah - secara default tidak ada klien, saya biasanya diam tentang klien seluler).

Setelah dia masih bisa masuk ke konsol, dia perlu menginstal panel. Dan operasi ini juga tidak cepat. Dan jika ada yang salah? Misalnya, RosKomNadzor dapat memblokir server tempat paket untuk OS Anda diunduh. Dengan kesalahan seperti itu, pengguna akan dibiarkan bertatap muka.



Anda mungkin berpendapat bahwa dalam kebanyakan kasus pengguna menerima panel yang sudah diinstal oleh hoster, dan hal di atas tidak berlaku untuknya. Mungkin Tetapi panel yang berjalan di server mengkonsumsi sumber daya yang Anda bayar (mengambil ruang disk, memakan prosesor dan memori Anda). Kinerjanya secara langsung tergantung pada kinerja server (server crash - panel crash).

Mungkin masih ada yang tidak menggunakan panel dan berpikir: ini bukan urusan saya. Tapi mungkin di server Anda, jika Anda punya, semacam panel masih berdiri dan memakan sumber daya, tetapi Anda tidak menggunakannya?

"Jadi ini sangat luar biasa, Anda membantu kami menjual sumber daya," kata tuan rumah Rusia. Lainnya menambahkan: "Mengapa kita menghabiskan sumber daya kita menyebarkan platform yang mengkonsumsi lebih dari panel yang berdiri sendiri?"

Ada beberapa jawaban untuk pertanyaan ini.
  1. Kualitas layanan ditingkatkan: Anda dapat mengontrol versi panel - perbarui dengan cepat ketika fungsionalitas baru muncul atau kesalahan terdeteksi; Anda dapat mengumumkan saham tepat di panel.
  2. Pada skala infrastruktur, Anda menghemat disk, memori, dan prosesor, karena beberapa proses diluncurkan hanya untuk melayani pengguna aktif, dan beberapa melayani banyak klien secara bersamaan.
  3. Dukungan tidak perlu menganalisis apakah perilaku adalah fitur versi panel tertentu atau kesalahan. Ini menghemat waktu.

Banyak lagi pelanggan kami membeli lisensi dalam kemasan dan kemudian menyulapnya, menjualnya kembali kepada pelanggan mereka. Tidak perlu lagi melakukan ini, pada prinsipnya, pekerjaan yang tidak berarti. Lagi pula, sekarang ini adalah satu produk.

Selain itu, kami mendapat kesempatan untuk menggunakan solusi berat, menawarkan fungsionalitas yang sebelumnya tidak dapat diakses. Misalnya, layanan untuk mendapatkan tangkapan layar suatu situs membutuhkan peluncuran kromium tanpa kepala. Saya tidak berpikir bahwa pengguna akan sangat senang jika, karena operasi seperti itu, ia kehabisan memori dan menembak dirinya sendiri, katakanlah, MySQL.

Sebagai kesimpulan, saya ingin mencatat bahwa kita belajar dari pengalaman orang lain dan secara aktif mengembangkan pengalaman kita sendiri. Penebangan, buruh pelabuhan, penemuan layanan, semua jenis penundaan, percobaan ulang dan antrian ... Sekarang Anda tidak ingat semua yang harus Anda kuasai atau temukan kembali. Semua ini tidak membuat pengembangan lebih mudah, tetapi membuka peluang baru dan membuat pekerjaan kami lebih menarik.

Ceritanya belum berakhir, tetapi apa yang terjadi dapat dilihat di situs web Vepp .

Source: https://habr.com/ru/post/id467973/


All Articles