2008-12-01 26 views
6

Tôi đang viết một ứng dụng web phức tạp hợp lý. Chương trình phụ trợ Python chạy một thuật toán có trạng thái phụ thuộc vào dữ liệu được lưu trữ trong một số bảng cơ sở dữ liệu có liên quan không thay đổi thường xuyên, cộng với dữ liệu cụ thể của người dùng thay đổi thường xuyên. Trạng thái của mỗi người dùng của thuật toán trải qua nhiều thay đổi nhỏ khi người dùng làm việc với ứng dụng. Thuật toán này được sử dụng thường xuyên trong quá trình làm việc của mỗi người dùng để đưa ra các quyết định quan trọng nhất định.Làm thế nào để một đối tượng Python tồn tại lâu dài trong một ứng dụng web?

Vì lý do hiệu suất, hãy khởi tạo lại trạng thái theo mọi yêu cầu từ dữ liệu cơ sở dữ liệu (bán chuẩn) nhanh chóng trở thành không khả thi. Nó sẽ là rất thích hợp hơn, ví dụ, để bộ nhớ cache đối tượng Python của nhà nước trong một số cách để nó có thể chỉ đơn giản được sử dụng và/hoặc cập nhật bất cứ khi nào cần thiết. Tuy nhiên, vì đây là một ứng dụng web, có một số quy trình phục vụ các yêu cầu, do đó, việc sử dụng một biến toàn cục không nằm trong câu hỏi.

Tôi đã thử tuần tự hóa đối tượng liên quan (qua pickle) và lưu dữ liệu đã tuần tự hóa vào DB, và giờ đây đang thử nghiệm với bộ nhớ đệm dữ liệu được tuần tự hóa thông qua memcached. Tuy nhiên, điều này vẫn có chi phí đáng kể của serializing và deserializing các đối tượng thường xuyên.

Tôi đã xem giải pháp bộ nhớ dùng chung nhưng điều duy nhất có liên quan tôi đã tìm thấy là POSH. Tuy nhiên POSH dường như không được sử dụng rộng rãi và tôi không cảm thấy dễ dàng tích hợp một thành phần thử nghiệm như vậy vào ứng dụng của tôi.

Tôi cần một số lời khuyên! Đây là lần đầu tiên tôi phát triển một ứng dụng web, vì vậy tôi hy vọng đây là một vấn đề đủ phổ biến mà có những giải pháp nổi tiếng cho các vấn đề như vậy. Tại đây các giải pháp điểm mà giả định Python back-end đang chạy trên một máy chủ duy nhất sẽ là đủ, nhưng điểm thêm cho những giải pháp mà quy mô đến nhiều máy chủ cũng :)

Ghi chú:

  • Tôi có điều này ứng dụng đang hoạt động, hiện đang hoạt động và với người dùng đang hoạt động. Tôi bắt đầu mà không thực hiện bất kỳ tối ưu hóa sớm nào, và sau đó được tối ưu hóa khi cần. Tôi đã thực hiện đo lường và thử nghiệm để đảm bảo vấn đề được đề cập ở trên là nút cổ chai thực tế. Tôi chắc chắn khá chắc chắn tôi có thể ép hiệu suất nhiều hơn từ các thiết lập hiện tại, nhưng tôi muốn hỏi nếu có một cách tốt hơn.
  • Bản thân thiết lập vẫn đang trong quá trình thực hiện; giả sử rằng kiến ​​trúc của hệ thống có thể là bất kỳ bộ nào mà giải pháp của bạn đưa ra.
+0

Khung làm việc nào? CherryPy? Django? –

+0

Bạn đã thực hiện bất kỳ phép đo nào chứng minh rằng truy cập trạng thái là nút cổ chai? Làm thế nào lớn là dưa chua, mất bao nhiêu thời gian để giải tán, bao lâu là toàn bộ yêu cầu, vv? –

+0

@Martin: Dưa chua là ~ 2MB lớn (giao thức 2), và quá trình tuần tự hóa và tuần tự hóa chiếm 90% thời gian xử lý yêu cầu. – taleinat

Trả lời

3

Tôi nghĩ rằng khung multiprocessing có những gì có thể được áp dụng ở đây - cụ thể là mô-đun chia sẻ ctypes.

Xử lý đa xử lý khá mới đối với Python, vì vậy nó có thể có một số điểm kỳ quặc. Tôi không hoàn toàn chắc chắn liệu giải pháp có hoạt động với các quá trình không sinh ra thông qua multiprocessing hay không.

+0

