Build Terdistribusi

Laporkan masalah Lihat sumber

Jika Anda memiliki codebase yang besar, rantai dependensi bisa menjadi sangat dalam. Biner sederhana pun sering kali dapat bergantung pada puluhan ribu target build. Pada skala ini, tidak mungkin untuk menyelesaikan build dalam waktu yang wajar di satu komputer: tidak ada sistem build yang dapat menghindari hukum dasar fisika yang diberlakukan pada hardware mesin. Satu-satunya cara untuk membuatnya berfungsi adalah dengan sistem build yang mendukung build terdistribusi, dengan unit pekerjaan yang dilakukan oleh sistem tersebar di sejumlah mesin yang arbitrer dan skalabel. Dengan asumsi bahwa kita telah memecah pekerjaan sistem menjadi unit-unit yang cukup kecil (akan dibahas lebih lanjut nanti), hal ini akan memungkinkan kita menyelesaikan build apa pun dari ukuran apa pun secepat yang bersedia kami bayar. Skalabilitas ini merupakan hal penting yang telah kami upayakan dengan menentukan sistem build berbasis artefak.

Penyimpanan cache jarak jauh

Jenis build terdistribusi yang paling sederhana adalah yang hanya memanfaatkan cache jarak jauh, seperti ditunjukkan pada Gambar 1.

Build terdistribusi dengan cache jarak jauh

Gambar 1. Build terdistribusi yang menampilkan penyimpanan cache jarak jauh

Setiap sistem yang menjalankan build, termasuk workstation developer dan sistem continuous integration, membagikan referensi ke layanan cache jarak jauh yang umum. Layanan ini dapat berupa sistem penyimpanan jangka pendek lokal yang cepat seperti Redis atau layanan cloud seperti Google Cloud Storage. Setiap kali pengguna perlu membuat artefak, baik secara langsung maupun sebagai dependensi, sistem akan terlebih dahulu memeriksa dengan cache jarak jauh untuk melihat apakah artefak tersebut sudah ada di sana. Jika demikian, Asisten dapat mendownload artefak, bukan mem-build-nya. Jika tidak, sistem akan mem-build artefak itu sendiri dan mengupload hasilnya kembali ke cache. Artinya, dependensi tingkat rendah yang tidak sering berubah dapat dibangun sekali dan digunakan bersama oleh pengguna, sehingga tidak perlu dibuat ulang oleh setiap pengguna. Di Google, banyak artefak yang ditampilkan dari cache, bukan dibuat dari awal, sehingga sangat mengurangi biaya menjalankan sistem build.

Agar sistem caching jarak jauh berfungsi, sistem build harus menjamin bahwa build sepenuhnya dapat direproduksi. Artinya, untuk target build apa pun, set input ke target tersebut harus dapat ditentukan sehingga kumpulan input yang sama akan menghasilkan output yang sama persis pada mesin apa pun. Ini adalah satu-satunya cara untuk memastikan bahwa hasil download artefak sama dengan hasil pembuatannya sendiri. Perlu diperhatikan bahwa cara ini mengharuskan setiap artefak dalam cache dikunci pada target dan hash inputnya. Dengan begitu, engineer yang berbeda dapat membuat modifikasi yang berbeda pada target yang sama secara bersamaan, dan cache jarak jauh akan menyimpan semua artefak yang dihasilkan dan menyajikannya dengan tepat tanpa konflik.

Tentu saja, agar ada manfaat dari cache jarak jauh, mendownload artefak harus lebih cepat daripada mem-build-nya. Hal ini tidak selalu terjadi, terutama jika server cache jauh dari mesin yang melakukan build. Jaringan dan sistem build Google disesuaikan dengan cermat agar dapat membagikan hasil build dengan cepat.

Eksekusi jarak jauh

Pembuatan cache jarak jauh bukanlah build terdistribusi yang sesungguhnya. Jika cache hilang atau jika Anda membuat perubahan tingkat rendah yang mengharuskan semuanya dibangun ulang, Anda masih harus menjalankan seluruh build secara lokal di komputer Anda. Tujuan sebenarnya adalah mendukung eksekusi jarak jauh, yang memungkinkan pekerjaan aktual dalam melakukan build dapat tersebar ke berapa pun jumlah pekerja. Gambar 2 menunjukkan sistem eksekusi jarak jauh.

Sistem eksekusi jarak jauh

Gambar 2. Sistem eksekusi jarak jauh

