Thứ năm, 19/12/2013 | 00:00 GMT+7

Cách sử dụng Celery với RabbitMQ để xếp hàng các tác vụ trên Ubuntu VPS

Xử lý không đồng bộ, hoặc không chặn là một phương pháp tách việc thực hiện các việc nhất định khỏi stream chính của chương trình. Điều này cung cấp cho bạn một số lợi thế, bao gồm cho phép mã hướng tới user của bạn chạy mà không bị gián đoạn.


Truyền thông điệp là một phương thức mà các thành phần chương trình có thể sử dụng để giao tiếp và trao đổi thông tin. Nó có thể được triển khai đồng bộ hoặc không đồng bộ và có thể cho phép các quá trình rời rạc giao tiếp mà không gặp vấn đề gì. Truyền thông điệp thường được triển khai như một giải pháp thay thế cho database truyền thống cho kiểu sử dụng này vì hàng đợi thông báo thường triển khai các tính năng bổ sung, tăng hiệu suất và có thể nằm hoàn toàn trong bộ nhớ.

Celery là một hàng đợi nhiệm vụ được xây dựng trên hệ thống truyền thông điệp không đồng bộ. Nó được dùng như một container các việc lập trình có thể được kết xuất. Chương trình đã vượt qua nhiệm vụ có thể tiếp tục thực thi và hoạt động một cách đáp ứng, và sau đó, nó có thể thăm dò ý kiến của cần tây để xem tính toán đã hoàn tất chưa và truy xuất dữ liệu.

Mặc dù cần tây được viết bằng Python, nhưng giao thức của nó có thể được thực hiện bằng bất kỳ ngôn ngữ nào. Nó thậm chí có thể hoạt động với các ngôn ngữ khác thông qua webhook.

Bằng cách triển khai hàng đợi công việc vào môi trường chương trình của bạn, bạn có thể dễ dàng giảm tải các việc và tiếp tục xử lý các tương tác từ user của bạn . Đây là một cách đơn giản để tăng khả năng đáp ứng của các ứng dụng của bạn và không bị khóa khi thực hiện các phép tính trong thời gian dài.

Trong hướng dẫn này, ta sẽ cài đặt và triển khai hàng đợi công việc cần tây bằng cách sử dụng RabbitMQ làm hệ thống nhắn tin trên Ubuntu 12.04 VPS.

Cài đặt các thành phần


Cài đặt Celery


Celery được viết bằng Python và như vậy, nó dễ dàng cài đặt theo cách giống như cách ta xử lý các gói Python thông thường.

Ta sẽ tuân theo các quy trình được khuyến khích để xử lý các gói Python bằng cách tạo một môi trường ảo để cài đặt hệ thống nhắn tin của ta . Điều này giúp ta giữ môi trường ổn định và không ảnh hưởng đến hệ thống lớn hơn.

Cài đặt gói môi trường ảo Python từ repository mặc định của Ubuntu:

sudo apt-get update sudo apt-get install python-virtualenv 

Ta sẽ tạo một folder nhắn tin nơi ta sẽ triển khai hệ thống của bạn :

mkdir ~/messaging cd ~/messaging 

Bây giờ ta có thể tạo một môi trường ảo nơi ta có thể cài đặt cần tây bằng cách sử dụng lệnh sau:

virtualenv --no-site-packages venv 

Với môi trường ảo được cấu hình , ta có thể kích hoạt nó bằng lệnh :

source venv/bin/activate 

Dấu nhắc của bạn sẽ thay đổi để phản ánh rằng bạn hiện đang hoạt động trong môi trường ảo mà ta đã thực hiện ở trên. Điều này sẽ đảm bảo các gói Python của ta được cài đặt local thay vì global .

Nếu bất kỳ lúc nào ta cần hủy kích hoạt môi trường (không phải bây giờ), có thể chạy lệnh:

deactivate 