Cảm ơn vì điều này! Tôi đã không nhận thấy rằng một phần của chức năng của mô-đun đa xử lý. Điều này có thể chỉ là những gì tôi cần! – taleinat

+0

Chức năng bộ nhớ chia sẻ trong đa xử lý yêu cầu các đối tượng được chia sẻ là các cá thể của các lớp đặc biệt, vì vậy nó không hoạt động đối với các đối tượng Python bình thường. Tuy nhiên, đây là gợi ý tốt nhất cho đến nay và gần nhất với câu trả lời cho câu hỏi của tôi, vì vậy tôi chấp nhận nó. – taleinat

2

Tôi nghĩ bạn có thể cung cấp cho ZODB một shot.

"Một tính năng chính của ZODB là tính minh bạch. Bạn không cần viết bất kỳ mã nào để đọc hoặc ghi rõ ràng đối tượng của bạn vào hoặc từ cơ sở dữ liệu. Bạn chỉ cần đặt các đối tượng liên tục của mình vào một vùng chứa hoạt động giống như từ điển Python Tất cả mọi thứ bên trong từ điển này đều được lưu trong cơ sở dữ liệu, từ điển này được gọi là "root" của cơ sở dữ liệu. Nó giống như một túi ma thuật; bất kỳ đối tượng Python nào bạn đặt bên trong nó sẽ trở nên liên tục. "

Ban đầu nó là một phần không thể tách rời của Zope, nhưng gần đây một gói độc lập cũng có sẵn.

Nó có giới hạn như sau:

". Trên thực tế có một vài hạn chế về những gì bạn có thể lưu trữ trong ZODB Bạn có thể lưu trữ bất kỳ đối tượng có thể được 'ngâm' vào một tiêu chuẩn, định dạng nối tiếp cross-platform Các đối tượng như các tệp, ổ cắm và các đối tượng mã Python, không thể được lưu trữ trong cơ sở dữ liệu vì chúng không thể được chọn."

Tôi đã đọc nó nhưng đã không cho nó bản thân mình một shot dù

điều khác có thể có thể là một trong bộ nhớ sqlite db, mà có thể đẩy nhanh quá trình một chút -. Là một trong bộ nhớ db, nhưng bạn vẫn sẽ phải làm những thứ serialization và tất cả Lưu ý:. trong ký ức db là tốn kém về tài nguyên

Dưới đây là một liên kết:.. http://www.zope.org/Documentation/Articles/ZODB1

+1

Điều này làm nhiều hơn hoặc ít hơn những gì tôi hiện đang làm - serializes đối tượng với dưa chua và lưu dữ liệu tuần tự vào cơ sở dữ liệu. Vì tôi đang cố gắng loại bỏ phần trên của quá trình tuần tự hóa và quá trình tuần tự hóa, ZODB sẽ không giúp ích gì. – taleinat

+1

@taleinat, nó chỉ deserializes và serializes khi đối tượng đi ra khỏi bộ nhớ cache và nó được yêu cầu một lần nữa. – Unknown

8

Hãy thận trọng của tối ưu hóa sớm

Bổ sung: "Phần phụ trợ Python chạy một thuật toán có trạng thái ..." là phiên trong khung công tác web. Đó là nó. Hãy để khung Django duy trì trạng thái phiên trong bộ nhớ cache. Giai đoạn.

"Trạng thái của mỗi người dùng của thuật toán trải qua nhiều thay đổi nhỏ khi người dùng làm việc với ứng dụng". Hầu hết các khung công tác web cung cấp một đối tượng phiên được lưu trong bộ nhớ cache. Thường thì nó có hiệu suất rất cao. Xem sốcủa Django cho việc này.

Lời khuyên. [Đã sửa đổi]

Dường như bạn có thứ gì đó hoạt động. Tận dụng để tìm hiểu khuôn khổ của bạn, tìm hiểu các công cụ và tìm hiểu những nút bấm bạn có thể xoay mà không làm đổ mồ hôi. Cụ thể, sử dụng trạng thái phiên.

Thứ hai, fiddle với bộ nhớ đệm, quản lý phiên và những thứ dễ điều chỉnh và xem liệu bạn có đủ tốc độ hay không. Tìm hiểu xem liệu ổ cắm MySQL hay ống có tên là nhanh hơn bằng cách thử chúng. Đây là những tối ưu hóa không lập trình.

Thứ ba, đo lường hiệu suất để tìm nút cổ chai thực tế của bạn. Hãy sẵn sàng để cung cấp (và bảo vệ) các phép đo như hạt mịn, đủ để có ích và ổn định, đủ để cung cấp so sánh có ý nghĩa các lựa chọn thay thế.

