Nhiệm vụ nền python

Các hệ thống chuyên ghi với cường độ lớn [như log, theo dõi,…]. Đẩy vào xử lý hàng đợi và công việc nền sẽ giảm nguy cơ quá tải cho cơ sở dữ liệu

  • Các hệ thống chuyên đọc nhưng có tính chất báo cáo, báo cáo, số lượng yêu cầu ít nhưng rất mất thời gian tổng hợp

  • Các hệ thống có thời gian phản hồi lâu vì tính chất công việc, giới hạn khách quan,… Việc phản hồi cho người dùng ngay tức thì rồi chạy trong nền sẽ giúp trải nghiệm người dùng tốt hơn. Hệ thống cũng có khả năng phục vụ nhiều người dùng hơn

  • Các công việc phát sinh từ nghiệp vụ chính, làm việc với nhiều dịch vụ bên ngoài nhưng không quan trọng. Ví dụ như thu thập lịch sử hệ thống, gửi email, cập nhật thông tin từ các nguồn,…

  • Các công việc mang tính độc lập và ít ảnh hưởng bởi dây dẫn hay thứ tự. Điều khoản bảo đảm này để có thể mở rộng hệ thống bằng cách thêm nhiều worker cùng lúc

  • Vì sao phải đến Hàng đợi
    • Hệ thống của bạn xử lý 1 công việc bị mất 0. 5 giây, không có gì phải bàn

    • Hệ thống của bạn xử lý 1 công việc mất 10 giây. Và người dùng sẽ phải ngồi nhìn trình duyệt quay trong 10s để biết có chuyện gì xảy ra tiếp theo

    • The same system at only can open 100 connection. Do đó kết nối chờ thứ 101 sẽ phải 10s,… rồi kết nối phía sau sẽ đợi, chờ đợi hoài, chờ đợi mãi,… rồi hết thời gian chờ

    • Và đó là lúc bạn phải nghĩ đến queue và background job. You only need to loss 0. 5s để ghi lại yêu cầu của khách hàng vào hàng đợi, phản hồi lại họ rằng bạn sẽ xử lý, rồi ngắt kết nối với họ và tạo các background job xử lý yêu cầu này trên worker

    Các khái niệm

    Nghề nghiệp

    Công việc là những công việc cần xử lý, ví dụ như công việc gửi email, ghi nhật ký… được thực hiện dưới nền dưới sự điều hành của công nhân

    Công nhân

    Worker là những thành phần riêng biệt và thông thường là các quy trình hoặc dịch vụ xử lý một số công việc chuyên biệt đó. Có thể có nhiều worker cùng làm việc để xử lý các công việc

    Explosion by python

    Mình sử dụng RQ [Redis Queue] để xử lý các tác vụ chạy trong nền bằng python. Thư viện này khá dễ sử dụng, và ưu điểm là nó sử dụng redis để đưa các công việc vào hàng đợi

    Cài đặt thư viện

    pip install rq
    
    6

    RQ chạy trên redis, bạn cần cài đặt Redis trước. Hướng dẫn cài đặt redis tại đây

    Tạo worker

    pip install rq
    
    7

    Giờ chúng ta chạy thử worker bằng lệnh

    pip install rq
    
    8

    Viết hàm để xử lý các công việc

    pip install rq
    
    9

    Chức năng này đơn giản chỉ là thực hiện yêu cầu đến 1 URL sau đó sẽ tính chiều dài của chuỗi trả về trong kết quả. Hàm này sẽ là hàm xử lý mỗi khi công việc được đưa vào hàng đợi

    Create queue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    0

    This Space will create a queue q with the media number to as a result of redis

    Move job to queue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    1

    Sau khi được đưa vào hàng đợi, công việc sẽ được đưa vào hàng đợi và công nhân sẽ thực hiện. You follow the worker will see the process are active

    Sau khi người lao động thực hiện xong các công việc, nó sẽ tiếp tục lắng nghe hàng đợi và xử lý khi có công việc tiếp theo. Trong 1 thời điểm, mỗi worker chỉ xử lý duy nhất 1 công việc và xử lý theo cơ chế tuần tự. Vì vậy giả sử mỗi công việc xử lý mất 5s, nếu có 10 công việc, queue sẽ mất 50s để xử lý. Do đó, có cách nào để tăng số lượng công nhân xử lý không. Câu trả lời là Có

    Tăng số lượng worker để xử lý

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    2

    Hàm này sẽ tạo ra 1 worker để xử lý, ý tưởng bây giờ là chúng ta sẽ tạo thêm nhiều process và mỗi process tương ứng với 1 worker

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    3

    Ở đây mình sử dụng 10 process tương ứng với 10 worker cùng làm việc

    Nếu quá trình chạy có lỗi hệ điều hành không cho phép python chạy đa tiến trình, bạn sẽ chạy thêm lệnh này để cho phép

    xuất OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

    Khi nào thì không nên dùng?

    Còn sau đây là những ví dụ không khuyến khích sử dụng hàng đợi và công việc nền ngoại trừ khi có kiến ​​trúc phù hợp

    • Các hệ thống chuyên đọc có tính chất hoạt động như các hệ thống đọc bài viết, sản phẩm,… Các hệ thống này sẽ được tối ưu hóa bằng con đường khác
    • Các công việc mang tính chất quan trọng, có tính quyết định nhưng thời gian phản hồi không quá dài. Ví dụ các yêu cầu liên quan đến việc thanh toán, tranh giành khóa duy nhất hệ thống [đặt chỗ, mua sản phẩm]

    One vài ví dụ thực tế

    Đây là một số hệ thống thực tế mình đã áp dụng hàng đợi và công việc nền. Các bạn có thể tham khảo để có cái nhìn sâu sắc hơn

    Trong phần này, chúng ta sẽ tìm hiểu cách xây dựng các tác vụ nền có thể thực thi độc lập với phần mềm máy chủ Web

    Để giúp các bạn dễ theo dõi, sau đây là danh sách các bài viết trong chuỗi bài hướng dẫn này

    • Phần 1. Chào thế giới
    • Phần 2. Tìm hiểu về mẫu
    • Phần 3. Tìm hiểu về Web Forms
    • Phần 4. Sử dụng cơ sở dữ liệu
    • Phần 5. Xử lý đăng nhập
    • Phần 6. Hồ sơ cá nhân và ảnh đại diện
    • Phần 7. Xử lý lỗi
    • Phần 8. Tạo chức năng theo dõi
    • Phần 9. Partition
    • Phần 10. email hỗ trợ
    • Phần 11. Nâng cấp giao diện
    • Phần 12. Xử lý thời gian
    • Phần 13. Hỗ trợ đa ngôn ngữ
    • Phần 14. Sử dụng Ajax
    • Phần 15. Tinh chỉnh cấu trúc ứng dụng
    • Phần 16. Hỗ trợ tìm kiếm hỗ trợ
    • Phần 17. Triển khai ứng dụng trên Linux
    • Phần 18. Triển khai ứng dụng với Heroku
    • Phần 19. Triển khai ứng dụng với Docker
    • Phần 20. JavaScript nâng cao
    • Phần 21. Thông báo cho người sử dụng
    • Phần 22. Tìm hiểu về nhiệm vụ nền [Bài viết này]
    • Phần 23. Xây dựng API

    Bạn có thể truy cập mã nguồn cho phần này tại GitHub

    Phần này sẽ tập trung vào các kỹ thuật cần thiết để xây dựng các tiến trình phức tạp và yêu cầu thời gian thực hiện thi dài trong ứng dụng. Các tiến trình này không thể thi hành đồng bộ với các yêu cầu từ chương trình khách [máy khách] bởi vì quá trình thực thi chúng sẽ kéo dài và sẽ không cho phép bất kỳ câu trả lời nào từ máy chủ về phía máy khách trong suốt thời gian . Trong Phần 10, chúng ta đã có dịp tìm hiểu một chút về chủ đề này khi chuyển chức năng gửi email thành một luồng [thread] chạy ở chế độ nền [background] để người dùng không phải đợi 3-4 giây mỗi lần. . Tuy nhiên, dù giải pháp này hoạt động tốt cho nhiệm vụ gửi email, nó lại không hiệu quả lắm khi các tiến trình yêu cầu thời gian thực thi dài hơn. Trong thực tế, giải pháp được sử dụng rộng rãi hơn là đưa các nhiệm vụ có thời gian thực thi dài vào các tiến trình phục vụ [worker process]

    Để minh họa cho nhu cầu về các tiến trình có thời gian thực thi dài, chúng ta sẽ tìm hiểu và xây dựng chức năng xuất tệp [export]. Chức năng này sẽ cho phép người dùng nhận được một tệp dữ liệu có chứa tất cả các bài viết của họ. Khi người dùng sử dụng chức năng này, ứng dụng sẽ khởi động tác vụ xuất tệp để tạo ra tệp JSON chứa toàn bộ bài viết của người dùng đó và gửi đến họ qua email. Tất cả các hoạt động này sẽ được diễn ra trong một tiến trình máy chủ, đồng thời hiển thị tiến độ công việc thông qua một thông báo để người dùng có thể quan sát được định mức hoàn thành theo tỷ lệ phần trăm.

    Giới thiệu về task queue [Task Queue]

    Nhiệm vụ hàng đợi là một giải pháp thuận lợi cho ứng dụng để thực thi một nhiệm vụ nhờ vào một quy trình phục vụ. Tiến trình phục vụ được thực thi độc lập với ứng dụng và thậm chí có thể được đặt trên một hệ thống khác. Giao tiếp giữa ứng dụng và trình phục vụ sẽ được thực hiện thông qua hàng đợi thông báo [hàng đợi tin nhắn]. Ứng dụng sẽ gửi công việc đến hàng đợi và theo dõi tiến trình công việc bằng cách tương tác với hàng đợi như sơ đồ sau

    Ứng dụng biến phổ biến nhất cho hàng đợi nhiệm vụ trong Python hiện nay là Celery. Đây là một ứng dụng tương đối phức tạp với nhiều tùy chọn và hỗ trợ một số kiểu hàng đợi khác nhau. Một ứng dụng hàng đợi Python phổ biến khác là Redis Queue [thường được gọi tắt là RQ] và không hoạt động bằng Celery [như chỉ hỗ trợ hàng đợi thông báo của Redis], nhưng lại dễ sử dụng hơn rất nhiều

    Cả Celery và RQ đều có thể hỗ trợ tốt cho các tác vụ nền trong ứng dụng Flask, vì vậy, chúng tôi sẽ sử dụng RQ cho ứng dụng của chúng tôi vì tính đơn giản của nó. Tuy nhiên, việc xây dựng chức năng này với Celery cũng không phải là quá khó. Nếu bạn thích sử dụng Celery hơn RQ, chúng ta có thể quay lại chủ đề này trong một bài viết khác

    Use RQ

    RQ là một gói Python chuẩn và có thể được cài đặt bằng pip

    1

    2

    [myenv] $ pip3 install rq

    [myenv] $ pip3 freeze > requirements.txt

    Như đã nói ở trên, liên lạc giữa ứng dụng và các trình phục vụ của RQ sẽ được thực hiện thông qua một hàng đợi thông báo của Redis, vì vậy bạn phải thiết lập một máy chủ Redis. Chúng ta có nhiều tùy chọn khác nhau để cài đặt và thực hiện một máy chủ Redis như là sử dụng chương trình cài đặt hoặc tải về mã nguồn và biên dịch chúng trên hệ thống của bạn. Nếu sử dụng Windows, bạn có thể tải trình cài đặt Redis server tại đây. Trên Linux, bạn có thể cài đặt thông qua các tiện ích quản lý gói tương ứng với bản phân phối Linux mà bạn đang sử dụng. Với Mac OS X, bạn có thể sử dụng lệnh brew install redis [sau khi đã cài đặt homebrew] và khởi động lại thủ công redis bằng lệnh redis-server

    Trong các hệ thống sử dụng Debian hoặc Ubuntu, bạn có thể cài đặt phần mềm Redis bằng các lệnh sau

    1

    2

    3

    $ sudo apt -y update # Cập nhật thông tin về các package trong hệ thống

    $ sudo apt -y install redis-server # Cài đặt Redis Server

    $ sudo systemctl enable --now redis-server.service # Khởi động và cho phép Redis Server tự khởi động khi khởi động.

    Sau khi khởi động, bạn chỉ cần đảm bảo rằng máy chủ đang hoạt động và cho phép truy cập RQ, ngoài ra bạn sẽ không cần phải làm gì thêm

    Cần lưu ý rằng RQ không chạy bằng trình thông dịch Python cho Windows. Nếu bạn đang sử dụng Windows, bạn cần thực thi RQ trong môi trường mô phỏng Unix. Bạn có thể làm điều này bằng một trong hai công cụ. Cygwin hoặc Hệ thống con Windows cho Linux [WSL]. Cả hai công cụ này đều tương thích với RQ

    Khởi tạo một nhiệm vụ [Tác vụ]

    Chúng ta sẽ bắt đầu bằng một ví dụ khởi động nhiệm vụ đơn giản trong RQ để bạn làm quen với nó. Một nhiệm vụ chỉ là một hàm Python. Sau đây là một ví dụ về nhiệm vụ và chúng ta sẽ đưa nó vào một mô-đun mới là ứng dụng/tác vụ. py

    ứng dụng/nhiệm vụ. py. Ví dụ về nhiệm vụ nền

    1

    2

    3

    4

    5

    6

    7

    8

    nhập thời gian

     

    def ví dụ[giây]:

        in['Bắt đầu nhiệm vụ']> từ redis nhập Redisnhập Redis

    Chủ Đề