2014-11-10 28 views
11

Tôi có ứng dụng Flask chạy dưới Gunicorn, sử dụng loại nhân viên đồng bộ với 20 quy trình công nhân. Ứng dụng đọc rất nhiều dữ liệu khi khởi động, cần thời gian và sử dụng bộ nhớ. Tồi tệ hơn, mỗi quá trình tải bản sao của riêng nó, làm cho nó mất nhiều thời gian hơn và mất 20X bộ nhớ. Dữ liệu tĩnh và không thay đổi. Tôi muốn tải nó một lần và có tất cả 20 công nhân chia sẻ nó.Chia sẻ dữ liệu toàn cầu tĩnh giữa các quy trình trong ứng dụng Gunicorn/Flask

Nếu tôi sử dụng cài đặt preload_app, nó chỉ tải trong một chuỗi và ban đầu chỉ mất bộ nhớ 1X, nhưng sau đó dường như phải chuyển sang 20X khi yêu cầu bắt đầu. Tôi cần truy cập ngẫu nhiên vào dữ liệu, vì vậy tôi ' d thay vì không làm IPC.

Có cách nào để chia sẻ dữ liệu tĩnh giữa các quy trình Gunicorn không?

Trả lời

4

Các tệp được ánh xạ bộ nhớ sẽ cho phép bạn chia sẻ các trang giữa các quá trình.

https://docs.python.org/2/library/mmap.html

Lưu ý rằng thống kê tiêu thụ bộ nhớ thường gây hiểu lầm và vô ích. Nó thường là tốt hơn để xem xét đầu ra của vmstat và xem nếu bạn đang trao đổi rất nhiều.

+0

Tôi đoán có lẽ đã nói rằng tôi muốn chia sẻ một dict Python bình thường, không chỉ là một blob bộ nhớ. –

+0

@DoctorJ Sau đó, bạn ra khỏi may mắn. Lý do là một cấu trúc dữ liệu Python chỉ là con trỏ đến con trỏ trong bộ nhớ, mà sẽ kéo dài nhiều trang. Hầu hết các trang đó cũng sẽ được chia sẻ với dữ liệu được ghi vào, do đó sao chép trên ghi làm cho các trang được sao chép trong mỗi quá trình. Tôi khuyên bạn nên sử dụng một cửa hàng đối tượng hoặc kho khóa-giá trị như Redis - đây là giải pháp "chuẩn" cho vấn đề này ngày nay. IPC trên localhost rất nhanh, có thể bạn đang tối ưu hóa sớm nếu bạn nghĩ rằng đó sẽ là nút cổ chai. – aaa90210

1

Giả sử ưu tiên của bạn là giữ dữ liệu dưới dạng cấu trúc dữ liệu Python thay vì di chuyển nó sang cơ sở dữ liệu như Redis, bạn sẽ phải thay đổi mọi thứ để có thể sử dụng một quy trình duy nhất cho máy chủ của mình.

Gunicorn thể làm việc với gevent để tạo ra một máy chủ có thể hỗ trợ nhiều khách hàng trong vòng một quá trình lao động đơn sử dụng coroutines, đó có thể là một lựa chọn tốt cho nhu cầu của bạn.

+0

Bạn có thể giải thích thêm về điều này không? Nghe có vẻ có giá trị, nhưng tôi không chắc nó sẽ hoạt động như thế nào. – Eli

+0

Không có nhiều sự khác biệt, Flask tóm tắt bạn từ các chi tiết. khi bạn sử dụng gevent, bạn chỉ cần đảm bảo chức năng xem của bạn làm những gì họ cần làm mà không cần tốn nhiều thời gian của CPU (hoặc có hiệu suất nếu chúng là các tác vụ dài). Đa tác vụ đạt được bằng cách đặt mỗi yêu cầu trong một coroutine, nhưng tất cả điều này được xử lý bởi khung công tác. – Miguel

+0

Tôi có nghĩa là nhiều hơn xung quanh nhận được mã để chạy trong quá trình cha mẹ chỉ tạo ra các dữ liệu và giữ nó cập nhật. Rất giống với câu hỏi này: http://stackoverflow.com/questions/13768894/run-startup-code-in-the-parent-with-django-and-gunicorn – Eli

Các vấn đề liên quan