Hướng dẫn php handle long process - xử lý php quá trình dài

89

Mới! Lưu câu hỏi hoặc câu trả lời và sắp xếp nội dung yêu thích của bạn. Tìm hiểu thêm.
Learn more.

Tôi có một tập lệnh PHP mất nhiều thời gian [5-30 phút] để hoàn thành. Chỉ trong trường hợp nó quan trọng, tập lệnh đang sử dụng Curl để cạo dữ liệu từ một máy chủ khác. Đây là lý do nó mất quá nhiều thời gian; Nó phải chờ mỗi trang tải trước khi xử lý nó và chuyển sang trang tiếp theo.

Tôi muốn có thể bắt đầu tập lệnh và để nó cho đến khi hoàn thành, nó sẽ đặt cờ trong bảng cơ sở dữ liệu.

Những gì tôi cần biết là làm thế nào để có thể kết thúc yêu cầu HTTP trước khi tập lệnh được hoàn thành. Ngoài ra, có phải là một tập lệnh PHP là cách tốt nhất để làm điều này?

hỏi ngày 6 tháng 2 năm 2010 lúc 9:16Feb 6, 2010 at 9:16

Kbanmankbanmankbanman

4.1736 Huy hiệu vàng31 Huy hiệu bạc40 Huy hiệu đồng6 gold badges31 silver badges40 bronze badges

2

Chắc chắn nó có thể được thực hiện với PHP, tuy nhiên bạn không nên làm điều này như một nhiệm vụ nền - quy trình mới phải được phân tách khỏi nhóm quy trình nơi nó được bắt đầu.

Vì mọi người tiếp tục đưa ra câu trả lời sai tương tự cho Câu hỏi thường gặp này, tôi đã viết một câu trả lời đầy đủ hơn ở đây:

//symcbean.blogspot.com/2010/02/php-and-long-running-processes.html

Từ các ý kiến:

Phiên bản ngắn là shell_exec['echo /usr/bin/php -q longThing.php | at now']; nhưng lý do "tại sao", hơi dài để đưa vào đây.

Cập nhật +12 năm

Mặc dù đây vẫn là một cách tốt để gọi một chút mã chạy dài, nhưng việc bảo mật sẽ hạn chế hoặc thậm chí vô hiệu hóa khả năng của PHP trong máy chủ web để khởi chạy các tệp thực thi khác. Và vì điều này phân tách hành vi của việc chạy nhật ký từ đó đã bắt đầu nó, trong nhiều trường hợp, có thể thích hợp hơn khi sử dụng một công việc daemon hoặc cron.

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 23:35Feb 6, 2010 at 23:35

Symcbeansymcbeansymcbean

47K6 Huy hiệu vàng57 Huy hiệu bạc90 Huy hiệu Đồng6 gold badges57 silver badges90 bronze badges

14

Cách nhanh chóng và bẩn sẽ là sử dụng chức năng ignore_user_abort trong PHP. Điều này về cơ bản nói: Không quan tâm người dùng làm gì, hãy chạy tập lệnh này cho đến khi nó được hoàn thành. Điều này có phần nguy hiểm nếu đó là một trang web đối diện công cộng [vì có thể, cuối cùng bạn có 20 phiên bản của tập lệnh chạy cùng một lúc nếu nó được bắt đầu 20 lần].

Cách "sạch" [ít nhất là IMHO] là đặt cờ [ví dụ như trong DB] khi bạn muốn bắt đầu quy trình và chạy cronjob mỗi giờ [hoặc hơn] để kiểm tra xem cờ đó có được đặt không. Nếu nó được đặt, tập lệnh chạy dài bắt đầu, nếu nó không được đặt, không phải là điều xảy ra.

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 9:26Feb 6, 2010 at 9:26

FlorianhflorianhFlorianH

3.0341 Huy hiệu vàng18 Huy hiệu bạc15 Huy hiệu đồng1 gold badge18 silver badges15 bronze badges

2

Bạn có thể sử dụng EXEC hoặc hệ thống để bắt đầu một công việc nền, sau đó thực hiện công việc đó.

Ngoài ra, có những cách tiếp cận tốt hơn để quét web mà bạn đang sử dụng. Bạn có thể sử dụng một cách tiếp cận luồng [nhiều luồng thực hiện một trang cùng một lúc] hoặc một lần sử dụng Eventloop [một chủ đề thực hiện nhiều trang tại thời điểm]. Cách tiếp cận cá nhân của tôi bằng cách sử dụng Perl sẽ sử dụng bất kỳ :: http.