Bây giờ ta đã kích hoạt môi trường, ta có thể cài đặt cần tây bằng pip:

pip install celery 

Cài đặt RabbitMQ


Celery yêu cầu một tác nhân nhắn tin để xử lý các yêu cầu từ một nguồn bên ngoài. Đại lý này được gọi là “nhà broker ”.

Có khá nhiều tùy chọn cho các nhà broker có sẵn để lựa chọn, bao gồm database quan hệ, database NoSQL, kho key-value và hệ thống nhắn tin thực tế.

Ta sẽ cấu hình cần tây để sử dụng hệ thống nhắn tin RabbitMQ, vì nó cung cấp hiệu suất mạnh mẽ, ổn định và tương tác tốt với cần tây. Đây là một giải pháp tuyệt vời vì nó bao gồm các tính năng phù hợp với mục đích sử dụng của ta .

Ta có thể cài đặt RabbitMQ thông qua repository của Ubuntu:

sudo apt-get install rabbitmq-server 

Dịch vụ RabbitMQ được khởi động tự động trên server của ta khi cài đặt.

Tạo một version cần tây


Để sử dụng khả năng xếp hàng tác vụ của cần tây, bước đầu tiên của ta sau khi cài đặt phải tạo một version cần tây. Đây là một quá trình đơn giản để nhập gói, tạo một “ứng dụng”, sau đó cài đặt các việc mà cần tây có thể thực thi trong nền.

Hãy tạo một tập lệnh Python bên trong folder nhắn tin của ta có tên là tasks.py nơi ta có thể xác định các việc mà nhân viên của ta có thể thực hiện.

sudo nano ~/messaging/tasks.py 

Điều đầu tiên ta nên làm là nhập hàm Celery từ gói celery:

from celery import Celery 

Sau đó, ta có thể tạo một version ứng dụng cần tây kết nối với dịch vụ RabbitMQ mặc định:

from celery import Celery  app = Celery('tasks', backend='amqp', broker='amqp://') 

Đối số đầu tiên của hàm Celery là tên sẽ được thêm vào trước các việc để xác định chúng.

Tham số backend là một tham số tùy chọn cần thiết nếu bạn muốn truy vấn trạng thái của nhiệm vụ nền hoặc truy xuất kết quả của nó.

Nếu nhiệm vụ của bạn chỉ đơn giản là các hàm thực hiện một số công việc và sau đó thoát ra, mà không trả về giá trị hữu ích để sử dụng trong chương trình của bạn, bạn có thể bỏ tham số này. Nếu chỉ một số tác vụ của bạn yêu cầu chức năng này, hãy kích hoạt nó tại đây và ta có thể vô hiệu hóa nó theo từng trường hợp cụ thể hơn nữa.

Tham số broker chỉ định URL cần thiết để kết nối với nhà broker của ta . Trong trường hợp của ta , đây là dịch vụ RabbitMQ đang chạy trên server của ta . RabbitMQ hoạt động bằng cách sử dụng một giao thức gọi là “amqp”. Nếu RabbitMQ đang hoạt động theo cấu hình mặc định của nó, celery có thể kết nối không có thông tin nào khác ngoài schemas amqp:// .

Xây dựng công việc cần tây


Vẫn còn trong file này, bây giờ ta cần thêm các nhiệm vụ của bạn .

Mỗi tác vụ cần tây phải được giới thiệu với decorator @app.task . Điều này cho phép cần tây xác định các chức năng mà nó có thể thêm các chức năng xếp hàng của nó vào. Sau mỗi lần trang trí, ta chỉ cần tạo một chức năng mà công nhân của ta có thể chạy.

Nhiệm vụ đầu tiên của ta sẽ là một hàm đơn giản in ra một chuỗi ra console .

from celery import Celery  app = Celery('tasks', backend='amqp', broker='amqp://')  @app.task def print_hello():     print 'hello there' 