Ví dụ: hiển thị sự khác biệt hiệu suất giữa các phiên liên tục và phiên được lưu trong bộ nhớ cache.

+0

Tôi có nó hoạt động, hiện đang sống và với những người dùng đang hoạt động. Tôi đã thất bại rồi. Và tôi đã thực hiện đo lường và thử nghiệm để đảm bảo đây là nút cổ chai thực sự. Tôi chắc chắn sẽ có nhiều việc khó khăn hơn để thực hiện, nhưng tôi muốn hỏi xem có cách nào tốt hơn không. – taleinat

+0

@taleinat: Vui lòng cập nhật câu hỏi bằng những sự kiện này. Ngoài ra, xác định khuôn khổ của bạn, hệ điều hành của bạn, cơ sở dữ liệu của bạn. –

+1

@ S.Lott: Tôi cố tình không đề cập đến khung công tác, hệ điều hành của tôi, v.v ... bởi vì tôi có thể thay đổi và tôi muốn cho phép các giải pháp với bất kỳ công cụ nào phù hợp với công việc. – taleinat

1

Một tùy chọn khác là xem xét yêu cầu về trạng thái, có vẻ như nếu tuần tự hóa là cổ chai thì đối tượng rất lớn. Bạn có thực sự cần một vật thể lớn không?

Tôi biết trong podcast Stackoverflow 27 nhóm reddit thảo luận về những gì họ sử dụng cho tiểu bang, để có thể hữu ích khi nghe.

+0

Tôi đã nghe hầu hết podcast bạn đã đề cập. Những tên reddit đã không thực sự đi vào chi tiết, họ chủ yếu nói rằng họ sử dụng memcached để đồng bộ hóa một số thứ thay vì "phiên dính", nhưng các phiên dính đơn giản hơn; và họ vẫn sẽ sử dụng memcached một lần nữa vì nó hoạt động rất tốt. – taleinat

2

Trước hết, cách tiếp cận của bạn không phải là thực tiễn phát triển web phổ biến. Thậm chí đa luồng đang được sử dụng, các ứng dụng web được thiết kế để có thể chạy các môi trường đa xử lý, cho cả khả năng mở rộng và triển khai dễ dàng hơn.

Nếu bạn chỉ cần khởi tạo một đối tượng lớn và không cần phải thay đổi sau này, bạn có thể thực hiện dễ dàng bằng cách sử dụng biến toàn cầu được khởi tạo trong khi ứng dụng WSGI của bạn đang được tạo hoặc mô-đun chứa đối tượng đang được tải vv, xử lý đa sẽ làm tốt cho bạn.

Nếu bạn cần thay đổi đối tượng và truy cập đối tượng từ mọi chuỗi, bạn cần đảm bảo đối tượng của mình là chủ đề an toàn, sử dụng khóa để đảm bảo. Và sử dụng một bối cảnh máy chủ duy nhất, một quá trình. Bất kỳ máy chủ python đa luồng nào cũng sẽ phục vụ bạn tốt, cũng FCGI là một lựa chọn tốt cho loại thiết kế này.

Tuy nhiên, nếu có nhiều chủ đề truy cập và thay đổi đối tượng, khóa có thể ảnh hưởng xấu đến hiệu suất của bạn, điều này có thể làm cho tất cả các lợi ích biến mất.

2

Đây là Durus, một hệ thống đối tượng liên tục cho các ứng dụng được viết bằng ngôn ngữ lập trình Python . Durus cung cấp một cách dễ dàng để sử dụng và duy trì bộ sưu tập nhất quán của các cá thể đối tượng được sử dụng bởi một hoặc nhiều quy trình. Truy cập và thay đổi trường hợp liên tục được quản lý thông qua một cá thể kết nối được lưu trong bộ nhớ cache bao gồm các phương thức commit() và abort() để thay đổi là giao dịch.

http://www.mems-exchange.org/software/durus/

Tôi đã sử dụng nó trước khi vào một số mã nghiên cứu, nơi tôi muốn kéo dài kết quả của phép tính nhất định. Cuối cùng tôi chuyển sang pytables vì nó đáp ứng tốt hơn nhu cầu của tôi.

+0

Điều này trông rất thú vị. Tuy nhiên, Durus cung cấp lớp cơ sở riêng của nó trong đó các đối tượng bền vững phải là các cá thể, vì vậy nó không hoạt động cho các đối tượng Python bình thường. – taleinat

+0

Bạn không thể thay đổi để sử dụng các lớp con của Persistent, vv ngay cả với nhiều thừa kế? – xitrium

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