Tìm hiểu về http caching

0. Mở đầu

Trong các ứng dụng web, caching là một vấn đề cực kỳ quan trọng để tối ưu hóa performance. Có rất nhiều cách để caching -Page Caching -Action Caching -Fragment Caching -Russian Doll Caching -Managing dependencies -Low-Level Caching -SQL Caching

Nhưng hôm nay mình xin giới thiệu về http caching

Thực ra nếu làm web, với client là browser (chrome, firefox)... thì các bạn có thể bỏ qua bài viết này, hoặc đọc để hiểu rõ hơn. Vì browser đã tự có cơ chế caching này rồi, còn nếu làm ứng dụng APP (Android, IOS), có thể sẽ có bạn không để ý về http caching, dẫn tới việc mất thời gian đi tìm các giải pháp phức tạp.

1. Tại sao dùng http caching

Các trình duyệt xây dựng trong nó hệ thống cache. Mỗi khi ta nhấn nút Back trên trình duyệt thì nó đọc lại cho ta trang ta vừa xem trong cache của nó. Đối tượng cache có thể là các file tạm thời trên đĩa hoặc có thể là trong bộ nhớ trong.

Tư tưởng là khi request 1 file từ host, trước hết ta sẽ load về HTTP header của file. Nếu là lần đầu hoặc, HTTP header thay đổi so với lần trước thì sẽ lấy file từ host về.

Ngược lại, sẽ lấy luôn file trên local.

Dưới đây là một gói HTTP header thông thường

HTTP/1.1 200 OK

Date: Fri, 08 Nov 2013 04:41:40 GMT

Server: Apache/2.2.15 (CentOS)

Last-Modified: Sun, 11 Aug 2013 02:41:48 GMT

Etag: "1c253d-6c2-4e3a2f30b418d"

Accept-Ranges: bytes

Content-Length: 1730

Cache-Control: max-age=1209600

Expires: Fri, 22 Nov 2013 04:41:40 GMT

Keep-Alive: timeout=15, max=100

Connection: Keep-Alive

Content-Type: text/javascript

2. Last-Modified

Ta sẽ so sánh thời gian sửa đổi cuối cùng để xác định xem file này đã cập nhật nội dung nào mới chưa, nếu có thì tải về:

B1: Client —-Last-modified——–> Server

B2: Server: Lục file đó, kiểm tra Last-modified có khớp vs Last-modified của client không, nếu khớp, tới B4.

B3: Nếu không khớp (tức là đã có cập nhật mới), gửi HTTP response chứa file yêu cầu về cho client. Tới B5.

B4: Gửi HTTP response chứa Status Code: 304 Not Modified.

Bước 5: Kết thúc.

3. Etag (Entity Tags)

Khuyết điểm khi dùng Last-Modified:

  • Múi giờ và thời gian của Server phải trùng với của client.

  • Vẫn yêu cầu xử lý trên server.

Do đó, có một cách khác là dùng Etag, nó là một chuỗi duy nhất được sinh ra bằng hash hoặc footprint, tức là mỗi lần có thay đổi là Etag cũng sẽ bị đổi theo.

B1: Client —–Etag—-> Server

B2: Server kiểm tra xem Etag có khớp không, nếu khớp chuyển tới B4.

B3: Nếu không khớp (có cập nhật mới), gửi HTTP response chứa file yêu cầu về cho client. Tới B5.

B4: Gửi HTTP response chứa Status Code: 304 Not Modified.

Bước 5: Kết thúc.

4. Expires

Khuyết điểm của Etag: Vẫn phải kết nối tới server để kiểm tra trong mỗi request.

Ta cần tìm một cách nào đó để browser tự biết khi nào cần tải về. Expires trong HTTP Header cũng giống như khi ta đặt expire time cho session. Browser sẽ tự biết khi nào file đó hết hạn để tài về.

B1: Browser: check Experies, nếu còn trong Expiration thì chuyển tới bước 4.

B2: Nếu đã hết hạn (expired) thì gửi request tới server yêu cầu gửi file về.

B3: Server —–file requested —–> Client. Tới bước 4.

Bước 4: Kết thúc.

