Có bao nhiêu yêu cầu đồng thời mà một quy trình Flask nhận được?


138

Tôi đang xây dựng một ứng dụng với Flask, nhưng tôi không biết nhiều về WSGI và đó là cơ sở HTTP, Werkzeug. Khi tôi bắt đầu phục vụ một ứng dụng Flask với gunicorn và 4 quy trình worker, điều này có nghĩa là tôi có thể xử lý 4 yêu cầu đồng thời?

Tôi có nghĩa là yêu cầu đồng thời, và không yêu cầu mỗi giây hoặc bất cứ điều gì khác.

Câu trả lời:


183

Khi chạy máy chủ phát triển - đó là những gì bạn nhận được bằng cách chạy app.run(), bạn sẽ nhận được một quy trình đồng bộ duy nhất, có nghĩa là nhiều nhất 1 yêu cầu đang được xử lý tại một thời điểm.

Bằng cách dán Gunicorn trước cấu hình mặc định của nó và chỉ cần tăng số lượng --workers, những gì bạn nhận được về cơ bản là một số quy trình (được quản lý bởi Gunicorn) mà mỗi hành vi giống như app.run()máy chủ phát triển. 4 công nhân == 4 yêu cầu đồng thời. Điều này là do Gunicorn sử dụng syncloại công nhân đi kèm theo mặc định.

Điều quan trọng cần lưu ý là Gunicorn cũng bao gồm các công nhân không đồng bộ, cụ thể eventletgevent(và cũng có thể tornado, nhưng điều đó được sử dụng tốt nhất với khung Tornado, dường như). Bằng cách chỉ định một trong những nhân viên không đồng bộ này với --worker-classcờ, những gì bạn nhận được là Gunicorn quản lý một số quy trình không đồng bộ, mỗi quy trình quản lý đồng thời của chính nó. Các quy trình này không sử dụng chủ đề, mà thay vào đó là coroutines. Về cơ bản, trong mỗi quy trình, vẫn chỉ có 1 điều có thể xảy ra tại một thời điểm (1 luồng), nhưng các đối tượng có thể bị 'tạm dừng' khi chúng đang chờ các quy trình bên ngoài kết thúc (nghĩ truy vấn cơ sở dữ liệu hoặc chờ trên I / O mạng).

Điều này có nghĩa là, nếu bạn đang sử dụng một trong những nhân viên không đồng bộ của Gunicorn, mỗi công nhân có thể xử lý nhiều hơn một yêu cầu tại một thời điểm. Chỉ có bao nhiêu công nhân là tốt nhất phụ thuộc vào bản chất của ứng dụng của bạn, môi trường của nó, phần cứng mà nó chạy, v.v. Chi tiết có thể được tìm thấy trên trang thiết kế của Gunicornghi chú về cách thức hoạt động của gevent của trang trên trang giới thiệu của nó.


4
Gunicorn hiện hỗ trợ các chủ đề "thực" kể từ phiên bản 19. Xem cái nàycái này .
Filipe Correia

2
Làm thế nào để theo dõi tài nguyên nào được chia sẻ (và cách thức) và tài nguyên hoàn toàn tách biệt giữa các luồng / quy trình? Ví dụ: làm thế nào tôi có thể xử lý một tình huống mà tôi muốn chia sẻ cơ sở hạ tầng khổng lồ giữa một số quy trình được Gunicorn xử lý và được sử dụng trong trình xử lý Flask?
Johann Petrak

Những gì bạn đang hỏi @Johsm giống như hỏi cách chia sẻ dữ liệu giữa các quy trình khác nhau trong hệ điều hành. Câu trả lời có thể trả lời câu hỏi của bạn, bạn phải sử dụng bộ nhớ ngoài vì các quy trình không chia sẻ bộ nhớ của nó với các quy trình khác. Gunicorn ở đây chỉ để sử dụng các kiến ​​trúc CPU đa xử lý nhưng không xử lý các vấn đề đó.
adkl

Còn giao thừa thì sao? Điều này có giữ cho đêm giao thừa không?
Eswar

2
máy chủ phát triển bình sử dụng các luồng theo mặc định kể từ v1.0 ( github.com/pallets/flask/pull/2529 )
hychou

40

Hiện tại có một giải pháp đơn giản hơn nhiều so với những giải pháp đã được cung cấp. Khi chạy ứng dụng của bạn, bạn chỉ cần chuyển threaded=Truetham số cho app.run()cuộc gọi, như:

app.run(host="your.host", port=4321, threaded=True)

Một tùy chọn khác theo những gì chúng ta có thể thấy trong các tài liệu werkzeug , là sử dụng processestham số, nhận được một số> 1 cho biết số lượng tối đa của các quy trình đồng thời để xử lý:

  • luồng - quá trình nên xử lý từng yêu cầu trong một luồng riêng biệt?
  • các quy trình - nếu lớn hơn 1 thì xử lý từng yêu cầu trong một quy trình mới cho đến số lượng quy trình đồng thời tối đa này.

Cái gì đó như:

app.run(host="your.host", port=4321, processes=3) #up to 3 processes

Thông tin thêm về run()phương pháp ở đây , và bài đăng trên blog đã dẫn tôi tìm giải pháp và tài liệu tham khảo api.


Lưu ý: trên các tài liệu Flask về các run()phương pháp đã chỉ ra rằng việc sử dụng nó trong Môi trường sản xuất không được khuyến khích vì ( trích dẫn ): "Mặc dù nhẹ và dễ sử dụng, máy chủ tích hợp của Flask không phù hợp để sản xuất vì nó không có quy mô tốt . "