ETA: Symcbean giải thích cách tách quá trình nền đúng cách ở đây.

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 9:49Feb 6, 2010 at 9:49

Leon Timmermansleon TimmermansLeon Timmermans

29,9k2 Huy hiệu vàng63 Huy hiệu bạc110 Huy hiệu Đồng2 gold badges63 silver badges110 bronze badges

1

Không, PHP không phải là giải pháp tốt nhất.

Tôi không chắc chắn về Ruby hay Perl, nhưng với Python, bạn có thể viết lại cào trên trang của mình để được nhiều luồng và nó có thể sẽ chạy nhanh hơn ít nhất 20 lần. Viết các ứng dụng đa luồng có thể là một thách thức, nhưng ứng dụng Python đầu tiên tôi đã viết là máy quét trang Mutlti-Thread. Và bạn có thể chỉ cần gọi tập lệnh Python từ trong trang PHP của mình bằng cách sử dụng một trong các hàm thực thi shell.

Rộng

12.7k6 Huy hiệu vàng39 Huy hiệu bạc63 Huy hiệu Đồng6 gold badges39 silver badges63 bronze badges

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 9:35Feb 6, 2010 at 9:35

Jamiebjamiebjamieb

9.69713 Huy hiệu vàng46 Huy hiệu bạc62 Huy hiệu Đồng13 gold badges46 silver badges62 bronze badges

4

Có, bạn có thể làm điều đó trong PHP. Nhưng ngoài PHP, sẽ là khôn ngoan khi sử dụng Trình quản lý hàng đợi. Đây là chiến lược:

  1. Chia nhỏ nhiệm vụ lớn của bạn thành các nhiệm vụ nhỏ hơn. Trong trường hợp của bạn, mỗi nhiệm vụ có thể tải một trang duy nhất.

  2. Gửi từng nhiệm vụ nhỏ đến hàng đợi.

  3. Chạy nhân viên xếp hàng của bạn ở đâu đó.

Sử dụng chiến lược này có những lợi thế sau:

  1. Đối với các nhiệm vụ chạy dài, nó có khả năng phục hồi trong trường hợp một vấn đề nghiêm trọng xảy ra ở giữa cuộc chạy - không cần phải bắt đầu từ đầu.

  2. Nếu các tác vụ của bạn không phải chạy tuần tự, bạn có thể chạy nhiều công nhân để chạy các tác vụ cùng một lúc.