Expires headers sử dụng tốt nhất cho caching các hình ảnh tĩnh (như Navigation bar và các button). Do đó ta có thể đặt một khoảng thời gian expired lớn.

5. Cache-Control

Rõ ràng việc sử dụng Expires khiến ta giảm được một lượng đáng kể công việc cho server nhưng thay vào đó, Browser vẫn phải thực hiện những phép tính thời gian và vẫn phải đòi hỏi sự đồng bộ giữa đồng hồ của Web server và của cache.

Mục đích của Cach-Control là để các nhà phát triển có thể kiểm soát tốt hơn nội dung trang web và giới hạn địa chỉ cho Expires.

Cache-Control header bao gồm:

  • max-age=[seconds]: gán thời gian tối đa trước khi file hết hạn. Giá trị này cũng tương tự như Expires và được tính bằng giây.

  • s-maxage=[seconds] : cũng tương tự như max-age nhưng chỉ áp dụng cho những cache được chia sẻ (ví dụ như proxy).

  • public: Đánh dấu rằng gói response này có thể cached. Thông thường người ta set thuộc tính public cho những thông tin không bảo mật và báo cho trình duyệt biết rằng có thể cache. Thông thường, nếu yêu cầu xác thực HTTP thì response sẽ tự động private.

  • private: Chỉ cho phép cache thông tin của một user nào đó vào trình duyệt của họ. Và những shared cache (như proxy) thì không được phép.

6. Các lưu ý để xây dựng một web site cache hiệu quả:

  • Sử dụng những URL duy nhất: Đây là nguyên tắc vàng trong caching. Nếu ta sử dụng một nội dung giống nhau cho trang khác nhau, những người dùng khác nhau hoặc những website khác nhau. Ta nên sử dụng các URL giống nhau. Đây là cách dễ dàng và hiệu quả nhất để trang web của ta có thể dễ dàng caching. Ví dụ, nếu ta sử dụng /index.html để chỉ tới một nội dung thì phải luôn luôn sử dụng nó.

  • Sử dụng một thư viện ảnh chung: như vậy những phần tử khác nhau sẽ dẫn đến những thư viện ảnh đó từ những vị trí khác nhau.

  • Cache lại những hình ảnh và những trang không thay đổi thường xuyên: Sử dụng header Cache-Control: max-age và set cho nó một giá trị thật rộng.

  • Nếu một resource (đặc biệt là một file để download) bị thay đổi, hãy đổi tên của nó: Với cách này, ta có thể giữ nó lâu hơn mà vẫn đảm bảo được phiên bản chính xác đang được cung cấp bằng cách mỗi lần cập nhật phiên bản mới, ta chỉ cần sửa đường dẫn tới nó một chút. Và trang web dẫn tới nó phải là duy nhất và thời gian quá hạn của trang web này phải ngắn.

  • Không thay đổi những file không cần thiết: Khi ta update web site, chỉ thay thế những file được sửa đổi, không nên update toàn bộ trang web vì những file không bị sửa đổi thì thuộc tính Last-Modified của nó sẽ thay đổi và trình duyệt sẽ phải cache lại nó.

  • Chỉ sử dụng cookies khi cần thiết: Cookies rất khó cache và không cần thiết trong nhiều trường hợp. Nếu bạn bắt buộc phải sử dụng cookie thì nên hạn chế dùng nó cho những trang web động.

  • Hạn chế sử dụng SSL: Vì những trang mã hóa không được cache lại, do đó ta chỉ sử dụng chúng trong những trường hợp bắt buộc và không nên sử dụng nhiều hình ảnh cho những trang SSL.

  • Kiểm tra trang web của bạn với: http://redbot.org/ Nó sẽ giúp bạn hiểu hơn những nội dung được trình bày bên trên để optimize trang web của bạn.

6. Kết luận

Với framework Ruby on rails mọi thứ đã sẵn có, chúng ta cũng không cần quan tâm đến điều này lắm. Tuy nhiên, nếu bạn làm APP và gặp phải vấn đề performance khi tải đi tải lại 1 resource (file pdf, img, video...) hãy nghĩ tới http caching.

Tài liệu tham khảo https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching

Hi vọng bài viết này hữu ích. ❤️