2012-11-26 23 views
19

Trên một dự án mới với nhiều lưu lượng truy cập, chúng tôi đang suy nghĩ về cách cấu trúc ứng dụng Symfony2 của chúng tôi để tận dụng bộ nhớ cache và sẵn sàng tích cực hơn trong tương lai. Tôi rất muốn biết ý kiến ​​của bạn.Làm thế nào để cấu trúc một ứng dụng Symfony2 với ESI?

Giả sử người dùng yêu cầu trang một danh sách địa điểm. Trang này có:

- list 
    - common data (title, author, description) 
    - user data (the user likes the list + other data) 
- first 20 places 
    - common data (title, photo of each place) 
    - user data (the rates of the user for those places) 

HTML có thể giống như:

<html>... 
<body> 
    <header> 
    ... 
    <!-- Embed the top user menu --> 
    <esi:include src="http://example.com/profile/menu" /> 
    ... 
    </header> 

    <content> 
    ... 
    common data of the list 
    ... 
    <!-- Embed the common data of the first 20 places, the same for everyone --> 
    <esi:include src="http://example.com/lists/17/places" /> 
    ... 
    <!-- Embed the user data of the list (used in JS) --> 
    <esi:include src="http://example.com/lists/17/user" /> 
    ... 
    <!-- Embed the user data of the list of places (used in JS) --> 
    <esi:include src="http://example.com/lists/17/places/user" /> 
    ... 
    </content> 
</body>  
</html> 

HTML sẽ được lưu trữ trên các cửa ngõ (Symfony hoặc Varnish). Danh sách các địa điểm sẽ được lưu trữ hầu hết thời gian trên cổng. Các yêu cầu dữ liệu người dùng sẽ là những yêu cầu được gọi và không được lưu trữ (không phải lúc đầu ít nhất).

Câu hỏi:

  1. Làm thế nào để bạn cảm thấy về cấu trúc này?
  2. Nếu người dùng ẩn danh, tôi có thể tránh thực hiện bao gồm esi cho dữ liệu người dùng không? Ngoài ra nếu tôi có một cookie cho người dùng anon? Làm sao?
  3. Trình bao gồm thực đơn người dùng có hợp lý không?
  4. Hoặc chúng ta nên quên đi ESI và luôn đi qua bộ điều khiển (lưu vào bộ nhớ đệm hiển thị dữ liệu chung chẳng hạn)?
  5. Chúng ta có nên di chuyển 2 yêu cầu ESI yêu cầu dữ liệu người dùng là cuộc gọi AJAX, thay vì đợi trên máy chủ không?
  6. Đây có phải là cách tiếp cận tốt để mở rộng quy mô nếu chúng ta cần thực hiện nhanh không? Điều gì sẽ là tốt nhất?

cảm ơn rất nhiều!

Trả lời

4

