Vượt quá giới hạn bộ nhớ python

Một khía cạnh cơ bản để tối ưu hóa bất kỳ ứng dụng nào là đảm bảo nó được kiến ​​trúc phù hợp. Ví dụ: nó nên sử dụng các công việc nền cho các tác vụ tính toán chuyên sâu để rút ngắn thời gian yêu cầu và sử dụng a để đảm bảo rằng các phần riêng biệt của ứng dụng có thể được thay đổi quy mô một cách độc lập

Ngoài điều này, bạn có thể đạt đến điểm cần mở rộng quy mô hoặc tối ưu hóa bằng cách sử dụng hiệu quả hơn các tài nguyên sẵn có. Ví dụ: nếu các yêu cầu web của bạn ngắn và được xử lý hiệu quả, bạn có thể tăng thông lượng trên dyno bằng cách tăng khả năng của máy chủ web để xử lý đồng thời nhiều yêu cầu hơn, thường phải trả giá bằng việc sử dụng nhiều RAM hơn

Bài viết này cung cấp cái nhìn toàn cảnh về cách tối ưu hóa ứng dụng cho các loại dyno khác nhau. Nó cung cấp một số ước tính sơ bộ về các khả năng và đặc biệt chú ý đến việc sử dụng bộ nhớ và xử lý đồng thời. Các kỹ thuật được đề xuất trong bài viết này có liên quan đến bất kỳ môi trường nào chạy ứng dụng của bạn, không chỉ một dyno. Để biết hướng dẫn cụ thể về việc giảm thiểu chi phí cho các môi trường khác nhau, hãy xem Tối ưu hóa chi phí tài nguyên

Khách hàng của Heroku Enterprise có Premier hoặc Signature Success Plans có thể yêu cầu hướng dẫn chuyên sâu về chủ đề này từ nhóm Kiến trúc giải pháp khách hàng (CSA). Tìm hiểu thêm về Phiên huấn luyện chuyên gia tại đây hoặc liên hệ với người điều hành tài khoản Salesforce của bạn

Xem xét các loại dyno khác nhau

Heroku cung cấp một loạt các loại dyno. Mỗi loại có một cấu hình CPU và RAM khác nhau

Thay đổi loại dyno của ứng dụng làm tăng độ phức tạp. với tư cách là nhà phát triển, bạn đã giới thiệu một biến mới, loại dyno, ngoài số lượng dyno

Tuy nhiên, một ứng dụng được thiết kế tốt sẽ tự nhiên có thể sử dụng các loại dyno khác nhau và suy nghĩ về việc tối ưu hóa ứng dụng của bạn để sử dụng dyno tốt hơn là một nỗ lực đáng giá

Ngay cả khi ứng dụng của bạn không cần sử dụng các loại dyno khác nhau, hãy cân nhắc áp dụng các kỹ thuật tối ưu hóa này cho loại dyno hiện tại của bạn

Các loại dyno khác nhau cung cấp ba trục tối ưu hóa quan trọng. CPU, RAM và cấu hình hiệu năng

CPU

Hầu hết các ứng dụng không bị ràng buộc bởi CPU trên máy chủ web

Nếu bạn đang xử lý các yêu cầu riêng lẻ chậm do hạn chế về CPU hoặc các tài nguyên được chia sẻ khác (chẳng hạn như cơ sở dữ liệu), thì việc tối ưu hóa đồng thời trên dyno có thể không giúp ích gì cho thông lượng của ứng dụng của bạn. Nói cách khác, nếu ứng dụng của bạn chậm khi có ít lưu lượng truy cập, các kỹ thuật trong bài viết này có thể không tăng hiệu suất

Các loại dyno khác nhau cung cấp các đặc tính hiệu suất CPU khác nhau và sẽ hỗ trợ một chút trong các tình huống CPU cao, nhưng lý tưởng nhất là bạn nên xem xét việc giảm tải công việc cho một nhân viên chạy nền như một bước đầu tiên trong quá trình tối ưu hóa cũng như tối ưu hóa mã

Một khía cạnh cuối cùng của CPU là số lượng lõi. Các loại dyno khác nhau, đặc biệt là performance, cung cấp nhiều lõi. Với nhiều lõi, bạn có thể thực thi song song nhiều luồng. Bài viết này chỉ ra nơi bạn cần hành động để sử dụng các lõi này

Phần còn lại của bài viết này sẽ giả định rằng ứng dụng không bị ràng buộc bởi CPU

ĐẬP