Vì hàm này không trả về bất kỳ thông tin hữu ích nào (thay vào đó nó in ra console ), ta có thể yêu cầu celery không sử dụng phần backend để lưu trữ thông tin trạng thái về tác vụ này. Điều này ít phức tạp hơn và cần ít tài nguyên hơn.

<pre>
từ cần tây nhập khẩu Cần tây

app = Celery ('task', backend = 'amqp', broker = 'amqp: //')

@ app.task <span class = “highlight”> (bỏ qua kết quả = True) </span>
def print
hello ():
in 'xin chào ở đó'
</pre>

Tiếp theo, ta sẽ thêm một hàm khác sẽ tạo ra các số nguyên tố (lấy từ RosettaCode ). Đây có thể là một quá trình chạy lâu, vì vậy nó là một ví dụ điển hình cho cách ta có thể đối phó với các quy trình công nhân không đồng bộ khi ta đang đợi kết quả.

from celery import Celery  app = Celery('tasks', backend='amqp', broker='amqp://')  @app.task(ignore_result=True) def print_hello():     print 'hello there'  @app.task def gen_prime(x):     multiples = []     results = []     for i in xrange(2, x+1):         if i not in multiples:             results.append(i)             for j in xrange(i*i, x+1, i):                 multiples.append(j)     return results 

Vì ta quan tâm đến giá trị trả về của hàm này là gì và vì ta muốn biết khi nào nó hoàn thành (để ta có thể sử dụng kết quả, v.v.), ta không thêm tham số ignore_result vào tác vụ thứ hai này.

Lưu và đóng file .

Bắt đầu các quy trình của công nhân cần tây


Bây giờ ta có thể bắt đầu một quy trình công nhân sẽ có thể chấp nhận kết nối từ các ứng dụng. Nó sẽ sử dụng file ta vừa tạo để tìm hiểu về các việc mà nó có thể thực hiện.

Khởi động một version worker dễ dàng như gọi tên ứng dụng bằng lệnh celery. Ta sẽ bao gồm một ký tự “&” ở cuối chuỗi của ta để đặt quy trình công nhân của ta trong nền:

celery worker -A tasks & 

Thao tác này sẽ khởi động một ứng dụng, sau đó tách nó khỏi terminal , cho phép bạn tiếp tục sử dụng nó cho các việc khác.

Nếu bạn muốn bắt đầu nhiều công nhân, bạn có thể thực hiện bằng cách đặt tên cho từng công nhân với đối số -n :

celery worker -A tasks -n one.%h & celery worker -A tasks -n two.%h & 

%h sẽ được thay thế bằng tên server khi công nhân được đặt tên.

Để dừng công nhân, bạn có thể sử dụng lệnh giết. Ta có thể truy vấn id quy trình và sau đó loại bỏ công nhân dựa trên thông tin này.

ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill 

Điều này sẽ cho phép nhân viên hoàn thành nhiệm vụ hiện tại của bạn trước khi thoát.

Nếu bạn muốn tắt tất cả nhân viên mà không cần đợi họ hoàn thành nhiệm vụ của bạn , bạn có thể thực hiện:

ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill -9 

Sử dụng hàng đợi để xử lý công việc


Ta có thể sử dụng (các) quy trình worker mà ta đã tạo ra để hoàn thành công việc trong nền cho các chương trình của ta .

Thay vì tạo toàn bộ chương trình để chứng minh cách hoạt động của nó, ta sẽ khám phá các tùy chọn khác nhau trong trình thông dịch Python:

python 

Tại dấu nhắc, ta có thể nhập các chức năng của bạn vào môi trường:

from tasks import print_hello from tasks import gen_prime 

Nếu bạn kiểm tra các chức năng này, chúng dường như không có bất kỳ chức năng đặc biệt nào. Hàm đầu tiên in ra một dòng như mong đợi:

print_hello() 

hello there 

Hàm thứ hai trả về một danh sách các số nguyên tố:

primes = gen_prime(1000) print primes 

