2010-11-02 37 views
8

Tôi có một tập lệnh php chạy dưới dạng cron job thực hiện một tập hợp các tác vụ đơn giản lặp lại cho mỗi người dùng trong cơ sở dữ liệu và mất khoảng 30 phút để hoàn thành. Quá trình này bắt đầu sau mỗi giờ và cần phải nhanh chóng và hiệu quả nhất có thể. Vấn đề Im có, giống như với bất kỳ kịch bản máy chủ nào, thời gian thực hiện khác nhau và tôi cần phải tìm ra các thiết lập thời gian cron tốt nhất.Công việc Cron cho tập lệnh php yêu cầu thời gian thực thi RẤT dài

Nếu tôi chạy cron mỗi phút, tôi cần dừng vòng lặp cuối cùng của tập lệnh 20 giây trước khi kết thúc phút để đảm bảo rằng vòng lặp hiện tại kết thúc đúng lúc. Trong suốt thời gian này, điều này làm tăng thêm thời gian lãng phí.

Tôi tự hỏi nếu một ý tưởng tồi của nó là đơn giản loại bỏ giới hạn thời gian thực thi php và chạy tập lệnh một lần một giờ và để nó chạy hoàn thành .... đây có phải là một ý tưởng tồi không?

+1

Công việc cron của bạn có đang gọi một trang web chạy PHP hay sử dụng PHP từ dòng lệnh không? Tôi không hiểu hết đoạn thứ hai - tại sao bạn ngừng xử lý và khởi động lại từng phút? –

+0

Tôi nghĩ bạn có thể nhận được một số câu trả lời hiệu quả hơn ở đây nếu bạn giải thích công việc cần làm gì. Có thể có một cách hiệu quả hơn để làm điều đó. – ocodo

Trả lời

5

Giả sử bạn muốn công việc thực hiện càng sớm càng tốt, đừng sử dụng cron. Cron là tốt cho những điều cần phải xảy ra tại thời điểm cụ thể. Nó thường bị lạm dụng để mô phỏng một quá trình nền mà lý tưởng sẽ xử lý công việc ngay sau khi công việc xuất hiện. Bạn có lẽ nên viết một daemon chạy liên tục. (Lưu ý: bạn cũng có thể xem một hệ thống kiểu tin nhắn/công việc xếp hàng, cũng có những thư viện đẹp để thực hiện việc này)

Bạn có thể viết một daemon từ đầu bằng cách sử dụng pcntl functions (vì bạn không quan tâm nhiều quá trình lao động, đó là super-easy để có được một quá trình chạy ở chế độ nền.), hoặc gian lận và chỉ cần thực hiện một kịch bản mà chạy mãi mãi và chạy nó qua screen, hoặc tận dụng một số mã thư viện rắn như PEAR System:Daemon hoặc nanoserv

Khi daemonization công cụ được đưa về chăm sóc, tất cả các bạn thực sự quan tâm là có một vòng lặp chạy mãi mãi. Bạn sẽ muốn quan tâm rằng tập lệnh của bạn không bị rò rỉ bộ nhớ hoặc tiêu thụ quá nhiều tài nguyên.

Nói chung, bạn có thể làm điều gì đó như:

<?PHP 
// some setup code 
while(true){ 
    $todo = figureOutIfIHaveWorkToDo(); 
    foreach($todo as $something){ 
     //do stuff with $something 
     //remember to clean up resources so you don't leak memory! 
     usleep(/*some integer*/); 
    } 
    usleep(/* some other integer */); 
} 

Và nó sẽ làm việc khá tốt.

0

Tôi đã sử dụng giao diện dòng lệnh php cho các tác vụ chạy dài tương tự trong quá khứ. Có thể bạn không muốn xóa giới hạn thời gian thực hiện cho bất kỳ yêu cầu nào.

0

Nghe có vẻ như một ý tưởng tuyệt vời nếu có ít khả năng sẽ mất hơn một giờ. Tuy nhiên, lưu ý rằng lỗi sai có thể là cách thực sự tốt để làm cho nó mất nhiều thời gian hơn dự kiến ​​..