Alat build yang berjalan pada setiap mesin pengguna (pengguna adalah engineer manusia atau sistem build otomatis) mengirim permintaan ke master build pusat. Master build membagi permintaan ke dalam tindakan komponennya dan menjadwalkan eksekusi tindakan tersebut pada kumpulan pekerja yang skalabel. Setiap pekerja melakukan tindakan yang diminta dengan input yang ditentukan oleh pengguna dan menulis artefak yang dihasilkan. Artefak ini dibagikan di seluruh mesin lain yang menjalankan tindakan yang mengharuskannya hingga output akhir dapat diproduksi dan dikirim ke pengguna.

Bagian tersulit dari penerapan sistem semacam ini adalah mengelola komunikasi antara pekerja, master, dan mesin lokal pengguna. Pekerja mungkin bergantung pada artefak perantara yang dihasilkan oleh pekerja lain, dan output akhir harus dikirim kembali ke mesin lokal pengguna. Untuk melakukannya, kita dapat membuat di atas cache terdistribusi yang dijelaskan sebelumnya dengan meminta setiap pekerja menulis hasilnya ke dan membaca dependensinya dari cache. Master memblokir pekerja agar tidak melanjutkan hingga semua hal yang mereka andalkan telah selesai, dalam hal ini mereka dapat membaca input mereka dari cache. Produk akhir juga di-cache, sehingga memungkinkan mesin lokal mendownloadnya. Perhatikan bahwa kita juga memerlukan cara terpisah untuk mengekspor perubahan lokal di hierarki sumber pengguna sehingga pekerja dapat menerapkan perubahan tersebut sebelum mem-build.

Agar hal ini berfungsi, semua bagian sistem build berbasis artefak yang dijelaskan sebelumnya harus digabungkan. Lingkungan build harus sepenuhnya mendeskripsikan dirinya sendiri sehingga kita dapat menjalankan pekerja tanpa intervensi manusia. Proses build itu sendiri harus sepenuhnya berfungsi sendiri karena setiap langkah mungkin dieksekusi di komputer yang berbeda. Output harus benar-benar deterministik agar setiap pekerja dapat memercayai hasil yang diterimanya dari pekerja lain. Jaminan tersebut sangat sulit untuk diberikan oleh sistem berbasis tugas, sehingga sangat tidak mungkin untuk membangun sistem eksekusi jarak jauh yang andal selain sistem eksekusi jarak jauh yang andal.

Build terdistribusi di Google

Sejak 2008, Google telah menggunakan sistem build terdistribusi yang menggunakan cache jarak jauh dan eksekusi jarak jauh, seperti yang diilustrasikan dalam Gambar 3.

Sistem build tingkat tinggi

Gambar 3. Sistem build terdistribusi Google

Cache jarak jauh Google disebut ObjFS. Layanan ini terdiri dari backend yang menyimpan output build di Bigtable yang didistribusikan ke seluruh mesin produksi kami dan daemon FUSE frontend bernama objfsd yang berjalan di setiap mesin developer. Daemon FUSE memungkinkan engineer menjelajahi output build seolah-olah output tersebut adalah file normal yang disimpan di workstation, tetapi dengan konten file yang didownload secara on demand hanya untuk beberapa file yang diminta langsung oleh pengguna. Penayangan konten file sesuai permintaan akan sangat mengurangi penggunaan jaringan dan disk, dan sistem dapat membangun dua kali lebih cepat dibandingkan saat kita menyimpan semua output build di disk lokal developer.

Sistem eksekusi jarak jauh Google disebut Forge. Klien Forge di Blaze (yang setara internal Bazel) yang disebut Distributor mengirimkan permintaan untuk setiap tindakan ke tugas yang berjalan di pusat data kami yang disebut Scheduler. Scheduler menyimpan cache hasil tindakan, sehingga memungkinkannya untuk segera menampilkan respons jika tindakan telah dibuat oleh pengguna lain dalam sistem. Jika tidak, tindakan akan ditempatkan dalam antrean. Kumpulan besar tugas Executor yang terus-menerus membaca tindakan dari antrean ini, menjalankannya, dan menyimpan hasilnya langsung di Bigtable ObjFS. Hasil ini tersedia bagi eksekutor untuk tindakan mendatang, atau untuk didownload oleh pengguna akhir melalui objfsd.

Hasil akhirnya adalah sistem yang diskalakan untuk mendukung semua build yang dilakukan di Google secara efisien. Dan skala build Google benar-benar masif: Google menjalankan jutaan build yang menjalankan jutaan kasus pengujian dan menghasilkan output build berukuran petabyte dari miliaran baris kode sumber setiap harinya. Sistem semacam ini tidak hanya memungkinkan engineer kami membuat codebase yang kompleks dengan cepat, tetapi juga memungkinkan kami mengimplementasikan sejumlah besar alat dan sistem otomatis yang mengandalkan build kami.