Precompile Rails asset trên nhiều server
Rails
33
Asset Pipeline
1
Capistrano
3
White

Cẩm Huỳnh viết ngày 19/04/2016

Giới thiệu Asset Pipeline

Asset Pipeline là một chức năng khá "hay" :trollface: của Rails, được xây dựng dựa trên Sprockets, giúp chúng ta nén và hợp nhất các assets (Javascript & CSS, hình ảnh) thành một file duy nhất (application.js, application.css, v.v.), ngoài ra nó còn giúp tạo ra fingerprint cho từng file asset để tối ưu hóa cache ở phía client.

Cách sử dụng thì vô cùng đơn giản.

# Ví dụ trong view

= image_tag 'logo.png' 
#=> <img src="/assets/logo-asdf897868sdfasd7f687623.png" alt="" />

Bài toán deploy được đặt ra

Giả sử ta có một ứng dụng Rails được triển khai trên ba server: hai web server để handle HTTP requests và một worker server để chạy những tác vụ chạy nền (gửi emails, cache dữ liệu, backup data), và cả ba server đều cần dùng đến static assets (email templates, file đính kèm, vv). Nếu asset trên server không được precompile, bạn sẽ không lấy được finger print của nó.

Cách làm thông thường là dùng capistrano-rails và gắn thêm cho mỗi server 1 cái role web trong config/deploy/<environment>.rbcapistrano-rails sẽ giúp bạn precompile assets trên cả ba server đó.

# Production server
server 'xxx.xxx.xxx', user: 'deployer', roles: %w{app web}
server 'yyy.yyy.yyy', user: 'deployer', roles: %w{app web}

# Worker server
server 'zzz.zzz.zzz', user: 'deployer', roles: %w{worker web}

# asset role mặc định của capistrano-rails là web.

Tuy nhiên cách làm trên vẫn có một số hạn chế:

  • Asset Precompilation là một quá trình ngốn RAM và khá chậm.
  • Hoang phí .. "dung lượng ổ cứng" :trollface:, worker server của bạn hoàn toàn không serve những assets đó, assets chỉ được tạo ra để lấy finger print.
  • Nếu bạn dùng những giải pháp CDN như CloudFront, thì precompile cả đống assets trên cả hai web server là vô ích.

Nếu ta chỉ precompile asset một lần, thay vì là ba, thì sẽ vừa tăng tốc độ deploy, vừa bớt tốn tài nguyên tính toán phiền phức.

Một chút về fingerprint trong Asset Pipeline

Fingerprint của mỗi file được sinh ra từ nội dung của file đó, nên khi nội dụng file thay đổi, fingerprint cũng sẽ thay đổi theo. Tuy nhiên để tối ưu hóa tốc độ thì sau mỗi lần precompile, Sprockets sẽ cache lại tất cả fingerprint vào trong file .sprockets-manifest-<random>.json

Một số điểm nhấn:

  • Fingerprint của asset sẽ giống nhau nếu nội dụng file giống nhau, dù trên bất kì server nào.
  • Khi bạn hỏi fingerprint của một file nào đó, Sprockets không quan tâm có file đó hay không, mà nó sẽ hỏi file manifest đó.

Suy ra, câu trả lời của câu hỏi ở trên là: Bạn chỉ cần có file manifest là đủ.

Viết code

Nói thì dài dòng nhưng mà làm thì rất đơn giản, và có thể làm theo nhiều cách.

  • Precompile asset trên một server nào đó, download manifest về local, rồi upload nó lên những server nào cần.
  • Precompile assets trên máy local, rồi upload nó lên những server nào cần.
  • Precompile asset trên một server nào đó, rồi dùng rsync để sync file manifest cho những server nào cần.
  • ...

Vì khá làm biếng nên mình sẽ dùng Rsync.

Chú ý: Code được viết theo kiểu mã giả (theo cú pháp của Capistrano 3.x), đồng thời chưa được test, chỉ phù hợp để tham khảo, cân nhắc trước khi sử dụng.

# config/deploy.rb

set :manifest_roles, [:web, :worker]

namespace :assets do
  task :sync_manifest do
    on roles(fetch(:manifest_roles)) do
      execute :rsync, "-a -m --delete --include='.sprockets-manifest-*.json' --include='*/' --exclude='*' deployer@xxx:/path/to/your/manifest /path/to/your/manifest"
    end
  end
end

# Hook tác vụ sync file manifest của chúng ta vào sự kiện sau khi compile assets và sau khi rollback assets.

after 'deploy:compile_assets', 'assets:sync_manifest'
after 'deploy:rollback_assets', 'assets:sync_manifest'

Kết luận

Bài viết hơi dài dòng và cảm ơn các bạn đã đọc.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Cẩm Huỳnh

45 bài viết.
426 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
50 5
image cover]imgcover] “Make it work, make it right, make it fast.” Bạn vừa viết xong một ứng dụng web :tada:. Mọi thứ chạy ổn. Code cũng đã được...
Cẩm Huỳnh viết 23 ngày trước
50 5
White
43 9
(Ảnh) Vì sao lại là Bật Đèn? Ai từng đọc qua Tắt Đèn hẳn đã biết tác phẩm được kết thúc bằng tình huống: Buông tay, chị vội choàng dậy, mở cửa...
Cẩm Huỳnh viết hơn 1 năm trước
43 9
White
41 25
Vừa rồi mình vừa tiết kiệm được $5 mỗi tháng sau khi migrate cái (Link) từ Digital Ocean sang Heroku Free Dyno. (Ảnh) Kết quả thật mĩ mãn vì hầu ...
Cẩm Huỳnh viết hơn 1 năm trước
41 25
Bài viết liên quan
White
21 3
Giao diện lập trình ứng dụng, còn gọi là API (Application Programming Interface) là chương trình cho phép người dùng sử dụng các phương thức của mộ...
chuong2v viết hơn 3 năm trước
21 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
45 bài viết.
426 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!