CACHING ON RAILS
Bài đăng này đã không được cập nhật trong 9 năm
Tại sao chúng ta lại sử dụng cache?
- Cache có thể tăng hiệu năng sử dụng của hệ thống
- Cache giảm tải việc truy xuất trực tiếp vào database
- Cache tăng tốc độ truy cập ứng dụng web lên nhiều lần so với việc không sử dụng cache.
- Cache ứng dụng trong Rails web app là một ứng dụng web hoạt động theo hình thức Request và Responce dữ liệu đầu vào là URL và các tham số và kết quả trả về là nội dung HTML..
nếu phân tích một luồng resquest và responce thông thường của ứng dụng web chúng ta có thể mô tả thành các bước như sau:
Request -(1)-> [Controller/Action -(2)-> [[Model -(3)-> DB -(4)]-> View -(5)]] -> Response
Tại mỗi bước thì ứng dụng web có thể trả về kết quả ngay lập tức mà không cần phải tính toán gì nếu như đã có kết quả lưu trữ trong cache trên webserver.
Dựa vào luồng đi của ứng dụng web ta có thể phân cache ra thành 5 loại như sau:
Page: Nguyên cả trang HTML ứng với URL nhất định được lưu vào cache, các truy cập tiếp theo đến cùng URL này nhận được ngay kết quả từ web server. Chương trình không phải tính toán gì, thậm chí không biết là đã có request vì web server không báo.
Action: Chương trình biết là có request, nhưng trả về ngay kết quả mà không cần động vào Model hay View.
Fragment: Chỉ một phần HTML của trang được lưu.
Object: Object nào đó (có thể không phải là chuỗi kí tự HTML) được lưu.
SQL: Khi cùng câu lệnh SQL được gọi đi gọi lại, thì chỉ lệnh đầu tiên được gửi đến DB server
Sử dụng cache trong rails 3
để enable chức năng sử dụng cache trong rails :
- thay đổi config trong file config/deverlopment.rb hoặc môi trường khác như sau:
config.action_controller.perform_caching = true
- Page Caching
rails cung cấp một cách cài đặt
caches_page :index
để thông báo cho webserver tự động generate trang HTML tĩnh và sử dụng cho các lần request tiếp theo từ controller Product action là index. mặc định thì trang HTML này sẽ được tạo ra tại folder /public bạn cũng có thể thay đổi chúng bằng cách thay đổi config trong
config.action_controller.page_cache_directory=new_cache_path
class ProductsController < ActionController
caches_page :index
def index
@products = Products.all
end
def create
expire_page :action => :index
end
end
ở đoạn code trên bạn sử dụng
expire_page :action => :index
trong action create để thông báo cho webserver hủy bỏ trang tĩnh index đã lưu trên webserver khi có một record mới được tạo. điều này nghĩa là khi bạn gọi lại trang index lần sau đó thì server sẽ thực hiện nạp lại trang index vào trang HTML bà bạn sẽ nhìn thấy dữ liệu của một record đã được thêm mới bạn cũng có thể cấu hình cho webserver (Ngix) sẽ tự động zip lại page khi gửi trả lại phía client để tăng tốc độ truy cập bằng cách bật thuộc tính
gzip_static:on trong setting server Ngix.
location / {
gzip_static on; # to serve pre-gzipped version
}
sau đó bạn có thể set thuộc tính gzip bằng cách
caches_page :index, :gzip => :best_speed
- Action Caching
Có những nhươc điểm của việc sử dụng cache page là với những trang mà yêu cầu quyền truy cập thì bạn không thể sử dụng dc. do request sẽ được trả lại ngay từ webserver nên ứng dụng không thể fillter được request với một trang đã được cache này từ đó chúng ta có cache_action
class ProductsController :index
caches_action :index
def index
@products=Product.all
end
def create
expire_action :action => :index
end
end
- Fragment Caching
Fragment caching là việc cache lại từng phần tử thông tin của trang để thực hiện việc caching từng phần tử của trang ta làm như sau:
<% cache(:action => 'index', :action_suffix => 'all_products') do %> All available products: <% Product.all.each do |p| %> <%= link_to p.name, product_url(p) %> <% end %> <% end %>
đoạn code trên chúng ta đang cache lại thông tin của tất cả các product lấy ra từ db trong block
<% cache() do end %>
để dọn dẹp cache chúng ta sử dụng
<% expire_fragment(:controller => 'products', :action => 'recent', :action_suffix => 'all_products') %>
khi sử dụng doạn code trên thì rails sẽ thông báo cho sever biết để hủy cache có suffix: ‘all_products’
- Sweepers
Sweeper sử dụng để quản lý exprire cache nếu bạn có nhiều cache được sử dụng ở nhiều nơi thì việc sử dụng sweeper giúp bạn dễ dàng quản lý chúng bằng để sử dụng sweeper bạn cần làm như sau.
VD bạn khai báo các hàm callback để thực hiện expired cache với model Product
class ProductSweeper < ActionController::Caching::Sweeper observe Product
This sweeper is going to keep an eye on the Product model
If our sweeper detects that a Product was created call this
def after_create(product) expire_cache_for(product) end
If our sweeper detects that a Product was updated call this
def after_update(product) expire_cache_for(product) end
If our sweeper detects that a Product was deleted call this
def after_destroy(product) expire_cache_for(product) end
private def expire_cache_for(product)
Expire the index page now that we added a new
product expire_page(:controller => 'products', :action => 'index')
Expire a fragment
expire_fragment('all_available_products') end end
và sau đó bạn khai báo trong Product controler như sau:
class ProductsController < ActionController before_filter :authenticate caches_action :index cache_sweeper :product_sweeper def index @products = Product.all end end
- SQL Caching
Nếu bạn sử dụng câu lệnh truy vấn lại nhiều lần rails sẽ hỗ trợ bạn lưu lại kết quả truy vấn vào cache VD: nếu bạn chạy 2 lần một câu lệnh truy vấn như bên dưới thì rails sẽ chỉ chạy một lần duy nhất thao tác vào db. các lần sau đó rails sẽ tự động lấy kết quả từ trong memory.
class ProductsController < ActionController def index # Run a find query @products = Product.all ... # Run the same query again @products = Product.all end end
Tuy nhiên việc cache lại câu lệnh sql trong rail chỉ có tác dụng trong chính hàm đó nên nếu bạn muốn sử dụng rộng rãi việc cache lại kết quả của lệnh truy vấn thì bạn sẽ phải sử dụng cache ở chế độ thấp hơn.
- Cache Stores
Rails hỗ trợ việc lưu trữ cache bằng nhiều cách khác nhau.
- Cache trên memory
nếu config lưu trữ trên memory thì rails sẽ thực hiện lưu trữ mọi thông tin trên memory của cùng một process. rail có thể lưu trữ cả chuỗi và các rails Object trong cache trên memory. setting:
ActionController::Base.cache_store = :memory_store
tuy nhiên việc lưu trữ trên memory với rails không phải là thread saft nên không thể dùng với ứng dụng multithread được Để sử dụng thread safe thì chúng ta phải sử dụng synchronized_memory_store thay vì memory_store
- Cache tron file
cache lưu trữ thông tin của ứng dụng trong rails default là được lưu trữ trong file với đường dẫn mặc định là tmp/cache lợi thế của việc lưu trữ cache trong file là có thể truy suất từ các process khác nhau trong cùng một server setting:
ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
- Cache DRb Store
Cache được lưu trữ trong một vùng nhớ chia sẻ mà các process cùng truy cập đến tuy nhiên bạn sẽ phải quản lý việc sử dụng process DRB này. setting
ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
- Memcache Store
Giống như cách lưu cache bằng DRb store. tuy nhiên Memache sử dụng cache dạng Danga’s memcached trong khi đó DRb store sử dụng default gem memcached-client (phổ biến nhất trong các ứng dụng hiện nay) setting:
ActionController::Base.cache_store = :memcached_store, "localhost"
memache có một số ưu điểm như: có thể sử dụng loadbalance and clustering với nhiều server memcached khác nhau. việc loadbalancing có thể được thực hiện giữa nhiều server (live) với nhau. khi một trong các server chết thì bỏ qua và chỉ thực hiện với các server đang sống
Compressed MemcachedStore Đây là cách lưu trữ có hỗ trợ nén dữ liệu sử dụng GZIP trong memcached
ActionController::Base.cache_store = :compressed_memcached_store, "localhost"
All rights reserved