Khi chúng tôi giảm tải các tác vụ chạy dài từ máy chủ web, người dùng sẽ tải trang nhanh và chúng tôi [nhà phát triển] sẽ xử lý song song. Thắng, thắng
Trong các ứng dụng Python [Django/Flask], cho đến nay, Celery là thư viện phổ biến nhất để xử lý công việc ở chế độ nền. Đây là một công cụ phải học dành cho các nhà phát triển web Python
Bài viết này sẽ hướng dẫn bạn qua một ứng dụng ví dụ minh họa các tính năng của Celery và tìm hiểu sâu hơn về cách sử dụng chúng
Khái niệm cơ bản về Cần tây & DjangoTôi đã từng viết về Cần tây trong một trong những bài viết phổ biến nhất của mình
hướng dẫn cần tây. Công nghệ phải học dành cho nhà phát triển Python
Công nhân để xử lý các tác vụ trong nền là công cụ thiết yếu và mạnh mẽ trong bộ công cụ của bất kỳ nhà phát triển nào
Trung bình. com
Bài viết này giả định rằng bạn đã quen thuộc với những kiến thức cơ bản về Cần tây. Nếu chưa, hãy bắt đầu với bài viết trên
nền nhanhNgười dùng không muốn đợi các tác vụ chạy lâu. Họ muốn tải trang nhanh. Nhưng đôi khi công việc cần có thời gian, đặc biệt đối với các ứng dụng sử dụng nhiều dữ liệu. Làm thế nào để chúng tôi giải quyết nó?
Chúng tôi cần giảm tải công việc từ máy chủ web của mình. Bằng cách sử dụng hàng đợi tác vụ và các máy chủ dành riêng cho “công nhân”, chúng tôi có thể sắp xếp một cách để hoàn thành công việc một cách không đồng bộ. Các công nhân sẽ chạy các nhiệm vụ đằng sau hậu trường và cập nhật cho chúng tôi kết quả
trong bài viết này
- Tôi đã xây dựng ứng dụng bằng Django
- Hàng đợi tin nhắn — nơi chúng tôi thêm tác vụ mới và nhân viên nhận tác vụ tiếp theo — được triển khai trong Redis
- Chúng tôi sử dụng Celery để kết hợp tất cả lại với nhau, thêm các tác vụ vào hàng đợi từ ứng dụng Django của chúng tôi VÀ chạy các máy chủ worker xử lý các tác vụ từ hàng đợi
Whew, đó là rất nhiều thông tin trong một vài đoạn văn ngắn. Nếu bạn bối rối hoặc không theo dõi, hãy xem bài viết Hướng dẫn về cần tây trước khi đi sâu vào bài viết này
Chỉ muốn mã nguồn?hạnh phúc để bắt buộc
cần tây39/celery_tutorial tại celery-fib · bennett39/celery39
hướng dẫn cần tây. Đóng góp cho sự phát triển bennett39/celery39 bằng cách tạo một tài khoản trên GitHub
github. com
Đảm bảo rằng bạn đang ở nhánh celery-fib
của repo đó
Tôi có một video với tất cả thông tin này, ngoài ra bạn có thể thấy ứng dụng hoạt động như thế nào
Tìm hiểu sâu hơn với máy tính FibonacciTrong bài viết này, chúng ta sẽ xây dựng một ứng dụng mẫu. Để đơn giản, nhiệm vụ “chạy dài” của chúng ta sẽ là tính toán Fibonacci
Đừng lo nếu bạn chưa biết về Fibonacci. Nó không thực sự quan trọng — chỉ là một nhiệm vụ giả cho ứng dụng mẫu của chúng tôi để tính toán và lưu trữ kết quả
Điều quan trọng cần biết là — được triển khai một cách ngây thơ — máy tính Fibonacci có thể hơi kém hiệu quả
- Các số Fibonacci lớn hơn có thể mất nhiều thời gian hơn để tính toán
- Các số Fibonacci nhỏ hơn tương đối nhanh để tính toán
Chúng tôi sẽ sử dụng đặc điểm này của thuật toán để tạo lợi thế cho mình để chúng tôi có thể tạo các tác vụ khác nhau nhanh hoặc chậm để Celery xử lý
Một lưu ý về DjangoVì đây không phải là hướng dẫn về Django nên tôi sẽ bỏ qua phần chúng ta xây dựng ứng dụng Django
Nếu bạn cần trợ giúp với Django, tôi có rất nhiều tài nguyên
Cách tạo một dự án Django trong 5 phút
Thật dễ dàng để bắt đầu phát triển ở Django
bennettgarner. Trung bình. com
Bắt đầu với một ứng dụng Django mẫuỨng dụng ví dụ tôi đã tạo RẤT đơn giản với giao diện người dùng đơn giản và chỉ có một tính năng. tính số Fibonacci
Nó trông như thế này
Ứng dụng ví dụ — không đẹp, nhưng nó hoạt động
Bạn có thể xem kết quả tính toán của tôi. Ví dụ
- Số Fibonacci thứ nhất là 1
- Số Fibonacci thứ 5 là 5
Ở đầu ứng dụng, bạn có thể thấy liên kết đến “Bắt đầu phép tính mới. ” Điều đó đưa bạn đến một biểu mẫu để bắt đầu một nhiệm vụ mới
Biểu mẫu barebones để bắt đầu một nhiệm vụ mới
Việc tính toán số Fibonacci thứ 37 có thể mất nhiều thời gian. Máy chủ web của tôi thậm chí có thể hết thời gian
Chúng ta có thể làm gì?
Kiến trúc một giải pháp với CeleryCho đến nay, ứng dụng Django của chúng tôi có kiến trúc như sau
- Máy chủ web [Django]
- Cơ sở dữ liệu [SQLite]
Để xử lý các tác vụ ở chế độ nền, chúng tôi sẽ cần thêm công nhân Celery. Chúng tôi cũng sẽ cần thêm một hàng đợi nơi chúng tôi có thể thêm các tác vụ
Celery sẽ chạy máy chủ của riêng mình, với tính năng xử lý đồng thời được tích hợp tự động. Chúng tôi sẽ sử dụng máy chủ Redis làm hàng đợi để theo dõi các tin nhắn qua lại giữa Django và Celery
Kiến trúc mới của chúng tôi trông như thế này
- Máy chủ web [Django]
- Cơ sở dữ liệu [SQLite]
- Hàng đợi tin nhắn [Redis]
- Máy chủ công nhân [Celery] — chạy đồng thời 12
Vì vậy, trên một máy chủ công nhân, có 12 "quy trình" công nhân có thể nhận các tác vụ mới. Tổng cộng chúng ta có thể chạy 12 tác vụ cùng lúc
Đặt nó tất cả cùng nhau. Django + Cần tây + RedisVì vậy, làm thế nào để tất cả làm việc cùng nhau?
- Django thêm nhiệm vụ vào hàng đợi trong Redis. Khi người dùng yêu cầu phép tính Fibonacci, Django sẽ tạo một tải trọng cho biết tất cả thông tin về tác vụ và thêm tải trọng đó vào Redis
- Tác vụ nằm trong hàng đợi Redis theo thứ tự vào trước, ra trước [FIFO]. Nó vẫn ở trong hàng đợi cho đến khi có worker process để hoàn thành tác vụ
- Khi có bất kỳ quy trình nào trong số 12 quy trình công nhân của Celery, nó sẽ bật tác vụ tiếp theo ra khỏi hàng đợi. Redis được thiết kế sao cho việc đưa một tác vụ ra khỏi hàng đợi là nguyên tử và không có xung đột, vì vậy các worker không thể vô tình nhận cùng một tác vụ
- Khi một công nhân khác có sẵn, nó sẽ bật tác vụ tiếp theo ra khỏi hàng đợi. Không quan trọng những công nhân khác đang làm gì hoặc họ đã hoàn thành công việc của mình hay chưa. Mỗi công nhân hoạt động độc lập
- Nếu một nhiệm vụ mất nhiều thời gian hơn nhiệm vụ khác, thì nó sẽ mất nhiều thời gian hơn. Tất cả các công nhân tiếp tục làm việc trên các nhiệm vụ, đưa các nhiệm vụ mới ra khỏi hàng đợi và một nhiệm vụ chạy dài chỉ làm chậm một công nhân đang làm việc với nó
- Khi công nhân hoàn thành phép tính Fibonacci, nó sẽ lưu kết quả vào cơ sở dữ liệu
Tôi đã tạo một mô hình Django để theo dõi các tác vụ tính toán và trạng thái của chúng. Mô hình trông như thế này
Có một tùy chọn cho Calculation.equation
. Ngay bây giờ, phương trình duy nhất chúng ta có thể thực hiện là phép tính FIB
. Trong tương lai, chúng ta có thể mở rộng ứng dụng này để cho phép tính các dạng phương trình khác
Lưu ý rằng trường Calculation.status
bao gồm một số trạng thái. PENDING
, ERROR
và SUCCESS
. Chúng tôi sẽ sử dụng trường trạng thái để theo dõi các tính toán khác nhau mà chúng tôi đang thực hiện
Khi người dùng muốn bắt đầu một phép tính mới, đây là điều sẽ xảy ra
- Người dùng NHẬN trang. Cái này gọi phương thức
get[]
và hiển thị biểu mẫu - Người dùng POST biểu mẫu với một số. Nội dung biểu mẫu có sẵn trong
request.POST
— cảm ơn Django - Chúng tôi sử dụng số mà người dùng đã đăng để tạo một đối tượng
celery-fib
0 mới. Nó cócelery-fib
1 ,celery-fib
2 vàcelery-fib
3 - Chúng tôi gọi
celery-fib
4 - đây là nơi chúng tôi bắt đầu sử dụng Cần tây. Phương thứccelery-fib
5 nói với Celery, “Này, xử lý điều này một cách không đồng bộ ở chế độ nền, bất cứ khi nào có một worker sẵn sàng”
Lưu ý rằng chúng tôi đã nhập celery-fib
6 ở đầu tệp. Vì vậy, chúng tôi đang gọi một số mã khác và gửi một đối số của celery-fib
7 cho đối tượng Tính toán mới mà chúng tôi vừa tạo
Chúng ta hãy nhìn vào celery-fib
6…
Tệp này trông hơi quen thuộc vì nó bao gồm việc triển khai thuật toán Fibonacci của chúng tôi
Bên dưới hàm celery-fib
9, chúng ta có celery-fib
6, định nghĩa của nhiệm vụ Celery của chúng ta. Một số điều cần chú ý
- Trên dòng 18, chúng tôi sử dụng trình trang trí
Calculation.equation
1 để xác định tác vụ Celery mới. Nhiệm vụ được đăng ký tự động với ứng dụng Celery của chúng tôi [được xác định ở nơi khác].Calculation.equation
2 cho phép chúng tôi chấp nhậnCalculation.equation
3 làm đối số đầu tiên cho tác vụ và cập nhật trạng thái tác vụ hoặc thử lại tác vụ từ bên trong tác vụ. Tôi có xu hướng luôn bao gồmCalculation.equation
4 trong các nhiệm vụ Cần tây của mình - Tác vụ chấp nhận
Calculation.equation
3 vàCalculation.equation
6 làm đối số. Khi nhân viên lấy tác vụ từ hàng đợi, tải trọng sẽ bao gồm định nghĩa tác vụ vàcelery-fib
7 cho phiên bản mô hình mà chúng tôi muốn làm việc với - Điều đầu tiên chúng tôi làm là tải đối tượng
celery-fib
0 từ cơ sở dữ liệu trên dòng 21. Đây là một mô hình phổ biến trong Cần tây. Không bao giờ sử dụng một phiên bản mô hình trong bộ nhớ làm đối số cho tác vụ. Thay vào đó, hãy luôn sử dụng ID và tải lại phiên bản từ đĩa. Vì chúng tôi không biết chính xác khi nào tác vụ sẽ hoàn thành, nên chúng tôi không thể tin rằng phiên bản trong bộ nhớ đã được cập nhật. Luôn tải lại mô hình từ cơ sở dữ liệu - Tiếp theo, trong khối
Calculation.equation
9, chúng tôi cố gắng tính kết quả. Nếu thành công, chúng tôi cập nhậtFIB
0 và đặtCalculation.status
thànhSUCCESS
. Nếu có lỗi, hãy cập nhật trạng thái tương ứng và bao gồm thông báo lỗi trên đối tượngcelery-fib
0 - Cuối cùng, trên dòng 30, cam kết các thay đổi đối với cơ sở dữ liệu và kết thúc tác vụ
Đây là phần nhàm chán. Có một số bước cấu hình quan trọng để Celery hoạt động. Phần lớn cấu hình là bản soạn sẵn và sẽ giống nhau mọi lúc
Tôi đã minh họa cách thiết lập Celery trong hướng dẫn Celery đầu tiên, vì vậy tôi sẽ không xem lại ở đây. Nếu bạn đang tìm cách thiết lập Celery từ đầu trong một dự án, thì đây là hướng dẫn dành cho bạn
hướng dẫn cần tây. Công nghệ phải học dành cho nhà phát triển Python
Công nhân để xử lý các tác vụ trong nền là công cụ thiết yếu và mạnh mẽ trong bộ công cụ của bất kỳ nhà phát triển nào
Trung bình. com
Tôi sẽ chỉ nói rằng có nội dung cấu hình tiêu chuẩn trong tệp FIB
4 và FIB
5 trong repo đính kèm — không khác gì hướng dẫn ở trên. Nó đây, nếu bạn muốn/cần xem qua
cần tây39/cần tây. py at celery-fib · bennett39/celery39
Bạn không thể thực hiện hành động đó vào lúc này. Bạn đã đăng nhập bằng tab hoặc cửa sổ khác. Bạn đã đăng xuất trong một tab khác hoặc…
github. com
Hãy bỏ qua trước những điều thú vị
dùng thửHãy nhớ rằng chúng tôi có một vài phần khác nhau trong kiến trúc của chúng tôi. Chúng ta cần khởi động tất cả
- Chạy Django với
FIB
6 [Khi được triển khai vào sản xuất, chúng tôi sẽ sử dụng một lệnh khác. Hiện tại, điều này hoạt động. ] - Khởi động máy chủ Redis. Tại địa phương, bạn cần cài đặt Redis và sau đó sử dụng
FIB
7 để khởi động nó - Ra mắt công nhân Celery để nhận nhiệm vụ. Sử dụng repo mẫu, lệnh là
FIB
8 - Chúng tôi cũng cần cơ sở dữ liệu. Vì ứng dụng mẫu sử dụng cơ sở dữ liệu hệ thống tệp SQLite nên chúng tôi không cần chạy máy chủ cho ứng dụng đó. Nếu bạn có một ứng dụng sử dụng cơ sở dữ liệu khác, đừng quên chạy cả máy chủ đó
Đây là giao diện máy chủ của chúng tôi đang chạy cục bộ
Redis, Django và Celery đều đang chạy trên máy tính của tôi. Hãy chạy một số tác vụ nền
Bây giờ hãy xem những gì Celery có thể làm. Bắt đầu tính toán số Fibonacci đầu tiên
Phép tính này sẽ khá tức thời, nhưng để minh họa, tôi đã tạm dừng Celery để chúng tôi có thể xem tác vụ đang chờ xử lý trước khi nó được xử lý
Khi tôi bỏ tạm dừng Celery, nó sẽ thấy ngay nhiệm vụ mới trong hàng đợi. Một công nhân nhặt nó lên và hoàn thành nhiệm vụ trong tích tắc
Quay lại ứng dụng, chúng ta có thể thấy phép tính đã hoàn thành thành công và đưa kết quả vào cơ sở dữ liệu
Ngọt. Nó đang hoạt động. Một nhân viên Celery vừa hoàn thành phép tính và máy chủ web Django của chúng tôi không phải làm bất cứ điều gì
Bây giờ, hãy thêm đồng thờiLý do thực sự để sử dụng Celery là để chạy đồng thời nhiều tác vụ trong nền. Vì vậy, hãy thử nó ra
Hãy bắt đầu một loạt phép tính — một số dài hơn, một số ngắn hơn. Hãy thử các số Fibonacci thứ 39, 4, 6 và 32
Một lần nữa, khi chúng tôi thêm các tác vụ mới vào hàng đợi, chúng được đánh dấu là đang chờ xử lý
Nhiệm vụ đầu tiên của tôi. Quá trình này có thể mất một chút thời gian vì số Fibonacci thứ 39 khá lớn
Celery sẽ tính toán nhiệm vụ thứ hai độc lập với nhiệm vụ thứ nhất bằng một worker process riêng biệt. Phép tính đơn giản này sẽ nhanh hơn nhiều và hoàn thành trước nhiệm vụ đầu tiên của chúng ta
Tôi đã thêm tác vụ thứ ba và Celery đã tính toán nhanh hơn tốc độ tải trang của tôi. Lưu ý cách cả hai nhiệm vụ sau đều hoàn thành, trong khi nhiệm vụ đầu tiên vẫn đang chờ xử lý. Đây là điều kỳ diệu của công việc nền, không đồng bộ
Hãy thử thêm một nhiệm vụ nữa. Cái này cũng sẽ mất nhiều thời gian hơn để hoàn thành. Hãy xem cái nào về đích trước?
Nhìn lại nhật ký, chúng ta có thể thấy Celery nhận và hoàn thành các nhiệm vụ khác nhau
Nhiệm vụ có ID FIB
9 là nhiệm vụ đầu tiên chúng tôi xếp hàng, nhưng lại là nhiệm vụ cuối cùng hoàn thành. Mất 18 giây để tính số Fibonacci thứ 39
Ngược lại, nhiệm vụ Calculation.status
0 là nhiệm vụ cuối cùng chúng tôi xếp hàng và nó đã hoàn thành trước FIB
9. Chỉ mất 0. 7 giây để tính số Fibonacci thứ 32. [Có vẻ như thuật toán của chúng ta có độ phức tạp bậc hai nhỉ? 😉]
Và đây là kết quả
Xem trực tiếp
Để xem nó hoạt động, hãy xem video này. Tôi đã thêm dấu thời gian vào video nên bạn có thể bỏ qua phần mà chúng ta đang tìm hiểu về các tác vụ Fibonacci
Cố gắng mô tả Cần tây trong văn bản thực sự khó khăn. Nó có ý nghĩa hơn khi bạn nhìn thấy nó trực tiếp
Trong video mình còn chạy thêm rất nhiều phép tính. Vì vậy, bạn có thể tìm hiểu thêm về các số Fibonacci
Cần tây - một công cụ thiết yếuMặc dù máy tính Fibonacci là một ví dụ ngớ ngẩn, nhưng hy vọng bạn có thể hiểu được mức độ hữu ích của các tác vụ nền
Chúng tôi giải phóng máy chủ web của mình khỏi những công việc nặng nhọc. Thay vào đó, chúng ta có thể hoàn thành công việc song song ở hậu trường. Trong các ứng dụng sản xuất, công việc nền có thể có các dạng
- Chuyển đổi dữ liệu chuyên sâu
- Email, thông báo và tin nhắn được xếp hàng đợi
- Công việc theo lịch trình mỗi ngày, tuần hoặc tháng
- Lưu dữ liệu phân tích vào cơ sở dữ liệu hoặc hệ thống bên ngoài
- Chạy sao lưu tự động
- Đang chờ yêu cầu tới các API bên ngoài
Nó siêu hữu ích. Đối với các nhà phát triển web Python, Celery là một công cụ thiết yếu để xây dựng các ứng dụng hiện đại, có thể mở rộng. Bây giờ bạn đã thấy nó hoạt động, hãy thử tự mình xây dựng thứ gì đó với nó