Tuy nhiên, họ chỉ đến trang Tùy chọn triển khai của họ để biết các cách được đề xuất để thực hiện việc này khi đi vào sản xuất.


5
Cảm ơn bạn về thông tin. Điều quan trọng cần lưu ý là tài liệu cho các trạng thái chạy không nên được sử dụng trong môi trường sản xuất nói rằng nó không đáp ứng các yêu cầu về bảo mật hoặc hiệu suất.
Coffee_fan

1
@Coffee_fan bạn nói đúng. Ngay cả trên bản 1.1.x mới nhất, họ không khuyến khích điều đó và thay vào đó đề nghị kiểm tra trang của họ trên Tùy chọn triển khai khi đi vào sản xuất. Bao gồm sự quan sát có giá trị của bạn trong câu trả lời :)
DarkCygnus

33

Flask sẽ xử lý một yêu cầu cho mỗi luồng cùng một lúc. Nếu bạn có 2 tiến trình với 4 luồng mỗi luồng, thì đó là 8 yêu cầu đồng thời.

Flask không sinh sản hoặc quản lý chủ đề hoặc quy trình. Đó là khả năng đáp ứng của cổng WSGI (ví dụ: gunicorn).


9

Không- bạn chắc chắn có thể xử lý nhiều hơn thế.

Điều quan trọng cần nhớ là sâu thẳm, giả sử bạn đang chạy một máy lõi đơn, CPU thực sự chỉ chạy một lệnh * tại một thời điểm.

Cụ thể, CPU chỉ có thể thực thi một bộ hướng dẫn rất hạn chế và nó không thể thực thi nhiều hơn một lệnh trên mỗi đồng hồ (nhiều hướng dẫn thậm chí chỉ mất hơn 1 tick).

Do đó, hầu hết đồng thời chúng ta nói về khoa học máy tính là phần mềm đồng thời. Nói cách khác, có các lớp triển khai phần mềm trừu tượng CPU cấp thấp nhất từ ​​chúng tôi và khiến chúng tôi nghĩ rằng chúng tôi đang chạy mã đồng thời.

Những "thứ" này có thể là các quy trình, là các đơn vị mã được chạy đồng thời theo nghĩa là mỗi quy trình nghĩ rằng nó chạy trong thế giới riêng của nó với bộ nhớ không chia sẻ riêng.

Một ví dụ khác là các luồng, là các đơn vị mã bên trong các quy trình cũng cho phép đồng thời.

Lý do 4 quy trình worker của bạn sẽ có thể xử lý hơn 4 yêu cầu là vì chúng sẽ loại bỏ các luồng để xử lý ngày càng nhiều yêu cầu.

Giới hạn yêu cầu thực tế phụ thuộc vào máy chủ HTTP được chọn, I / O, HĐH, phần cứng, kết nối mạng, v.v.

Chúc may mắn!

* hướng dẫn là các lệnh rất cơ bản mà CPU có thể chạy. ví dụ - thêm hai số, chuyển từ hướng dẫn này sang hướng dẫn khác


1
Có phải gunicorn sinh ra các chủ đề hoặc Flask? Tôi không tìm thấy bằng chứng ủng hộ khả năng nào.
jd.

1
Chắc chắn, tôi hiểu rằng về các quy trình, nhưng câu trả lời cho biết nhiều chủ đề được sinh ra khi cần thiết. Đó là những gì tôi muốn có xác nhận.
jd.

4
"Sâu sâu, giả sử bạn đang chạy một máy lõi đơn, CPU thực sự chỉ chạy một lệnh * tại một thời điểm" Điều này không đúng trên các máy hiện đại. Hầu hết các CPU hiện đại là pipelinedsuperscalar , trong đó ngay cả một lõi đơn có nhiều đơn vị thực thi và bộ giải mã lệnh chuyển đổi "mã máy" nhìn từ phía phần mềm thành các vi lệnh phần cứng thực tế được gửi đến các đơn vị thực thi riêng lẻ.
Michael Geary

1
Để làm rõ, trở lại trong ngày, CPU thực sự đã thực hiện trực tiếp các lệnh số trong một tệp thực thi - mã máy. Mỗi tham chiếu CPU có một biểu đồ thời gian hướng dẫn cho biết mỗi lệnh đã thực hiện bao nhiêu chu kỳ xung quanh bao gồm bất kỳ tham chiếu bộ nhớ nào. Vì vậy, bạn có thể chỉ cần thêm thời gian để biết bất kỳ đoạn mã nào sẽ mất bao lâu. CPU hiện đại không giống như vậy chút nào. Một ngoại lệ thú vị là BeagleBone có bộ xử lý ARM siêu thanh hiện đại hai bộ xử lý "PRU" kiểu cũ với thời gian hướng dẫn cố định.
Michael Geary

1
Và để làm rõ điều đó , khi tôi nói "hiện đại", tôi đã sử dụng nó như một cách viết tắt cho các bộ xử lý như chip ARM / Intel / AMD - pipelined, superscalar, v.v ... Tất nhiên cũng có những bộ xử lý hiện đại hoạt động theo cách cũ với thời gian cố định theo hướng dẫn, như PRU BeagleBone tôi đã đề cập và nhiều bộ vi điều khiển mới khác nhau. (Và bây giờ trở lại Gunicorn!)
Michael Geary
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.