Tùy thuộc vào ngôn ngữ và khung web, thường có sự tương ứng trực tiếp giữa RAM và đồng thời

Ví dụ: các máy chủ web như Unicorn cho Ruby hoặc Gunicorn cho Python, phân nhánh trước một số bản sao giống hệt nhau của máy chủ web của bạn (được gọi là công nhân). Sau đó, Unicorn có hàng đợi kết nối của riêng mình và khi công nhân hoàn thành một yêu cầu web, họ sẽ lấy một yêu cầu mới ra khỏi hàng đợi

Có nhiều RAM hơn trong trường hợp này có nghĩa là bạn có thể có nhiều công nhân chạy đồng thời hơn - và thường có mối tương quan khá tuyến tính giữa RAM và đồng thời. Tối ưu hóa đồng thời cho RAM là điều mà bài viết này giải quyết

hồ sơ hiệu suất

Cấu hình hiệu suất của từng loại dyno có thể có tác động. Đặc biệt, các dyno eco, basic, standard-1xstandard-2x hoạt động trên cơ sở chia sẻ CPU, trong khi các dyno của performance là người thuê duy nhất

Do đó, các dyno performance này cung cấp mức độ cô lập tài nguyên cao hơn

Điều này có thể có tác động đáng kể đến các ứng dụng, tùy thuộc vào lượng lưu lượng truy cập mà chúng nhận được và chúng được tối ưu hóa tốt như thế nào. Cụ thể, cấu hình hiệu suất nhất quán hơn có thể giúp giảm độ trễ đuôi

Khi nào nên thử một kích thước dyno khác

Có nhiều yếu tố ảnh hưởng khi xem xét các loại dyno khác nhau. Một số trong số chúng là vốn có của ứng dụng của bạn (nó sử dụng bao nhiêu CPU), một số là do các yếu tố tối ưu hóa được giới thiệu bởi sự đồng thời tăng lên (do có nhiều RAM hơn) và một số là do các đặc điểm vốn có của chính dyno

Sự phức tạp này có thể khó điều hướng, nhưng có thể tìm thấy các kỹ thuật đơn giản được đề xuất trong bài viết này cho các ứng dụng không bị ràng buộc bởi CPU giúp nó trở nên dễ xử lý hơn và dễ dàng tối ưu hóa cho bất kỳ loại dyno nào

Sau khi bạn đã tối ưu hóa cho một loại dyno cụ thể, chẳng hạn như standard-1x dyno, hãy áp dụng các kỹ thuật tương tự trên một dyno standard-2x, performance0 hoặc performance1 - có tính đến các yếu tố mà mỗi loại dyno đưa vào

Dưới đây là một số quy tắc thô của ngón tay cái

  • Đối với hầu hết các ứng dụng không nhận được lưu lượng truy cập cực lớn, hãy xem xét standard-1x dynos
  • Nếu ứng dụng đặc biệt ngốn bộ nhớ, như đã thấy trong một số khung dựa trên Java như Play và JRuby, hãy xem xét standard-2x dynos giúp tăng gấp đôi bộ nhớ
  • Đối với các ứng dụng web có khối lượng rất lớn, chạy trên hơn 20 standard-1x dyno, hãy xem xét performance0 hoặc performance1 dyno

Phương pháp cơ bản để tối ưu hóa bộ nhớ

Chúng tôi khuyên bạn nên làm theo các bước sau, sử dụng các công cụ hiển thị được liệt kê bên dưới, cũng như các đề xuất theo ngôn ngữ. Điều này sẽ đưa bạn đến một điểm mà bạn có thể dễ dàng tối ưu hóa cho một loại dyno duy nhất hoặc để di chuyển giữa các loại dyno

  1. Sử dụng máy chủ web đồng thời
  2. Thiết lập thiết bị đo lường tác động của tải đối với ứng dụng
  3. Quan sát hiệu suất của ứng dụng và điều chỉnh đồng thời nếu cần

Tối ưu hóa là một quá trình lặp đi lặp lại - không có con đường vàng. Các ngôn ngữ, khung web và ứng dụng khác nhau hoạt động khá khác nhau

Ví dụ: một ứng dụng Ruby tiêu chuẩn có thể cần sử dụng máy chủ web phân nhánh nhiều bản sao của ứng dụng để sử dụng tất cả RAM có sẵn. Mặt khác, một ứng dụng Java tiêu chuẩn có thể chỉ cần một tham số cho JVM để phân bổ một đống lớn hơn