Chúng tôi đã sử dụng Varnish trên một trang cho toàn bộ trang đệm và tôi đã sử dụng Symfony2 trong vài năm, nhưng hãy nhớ rằng tôi đã không sử dụng Varnish + Symfony2 + ESI trên bất kỳ môi trường sản xuất nào.

  1. Tôi nghĩ ý tưởng cơ bản là OK. Nếu menu giống nhau ở nhiều trang và danh sách địa điểm cũng giống nhau trên nhiều trang, bạn sẽ nhận được nội dung chung được lưu trong bộ nhớ cache ngược của Varnish hoặc Symfony. Do Varnish thường chứa bộ nhớ cache trong bộ nhớ, bạn sẽ nhận được nội dung của mình nhanh hơn và không phải gọi đến hiển thị và mã truy vấn DB theo từng yêu cầu.

    Phần khó khăn là làm cho các yêu cầu ESI được lưu trong bộ nhớ cache nếu người dùng đăng nhập. Như tôi biết, trong cấu hình Varnish mặc định, các yêu cầu với Cookie trong chúng không bao giờ được lưu trong bộ nhớ cache. Nếu bạn có xu hướng chuyển cookie cho các yêu cầu ESI, các phản hồi ESI đó sẽ không được chia sẻ giữa những người dùng.

    Bạn có thể thử thực hiện một số quy tắc từ URL, nhưng nếu bạn sử dụng trình trợ giúp ghép nối Symfony mặc định, URL được tạo là/_internal/..., do đó khó có thể khác biệt giữa các URL công khai và riêng tư.

    Ngoài ra, bạn có thể định cấu hình để luôn bỏ qua bất kỳ cookie nào nếu Cache-Control: public được chuyển. Này được thực hiện theo mặc định trong Symfony:

    if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { 
        $response->setPrivate(true); 
    } 
    

    Như bạn thấy từ mã, nếu bạn có public chỉ thị, phản ứng sẽ không bao giờ tin.

    Tôi chưa tìm thấy cách Varnish xử lý chỉ thị này - như tôi hiểu, nó không lưu trữ bất kỳ yêu cầu nào có cookie theo mặc định. Vì vậy, tôi nghĩ rằng bạn phải tinh chỉnh cấu hình để thực hiện điều này.

  2. Nếu trang chính cũng được lưu vào bộ nhớ cache, tôi không thấy cách bạn có thể bỏ qua bao gồm.

    Tôi giả sử JS là bắt buộc đối với người dùng đã đăng ký của bạn (không phải rô bốt tìm kiếm), vì vậy tôi khuyên bạn nên sử dụng Javascript để tải dữ liệu người dùng khác nhau.

    Mã Javascript có thể xem liệu người dùng có cookie session-id v.v. và yêu cầu nhận dữ liệu chỉ trong trường hợp này. Bạn cũng nên đặt một số cookie khác như _loggedin để tránh mã Javascript nhận id phiên.

    Người dùng chưa đăng nhập cũng có thể có một số dữ liệu trong cookie, như _likedPost:1,2,132. Javascript có thể nhận được cookie này và thực hiện một số chỉnh sửa HTML mà không cần thực hiện thêm yêu cầu.

    Như chúng tôi đã làm với các cookie này: chúng tôi đã tách các cookie chỉ JS khỏi các cookie ứng dụng. Chúng tôi đã thực hiện điều này bằng một số mẫu, như _\w cho các cookie JS. Sau đó, chúng tôi đã tinh chỉnh cấu hình Varnish để tách tiêu đề Cookie và xóa các cookie chỉ JS này. Sau đó, nếu không còn cookie nào khác, phản hồi sẽ được chia sẻ với mọi người. Ứng dụng (Symfony) không nhận được các cookie đó, vì chúng bị loại bỏ.

  3. Tôi nghĩ điều đó xảy ra nếu nó giống nhau ở mọi trang.

  4. Tôi nghĩ ESI tốt như Varnish có thể lưu bộ nhớ cache trong bộ nhớ. Vì vậy, nó có thể là nó thậm chí sẽ không thực hiện bất kỳ truy vấn vào đĩa cứng của bạn cho nội dung. Vì bộ đệm điều khiển của bạn có thể cũng có trong bộ nhớ, tôi nghĩ rằng Varnish sẽ tìm bộ nhớ cache nhanh hơn khung công tác Symfony với tất cả định tuyến, mã PHP, khởi tạo dịch vụ, v.v.

  5. Nó phụ thuộc, nhưng tôi nghĩ rằng nó có thể được tiếp cận tốt hơn. Hãy nhớ rằng, bộ nhớ cache sống cuộc sống khác nhau. Ví dụ: nếu danh sách địa điểm của bạn được lưu trong bộ nhớ cache trong 2 giờ, vào cuối thời gian này, địa điểm có thể đã thay đổi - một số mục mới là mới trong danh sách và một số mục bị thiếu. Danh sách của bạn cho người dùng vẫn là cũ (được lưu trong bộ nhớ cache), nhưng bạn cung cấp dữ liệu của người dùng về danh sách mới - một số dữ liệu không cần thiết, một số dữ liệu bị thiếu.

    Đó có thể là cách tiếp cận tốt hơn để tải địa điểm bằng javascript, ví dụ tìm kiếm một số thuộc tính HTML như data-list-item-id và sau đó yêu cầu ajax truy vấn dữ liệu về các mục này. Trong trường hợp này, dữ liệu người dùng của bạn sẽ được đồng bộ hóa với danh sách được lưu trong bộ nhớ cache hiện tại và bạn có thể thực hiện 1 yêu cầu ajax cho cả hai danh sách thay vì 2.

  6. Nếu không hợp lệ bộ nhớ cache (yêu cầu PURGE), tất cả bộ nhớ cache HTTP thực sự tốt để mở rộng quy mô. Bạn có thể mở rộng ứng dụng cho một số máy chủ và cấu hình Varnish để gọi chúng một cách ngẫu nhiên, theo một số quy tắc hoặc chỉ để sử dụng một trong số chúng như là một failsafe. Nếu băng thông vẫn còn quá lớn, bạn luôn có thể sửa đổi thời gian chờ của bộ nhớ cache và cấu hình khác.

+0

cảm ơn rất nhiều, Chúng tôi đang yêu cầu dữ liệu người dùng trong ajax, thay vì trong ESI. Vì vậy, tôi đồng ý với bạn. Hãy chờ xem việc này sẽ đi đến đâu. Phần quan trọng và thú vị sẽ là tránh sử dụng PURGE. Đó là mục tiêu để có thể mở rộng quy mô. – fesja

+0

Chia sẻ cách hoạt động sau khi thử –