Bạn có nhiều tùy chọn khác nhau [đây chỉ là một vài]:

  1. RabbitMQ [//www.rabbitmq.com/tutorials/tutorial-one-phph.html]
  2. Zeromq [//zeromq.org/bindings:php]
  3. Nếu bạn đang sử dụng khung Laravel, hàng đợi được tích hợp [//laravel.com/docs/5.4/queues], với trình điều khiển cho AWS SES, Redis, Beanstalkd

Đã trả lời ngày 23 tháng 5 năm 2017 lúc 5:06May 23, 2017 at 5:06

Aljo Faljo faljo f

2.28021 Huy hiệu bạc22 Huy hiệu đồng21 silver badges22 bronze badges

PHP có thể hoặc không phải là công cụ tốt nhất, nhưng bạn biết cách sử dụng nó và phần còn lại của ứng dụng của bạn được viết bằng cách sử dụng nó. Hai phẩm chất này, kết hợp với thực tế là PHP là "đủ tốt" tạo ra một trường hợp khá mạnh để sử dụng nó, thay vì Perl, Ruby hoặc Python.

Nếu mục tiêu của bạn là học một ngôn ngữ khác, thì hãy chọn một ngôn ngữ và sử dụng nó. Bất kỳ ngôn ngữ bạn đã đề cập sẽ làm công việc, không có vấn đề. Tôi tình cờ thích Perl, nhưng những gì bạn thích có thể khác.

Symcbean có một số lời khuyên tốt về cách quản lý các quy trình nền tại liên kết của mình.

Nói tóm lại, viết một tập lệnh CLI PHP để xử lý các bit dài. Hãy chắc chắn rằng nó báo cáo trạng thái theo một cách nào đó. Tạo một trang PHP để xử lý các bản cập nhật trạng thái, bằng cách sử dụng AJAX hoặc các phương thức truyền thống. Tập lệnh khởi động của bạn sẽ bắt đầu quá trình chạy trong phiên riêng của mình và trả về xác nhận rằng quá trình này đang diễn ra.

Chúc may mắn.

Đã trả lời ngày 8 tháng 2 năm 2010 lúc 6:28Feb 8, 2010 at 6:28

Daotoaddaotoaddaotoad

26.4K7 Huy hiệu vàng58 Huy hiệu bạc99 Huy hiệu đồng7 gold badges58 silver badges99 bronze badges

Tôi đồng ý với các câu trả lời nói rằng điều này nên được chạy trong một quy trình nền. Nhưng điều quan trọng là bạn phải báo cáo về trạng thái để người dùng biết rằng công việc đang được thực hiện.

Khi nhận được yêu cầu PHP để khởi động quy trình, bạn có thể lưu trữ trong cơ sở dữ liệu đại diện cho nhiệm vụ với một định danh duy nhất. Sau đó, bắt đầu quá trình xẹp màn hình, chuyển nó là định danh duy nhất. Báo cáo lại cho ứng dụng iPhone rằng tác vụ đã được bắt đầu và nó nên kiểm tra một URL được chỉ định, chứa ID tác vụ mới, để có trạng thái mới nhất. Ứng dụng iPhone hiện có thể thăm dò ý kiến ​​[hoặc thậm chí "Thăm dò ý kiến ​​dài"] URL này. Trong khi đó, quy trình nền sẽ cập nhật biểu diễn cơ sở dữ liệu của tác vụ khi nó hoạt động với tỷ lệ phần trăm hoàn thành, bước hiện tại hoặc bất kỳ chỉ số trạng thái nào khác bạn muốn. Và khi nó đã hoàn thành, nó sẽ đặt một lá cờ hoàn thành.

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 19:58Feb 6, 2010 at 19:58

JacobjacobJacob

76.3K24 Huy hiệu vàng146 Huy hiệu bạc226 Huy hiệu Đồng24 gold badges146 silver badges226 bronze badges

Bạn có thể gửi nó dưới dạng yêu cầu XHR [AJAX]. Khách hàng thường không có thời gian chờ cho XHR, không giống như các yêu cầu HTTP thông thường.

Đã trả lời ngày 6 tháng 2 năm 2010 lúc 23:51Feb 6, 2010 at 23:51

JaljalJAL

21.1k1 Huy hiệu vàng46 Huy hiệu bạc66 Huy hiệu đồng1 gold badge46 silver badges66 bronze badges

Tôi nhận ra đây là một câu hỏi khá cũ nhưng muốn cho nó một phát súng. Kịch bản này cố gắng giải quyết cả cuộc gọi khởi động ban đầu để hoàn thành nhanh chóng và cắt giảm tải nặng thành các khối nhỏ hơn. Tôi đã không kiểm tra giải pháp này.


            

testpage.php

    

PS: Nếu bạn muốn gửi các tham số URL dưới dạng vòng lặp thì hãy theo dõi câu trả lời này: //stackoverflow.com/a/41225209/6295712

Đã trả lời ngày 19 tháng 12 năm 2016 lúc 15:32Dec 19, 2016 at 15:32

Hassan Saeedhassan SaeedHassan Saeed

5.3631 Huy hiệu vàng 30 Huy hiệu bạc35 Huy hiệu Đồng1 gold badge30 silver badges35 bronze badges

Không phải là cách tiếp cận tốt nhất, như nhiều người đã nêu ở đây, nhưng điều này có thể giúp ích:

ignore_user_abort[1]; // run script in background even if user closes browser
set_time_limit[1800]; // run it for 30 minutes

// Long running script here

Đã trả lời ngày 29 tháng 1 năm 2019 lúc 19:27Jan 29, 2019 at 19:27

Lucas Bustamantelucas BustamanteLucas Bustamante

Phù vàng 14.6K7 Huy hiệu vàng82 Huy hiệu đồng7 gold badges82 silver badges81 bronze badges

Nếu đầu ra mong muốn của tập lệnh của bạn là một số xử lý, không phải là một trang web, thì tôi tin rằng giải pháp mong muốn là chạy tập lệnh của bạn từ shell, chỉ đơn giản là

php my_script.php

Đã trả lời ngày 13 tháng 9 năm 2019 lúc 9:35Sep 13, 2019 at 9:35

MrmartinmrmartinMrMartin

3734 Huy hiệu bạc18 Huy hiệu đồng4 silver badges18 bronze badges

Bài Viết Liên Quan

Chủ Đề