Nếu ta cung cấp cho hàm thứ hai một dải số lớn hơn để kiểm tra, việc thực thi sẽ bị treo trong khi nó tính toán:

primes = gen_prime(50000) 

Dừng việc thực thi bằng lệnh “CTRL-C”. Quá trình này rõ ràng không phải là máy tính chạy nền.

Để truy cập background worker, ta cần sử dụng phương thức .delay . Cần tây kết hợp các chức năng của ta với các khả năng bổ sung. Phương thức này được sử dụng để truyền hàm cho một worker để thực thi. Nó sẽ trở lại ngay lập tức:

primes = gen_prime.delay(50000) 

Tác vụ này hiện đang được thực thi bởi các công nhân mà ta đã bắt đầu trước đó. Bởi vì ta đã cấu hình một tham số backend cho ứng dụng của bạn , ta có thể kiểm tra trạng thái của tính toán và truy cập vào kết quả.

Để kiểm tra xem nhiệm vụ đã hoàn thành chưa, ta có thể sử dụng phương thức .ready :

primes.ready() 

False 

Giá trị “Sai” nghĩa là tác vụ vẫn đang chạy và chưa có kết quả. Khi nhận được giá trị "Đúng", ta có thể làm gì đó với câu trả lời.

primes.ready() 

True 

Ta có thể nhận được giá trị bằng cách sử dụng phương thức .get .

Nếu ta đã xác minh giá trị được tính bằng phương thức .ready , thì ta có thể sử dụng phương pháp đó như sau:

print primes.get() 

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, . . . 

Tuy nhiên, nếu bạn chưa sử dụng phương thức .ready trước khi gọi .get , rất có thể bạn muốn thêm tùy chọn “thời gian chờ” để chương trình của bạn không bị buộc phải đợi kết quả, điều này sẽ không đạt được mục đích của ta thực hiện:

print primes.get(timeout=2) 

Điều này sẽ đưa ra một ngoại lệ nếu hết thời gian mà bạn có thể xử lý trong chương trình của bạn .

Kết luận


Mặc dù đây là đủ thông tin để giúp bạn bắt đầu sử dụng cần tây trong các chương trình của bạn , nhưng nó chỉ làm xước bề mặt về chức năng đầy đủ của thư viện này. Celery cho phép bạn xâu chuỗi các nhiệm vụ nền lại với nhau, group các nhiệm vụ và kết hợp các chức năng theo những cách thú vị.

Mặc dù cần tây được viết bằng Python, nó được dùng với các ngôn ngữ khác thông qua webhook. Điều này làm cho nó cực kỳ linh hoạt để di chuyển các việc vào nền, dù ngôn ngữ bạn chọn là gì.

<div class = “author”> Bởi Justin Ellingwood </div>


Tags:

Các tin liên quan

Cách thiết lập một Honeypot Pháo binh trên VPS Ubuntu
2013-12-04
Cách triển khai Bộ sao chép trong MongoDB trên VPS Ubuntu
2013-12-03
Cách tạo một cụm Sharded trong MongoDB bằng VPS Ubuntu 12.04
2013-12-02
Cách sử dụng ApacheBench để thực hiện kiểm tra tải trên VPS Ubuntu 13.10
2013-11-25
Cách cài đặt control panel Ajenti trên Ubuntu 13.04
2013-11-12
Cách thiết lập và cài đặt Django CMS trên VPS Debian 7 hoặc Ubuntu 13
2013-11-12
Cách cài đặt Dropplets trên Ubuntu 13.04 NGINX VPS
2013-10-25
Cách sử dụng HAProxy để thiết lập cân bằng tải HTTP trên VPS Ubuntu
2013-09-26
Cách tạo Omega 4 Drupal Subtheme trên Ubuntu VPS
2013-09-26
Cách sử dụng tính năng trùng lặp với GPG để tự động hóa an toàn các bản backup trên Ubuntu
2013-09-19