Để tránh tất cả các vấn đề khó chịu, bạn nên có tệp bảo vệ với ID tiến trình của tập lệnh. Khi khởi động, bạn nên kiểm tra để đảm bảo tệp không tồn tại hoặc nếu nó không tồn tại quá trình ID trong tệp (thông qua lệnh gọi (pid, 0)). Nếu các điều kiện này được đáp ứng, hãy tạo một tệp mới với PID của tập lệnh và xóa tệp khi bạn hoàn tất.

Đây là mẹo tương tự mà nhiều trình tiện ích sử dụng để đảm bảo nó chưa chạy. Nếu daemon bị chết đột ngột, tập tin sẽ vẫn tồn tại nhưng PID của quá trình đó sẽ không chạy được.

1

Đặt giới hạn thời gian thành 0 và cho phép nó thực hiện điều này là khá điển hình của cronjobs dựa trên PHP (theo kinh nghiệm của tôi), nhưng đây cũng là thời điểm bạn nên tự hỏi mình một vài câu hỏi quan trọng, chẳng hạn như "Tôi có nên viết lại công việc này bằng ngôn ngữ biên dịch? " và "Tôi có sử dụng tất cả các công cụ của tôi (cơ sở dữ liệu, v.v.) để đạt hiệu quả tối đa không?"

Điều đó nói rằng, có thể tốt hơn là loại bỏ hoàn toàn giới hạn thời gian sẽ là đặt giới hạn trên mà bạn thực sự muốn. Nếu điều đó có nghĩa là 48 phút, sau đó set_time_limit(48 * 60);

0

Tùy thuộc vào kịch bản của bạn, điều này có thể dẫn đến sự cố nếu bạn xóa giới hạn thời gian. Nếu mỗi ví dụ, bạn đang bỏ phiếu cho máy chủ bên ngoài không phản hồi trong khi công việc đang chạy và cron của bạn mất 2 giờ thay vì 30 phút để hoàn thành, bạn có thể nhận được một chồng các quy trình PHP đang được kích hoạt ngay cả khi chưa hoàn thành. Điều này có thể gây ra sự mất ổn định hệ thống và sự cố.

Bạn có thể có hai lựa chọn:

  • Hãy chắc chắn rằng không có trường hợp khác của kịch bản của bạn đang chạy trước, nếu không exit() trên đầu.
  • Cân nhắc việc thay đổi cronjob của bạn thành một daemon.
1

Tôi thực sự nghĩ bạn không nên đặt thời gian là 0, điều đó chỉ tìm kiếm sự cố. Tối đa, đặt nó là 59 * 60 giây, nhưng đặt nó thành 0 có thể gây ra sự cố bảo mật, nếu tập lệnh bị treo, nó sẽ treo gần như mãi mãi cho đến khi máy chủ lưu trữ ngừng thực thi. Nó được coi là thực hành xấu để làm như vậy.

0

Nó có phải chạy hàng giờ như đồng hồ không?

Nếu không chia công việc (bạn đã đề cập đến nhiều hơn một nhiệm vụ đơn giản), hãy thực hiện từng tác vụ mỗi giờ?

Hoặc chia nhỏ cho mỗi người dùng, thực hiện A-M theo giờ, sau đó là N-Z tiếp theo?

2

Thay vì đặt max_execution_time bạn cũng có thể sử dụng set_time_limit() để đặt lại bộ đếm trên mỗi vòng lặp. Điều này sẽ đảm bảo kịch bản của bạn không bao giờ hết thời gian trừ khi có điều gì đó nghiêm trọng treo trong vòng lặp hiện tại (và mất nhiều thời gian hơn max_execution_time).

Về cơ bản, điều này sẽ làm cho tập lệnh của bạn chạy miễn là cần trong khi mất thời gian chờ 30 giây giữa hai cuộc gọi set_time_limit().

+0

Đây là một lời khuyên tốt. Tôi không chắc tại sao bạn không có đủ phiếu bầu. – dinwal

Các vấn đề liên quan