Khi bạn có một cơ sở mã lớn, các chuỗi phần phụ thuộc có thể trở nên rất sâu. Ngay cả các tệp nhị phân đơn giản cũng có thể phụ thuộc vào hàng chục nghìn mục tiêu xây dựng. Ở quy mô này, bạn không thể hoàn tất quá trình tạo trong một khoảng thời gian hợp lý trên một máy duy nhất: không có hệ thống tạo nào có thể vượt qua các quy luật vật lý cơ bản được áp dụng cho phần cứng của máy. Cách duy nhất để thực hiện việc này là sử dụng một hệ thống xây dựng hỗ trợ các bản dựng phân tán, trong đó các đơn vị công việc mà hệ thống thực hiện được trải rộng trên một số lượng máy tuỳ ý và có thể mở rộng. Giả sử chúng ta đã chia công việc của hệ thống thành các đơn vị đủ nhỏ (sẽ nói thêm về vấn đề này sau), điều này sẽ cho phép chúng ta hoàn thành mọi bản dựng có kích thước bất kỳ nhanh nhất có thể nếu chúng ta sẵn sàng trả tiền. Khả năng mở rộng này là mục tiêu mà chúng tôi hướng đến bằng cách xác định một hệ thống xây dựng dựa trên cấu phần phần mềm.
Lưu vào bộ nhớ đệm từ xa
Loại bản dựng phân tán đơn giản nhất là loại chỉ tận dụng hoạt động lưu vào bộ nhớ đệm từ xa, như minh hoạ trong Hình 1.
Hình 1 Một bản dựng phân tán cho thấy tính năng lưu vào bộ nhớ đệm từ xa
Mọi hệ thống thực hiện các bản dựng, bao gồm cả máy trạm của nhà phát triển và hệ thống tích hợp liên tục, đều chia sẻ một thông tin tham chiếu đến dịch vụ lưu trữ từ xa chung. Dịch vụ này có thể là một hệ thống lưu trữ ngắn hạn, nhanh chóng và cục bộ như Redis hoặc một dịch vụ đám mây như Google Cloud Storage. Bất cứ khi nào người dùng cần tạo một cấu phần phần mềm, cho dù trực tiếp hay dưới dạng một phần phụ thuộc, hệ thống sẽ kiểm tra trước với bộ nhớ đệm từ xa để xem cấu phần phần mềm đó đã tồn tại ở đó hay chưa. Nếu có, thì nó có thể tải thành phần xuống thay vì tạo thành phần. Nếu không, hệ thống sẽ tự tạo cấu phần phần mềm và tải kết quả lên lại bộ nhớ đệm. Điều này có nghĩa là các phần phụ thuộc cấp thấp không thay đổi thường xuyên có thể được tạo một lần và chia sẻ giữa những người dùng thay vì mỗi người dùng phải tạo lại. Tại Google, nhiều cấu phần phần mềm được phân phát từ bộ nhớ đệm thay vì được tạo từ đầu, giúp giảm đáng kể chi phí chạy hệ thống bản dựng của chúng tôi.
Để hệ thống lưu vào bộ nhớ đệm từ xa hoạt động, hệ thống tạo bản dựng phải đảm bảo rằng các bản dựng hoàn toàn có thể tái tạo. Tức là đối với bất kỳ mục tiêu bản dựng nào, bạn đều có thể xác định tập hợp đầu vào cho mục tiêu đó sao cho cùng một tập hợp đầu vào sẽ tạo ra chính xác cùng một đầu ra trên mọi máy. Đây là cách duy nhất để đảm bảo rằng kết quả tải một cấu phần phần mềm xuống giống với kết quả tự tạo cấu phần phần mềm đó. Xin lưu ý rằng điều này đòi hỏi mỗi cấu phần phần mềm trong bộ nhớ đệm phải được khoá trên cả mục tiêu và hàm băm của các đầu vào. Nhờ đó, các kỹ sư khác nhau có thể sửa đổi khác nhau cho cùng một mục tiêu cùng một lúc và bộ nhớ đệm từ xa sẽ lưu trữ tất cả các cấu phần phần mềm kết quả và phân phát chúng một cách thích hợp mà không xảy ra xung đột.
Tất nhiên, để có thể hưởng lợi từ bộ nhớ đệm từ xa, việc tải một cấu phần phần mềm xuống cần phải nhanh hơn việc tạo cấu phần phần mềm đó. Điều này không phải lúc nào cũng đúng, đặc biệt là nếu máy chủ lưu vào bộ nhớ đệm ở xa máy đang thực hiện bản dựng. Mạng và hệ thống tạo của Google được điều chỉnh cẩn thận để có thể nhanh chóng chia sẻ kết quả tạo.
Thực thi từ xa
Việc lưu vào bộ nhớ đệm từ xa không phải là một bản dựng phân tán thực sự. Nếu mất bộ nhớ đệm hoặc nếu bạn thực hiện một thay đổi ở cấp thấp yêu cầu phải tạo lại mọi thứ, bạn vẫn cần thực hiện toàn bộ quá trình tạo cục bộ trên máy của mình. Mục tiêu thực sự là hỗ trợ việc thực thi từ xa, trong đó công việc thực tế của việc tạo bản dựng có thể được phân phối trên bất kỳ số lượng trình thực thi nào. Hình 2 mô tả một hệ thống thực thi từ xa.
Hình 2. Hệ thống thực thi từ xa
Công cụ tạo chạy trên máy của mỗi người dùng (trong đó người dùng là kỹ sư hoặc hệ thống tạo tự động) sẽ gửi yêu cầu đến một máy chủ tạo chính. Bản dựng chính chia các yêu cầu thành các hành động thành phần và lên lịch thực thi các hành động đó trên một nhóm worker có khả năng mở rộng. Mỗi worker thực hiện các hành động được yêu cầu với dữ liệu đầu vào do người dùng chỉ định và ghi ra các cấu phần phần mềm kết quả. Các cấu phần phần mềm này được chia sẻ trên các máy khác thực hiện những hành động yêu cầu chúng cho đến khi có thể tạo ra đầu ra cuối cùng và gửi cho người dùng.
Phần khó nhất khi triển khai hệ thống như vậy là quản lý hoạt động giao tiếp giữa các worker, master và máy cục bộ của người dùng. Các worker có thể phụ thuộc vào các cấu phần phần mềm trung gian do các worker khác tạo ra và đầu ra cuối cùng cần được gửi lại cho máy cục bộ của người dùng. Để làm việc này, chúng ta có thể xây dựng dựa trên bộ nhớ đệm phân tán được mô tả trước đó bằng cách để mỗi worker ghi kết quả của nó vào và đọc các phần phụ thuộc của nó từ bộ nhớ đệm. Khối chính ngăn các worker tiếp tục cho đến khi mọi thứ mà chúng phụ thuộc vào đã hoàn tất. Trong trường hợp đó, các worker sẽ có thể đọc dữ liệu đầu vào từ bộ nhớ đệm. Sản phẩm cuối cùng cũng được lưu vào bộ nhớ đệm, cho phép thiết bị cục bộ tải sản phẩm đó xuống. Xin lưu ý rằng chúng ta cũng cần một phương thức riêng để xuất các thay đổi cục bộ trong cây nguồn của người dùng để các worker có thể áp dụng những thay đổi đó trước khi tạo.
Để làm được việc này, tất cả các phần của hệ thống xây dựng dựa trên cấu phần phần mềm được mô tả trước đó cần phải kết hợp với nhau. Môi trường tạo bản dựng phải hoàn toàn tự mô tả để chúng ta có thể khởi động các worker mà không cần sự can thiệp của con người. Bản thân các quy trình xây dựng phải hoàn toàn độc lập vì mỗi bước có thể được thực thi trên một máy khác. Đầu ra phải hoàn toàn xác định để mỗi worker có thể tin tưởng kết quả mà worker đó nhận được từ các worker khác. Rất khó để một hệ thống dựa trên tác vụ đưa ra những đảm bảo như vậy, điều này khiến việc xây dựng một hệ thống thực thi từ xa đáng tin cậy trên một hệ thống như vậy gần như là không thể.
Bản dựng được phân phối tại Google
Kể từ năm 2008, Google đã sử dụng một hệ thống bản dựng phân tán sử dụng cả tính năng lưu vào bộ nhớ đệm từ xa và thực thi từ xa, như minh hoạ trong Hình 3.
Hình 3. Hệ thống xây dựng phân tán của Google
Bộ nhớ đệm từ xa của Google có tên là ObjFS. Hệ thống này bao gồm một phần phụ trợ lưu trữ các đầu ra bản dựng trong Bigtable được phân phối trên toàn bộ nhóm máy sản xuất của chúng tôi và một trình nền FUSE giao diện người dùng có tên là objfsd chạy trên máy của mỗi nhà phát triển. Trình nền FUSE cho phép các kỹ sư duyệt xem đầu ra bản dựng như thể đó là các tệp thông thường được lưu trữ trên máy trạm, nhưng nội dung tệp chỉ được tải xuống theo yêu cầu đối với một số ít tệp mà người dùng yêu cầu trực tiếp. Việc phân phát nội dung tệp theo yêu cầu giúp giảm đáng kể cả mức sử dụng mạng và ổ đĩa, đồng thời hệ thống có thể tạo nhanh gấp đôi so với khi chúng tôi lưu trữ tất cả đầu ra bản dựng trên ổ đĩa cục bộ của nhà phát triển.
Hệ thống thực thi từ xa của Google có tên là Forge. Một ứng dụng Forge trong Blaze (tương đương nội bộ của Bazel) có tên là Distributor sẽ gửi yêu cầu cho từng thao tác đến một công việc đang chạy trong các trung tâm dữ liệu của chúng tôi có tên là Scheduler. Trình lập lịch duy trì một bộ nhớ đệm kết quả của hành động, cho phép trả về phản hồi ngay lập tức nếu hành động đó đã được tạo bởi bất kỳ người dùng nào khác của hệ thống. Nếu không, hệ thống sẽ đặt thao tác vào một hàng đợi. Một nhóm lớn các tác vụ của Executor liên tục đọc các thao tác từ hàng đợi này, thực thi các thao tác đó và lưu trữ kết quả trực tiếp trong ObjFS Bigtable. Những kết quả này có sẵn cho các trình thực thi cho các thao tác sau này hoặc để người dùng cuối tải xuống thông qua objfsd.
Kết quả cuối cùng là một hệ thống có thể mở rộng để hỗ trợ hiệu quả tất cả các bản dựng được thực hiện tại Google. Quy mô của các bản dựng của Google thực sự rất lớn: Google chạy hàng triệu bản dựng, thực hiện hàng triệu trường hợp kiểm thử và tạo ra hàng petabyte đầu ra bản dựng từ hàng tỷ dòng mã nguồn mỗi ngày. Hệ thống như vậy không chỉ giúp các kỹ sư của chúng tôi nhanh chóng xây dựng các cơ sở mã phức tạp mà còn cho phép chúng tôi triển khai một số lượng lớn các công cụ và hệ thống tự động dựa trên bản dựng của chúng tôi.