Máy chủ web đồng thời

Các ngôn ngữ và nền tảng khác nhau có cách tiếp cận đồng thời khác nhau. Dưới đây là một cái nhìn ngắn gọn về cách thiết lập đồng thời trong các ứng dụng chạy trên Ruby, Java, Python và Node. js

hồng ngọc

Để xem cách bạn có thể tối ưu hóa ứng dụng của mình, vui lòng tham khảo bài viết toàn diện về R14 - Vượt quá hạn ngạch bộ nhớ trong Ruby (MRI). Nó đề cập đến các vấn đề phổ biến đối với tình trạng phình bộ nhớ trong ứng dụng Ruby cũng như một số công cụ và kỹ thuật chẩn đoán để tìm và khắc phục tình trạng sử dụng bộ nhớ tăng lên trong ứng dụng Ruby. Kết nối đồng thời và cơ sở dữ liệu trong Ruby với ActiveRecord là một tài nguyên tuyệt vời để đánh giá cách tính đến các phương pháp hay nhất cho các kết nối cơ sở dữ liệu để tối đa hóa đồng thời.

JRuby

Các máy chủ JRuby như Puma sử dụng đồng thời tốt mà không cần nhiều quy trình. Tuy nhiên, bạn sẽ cần điều chỉnh dung lượng bộ nhớ được phân bổ cho JVM, tùy thuộc vào loại dyno. Gói xây dựng Ruby xác định các giá trị mặc định hợp lý, có thể bị ghi đè bằng cách đặt performance7 hoặc performance8

Java, Scala, Clojure

Các máy chủ web Java như Jetty, Tomcat và Netty tận dụng tốt khả năng tương tranh ngay lập tức. Tuy nhiên, bạn sẽ cần điều chỉnh dung lượng bộ nhớ được phân bổ cho JVM, tùy thuộc vào loại dyno

Đọc các cờ performance7 thích hợp để thực hiện điều này

con trăn

Nếu bạn muốn tối ưu hóa để tăng tính đồng thời, Heroku khuyên bạn nên sử dụng ứng dụng Gunicorn cho Python

Gunicorn hoạt động bằng cách rẽ nhánh một số quy trình con có thể định cấu hình, được gọi là công nhân. Mỗi công nhân chỉ có thể xử lý một yêu cầu tại một thời điểm. Đồng thời xảy ra do quy trình Gunicorn chính xếp hàng đợi các yêu cầu web mới và sau đó chúng được ủy quyền cho công nhân nếu chúng có sẵn và đã hoàn thành xử lý yêu cầu trước đó

Việc tăng đồng thời sau đó được định cấu hình bằng cách tăng số lượng công nhân

Tuy nhiên, vì mỗi worker thực sự là một phiên bản rẽ nhánh của ứng dụng của bạn, nên việc chuyển từ một worker sang hai worker sẽ tăng gấp đôi yêu cầu bộ nhớ cho ứng dụng của bạn

Đó là sự đánh đổi - giữa tăng tính đồng thời và bộ nhớ có sẵn trong một dyno, mà bạn sẽ đo lường và điều chỉnh

Đọc Triển khai ứng dụng Python với Gunicorn để tìm hiểu cách thiết lập Gunicorn cho Python trên Heroku. Điều này sẽ dẫn đến một máy chủ web có biến cấu hình, eco0, cho phép bạn điều chỉnh số lượng công nhân mà quy trình Unicorn chính sẽ rẽ nhánh

Mặc dù phụ thuộc nhiều vào ứng dụng, bảng sau đây liệt kê một số quy tắc cơ bản về số lượng công nhân Unicorn có thể chạy trên mỗi loại dyno

Loại DynoSố lượng công nhân Gunicorneco, basic, standard-1x2-3standard-2x4-6hiệu suất-m8-12hiệu suất-l20-30

Đây chỉ là ước tính và sẽ thay đổi tùy theo ứng dụng. Sử dụng một cái gì đó trong phạm vi thấp hơn, đo lường và điều chỉnh khi cần thiết

Để biết các đề xuất dành riêng cho Django, hãy xem Kết nối đồng thời và cơ sở dữ liệu trong Django

Nút. js

Nút cung cấp mô hình quy trình đơn luồng, không chặn. Để tận dụng lợi thế của nhiều lõi, Nút phải sử dụng API cụm để rẽ nhánh nhiều quy trình đồng thời. Ngay cả khi bạn không có kế hoạch sử dụng đồng thời ngay hôm nay, chúng tôi khuyên bạn nên bật Cluster trong ứng dụng của mình để nó có thể mở rộng thành nhiều vùng chứa khác nhau

Đọc nút tối ưu hóa. js Đồng thời để tìm hiểu cách định cấu hình đồng thời thông qua API cụm của Node trên Heroku

PHP

Các ứng dụng sử dụng thời gian chạy PHP hoặc HHVM tự động điều chỉnh số lượng worker process hoặc thread tùy thuộc vào loại dyno mà chúng chạy trên đó. Yếu tố chính để quyết định số lượng quy trình hoặc luồng là giới hạn bộ nhớ PHP được định cấu hình cho một ứng dụng

Vui lòng tham khảo Tối ưu hóa đồng thời ứng dụng PHP để biết thêm thông tin về cách điều chỉnh các ứng dụng PHP để có thông lượng tối đa

Đo lường

Sau khi thiết lập máy chủ web đồng thời, bạn sẽ muốn điều chỉnh nó cho một loại dyno cụ thể. Việc đo bộ nhớ và thông lượng sẽ cung cấp đủ hướng dẫn để bạn đưa ra đánh giá về tác động của thay đổi

Đo bộ nhớ bằng log-runtime-metrics

Tính năng log-runtime-metrics của Heroku Labs thêm hỗ trợ cho phép hiển thị tải và sử dụng bộ nhớ để chạy dynos. Dynos trong Không gian riêng tư luôn gửi số liệu thời gian chạy tới luồng nhật ký và sẽ không cần bật tính năng này

Số liệu thống kê trên mỗi dyno về sử dụng bộ nhớ, sử dụng trao đổi và trung bình tải được chèn vào luồng nhật ký của ứng dụng

Đây là một số đầu ra ví dụ với tính năng này được kích hoạt

source=web.1 dyno=heroku.2808254.d97d0ea7-cf3d-411b-b453-d2943a50b456 sample#load_avg_1m=2.46 sample#load_avg_5m=1.06 sample#load_avg_15m=0.99
source=web.1 dyno=heroku.2808254.d97d0ea7-cf3d-411b-b453-d2943a50b456 sample#memory_total=21.00MB sample#memory_rss=21.22MB sample#memory_cache=0.00MB sample#memory_swap=0.00MB sample#memory_pgpgin=348836pages sample#memory_pgpgout=343403pages

eco1 là con số quan trọng nhất ở đây, cung cấp dấu hiệu về tổng bộ nhớ cư trú. Đảm bảo rằng bạn không vượt quá bộ nhớ của loại dyno của mình - và cũng để lại một số khoảng trống trên đầu. Tương tự như vậy, hãy đảm bảo rằng bạn duy trì mức sử dụng hoán đổi ở mức tối thiểu và hoạt động hoán đổi (eco2/eco3) ở mức tối thiểu. Lý tưởng nhất là eco2/______2_______3 không nên thay đổi nhiều theo thời gian (tỷ lệ thay đổi bằng 0)

Xem để hiểu cách diễn giải những số liệu này

Đầu ra của log-runtime-metrics đặc biệt hữu ích vì nó cho phép bạn xem mức sử dụng bộ nhớ trên mỗi dyno. Nếu bạn được cung cấp quá mức, bạn có thể thấy một dyno duy nhất đạt đỉnh trước bất kỳ điểm nào khác

Có nhiều cách khác để hiển thị dữ liệu bộ nhớ này

, với gói Niken trở lên, cung cấp một cách để vẽ biểu đồ đầu ra khác nhau từ chỉ số thời gian chạy nhật ký, tính trung bình các giá trị trên tất cả các dynos

Đây là đầu ra mẫu cho ứng dụng Rails trên standard-1x dynos sử dụng 4 công nhân Unicorn. Bộ nhớ, khoảng 359 MB ở mức cao nhất, vừa vặn với _______ 512 MB RAM

Vượt quá giới hạn bộ nhớ python

Đo thông lượng và thời gian đáp ứng

Thông lượng, số lượng yêu cầu được xử lý mỗi phút, cũng như thời gian phản hồi, là những chỉ báo đặc biệt hữu ích về mức độ ảnh hưởng của việc tối ưu hóa đến hiệu suất của một dyno.

Đặc biệt, các giá trị thời gian phản hồi phần trăm thứ 95 và 99 được cung cấp bởi các tiện ích bổ sung như Librato hoặc New Relic phải được theo dõi chặt chẽ