2010-04-21 23 views
10

Tôi đang cố gắng tìm ra cách hiệu quả nhất để chạy một tác vụ PHP khá tốn hàng nghìn lần mỗi ngày. Nó cần tạo kết nối IMAP tới Gmail, lặp qua email, lưu thông tin này vào cơ sở dữ liệu và lưu hình ảnh cục bộ.Tôi phải làm gì khi công việc cron không đủ? (php)

Chạy tác vụ này thường xuyên bằng cách sử dụng cron không phải là vấn đề lớn, nhưng tôi cần phải chạy nó mỗi phút và cuối cùng tôi biết rằng các crons sẽ bắt đầu chạy trên đầu trang và gây ra vấn đề về bộ nhớ.

Bước tiếp theo là gì khi bạn cần chạy một tác vụ nhiều lần một cách hiệu quả? Tôi đã đọc về beanstalk & pheanstalk và tôi không hoàn toàn chắc chắn nếu điều đó sẽ làm những gì tôi cần. Suy nghĩ ???

+0

Điều này không liên quan trực tiếp đến câu hỏi của bạn, nhưng sử dụng CURL để truy xuất hình ảnh. Nó lưu trữ yêu cầu DNS, trong khi file_get_contents() và chức năng tập tin gốc khác thì không. Tôi đã từng cần làm một kịch bản để lấy hình ảnh, và khá nhiều thời gian thực hiện là độ trễ mạng. Vì vậy, có thể giúp một chút để giảm nó. – Savageman

Trả lời

7

Hoặc tạo cơ chế khóa để các tập lệnh sẽ không trùng lặp. Điều này khá đơn giản như kịch bản chỉ chạy mỗi phút, một file .lock đơn giản sẽ đủ:

<?php 
    if (file_exists("foo.lock")) exit(0); 
    file_put_contents("foo.lock", getmypid()); 

    do_stuff_here(); 

    unlink("foo.lock"); 
?> 

này sẽ đảm bảo các kịch bản không chạy song song, bạn chỉ cần phải chắc chắn rằng các tập tin bị xóa .lock khi chương trình thoát, vì vậy bạn nên có một điểm thoát duy nhất (ngoại trừ khi thoát ra ở đầu).

Một giải pháp thay thế tốt - như Brian Roach đề xuất - là một quy trình máy chủ chuyên dụng chạy mọi lúc và giữ kết nối với máy chủ IMAP. Điều này làm giảm chi phí rất nhiều và không phải là khó khăn hơn nhiều so với việc viết một kịch bản php bình thường:

<?php 
    connect(); 
    while (is_world_not_invaded_by_aliens()) 
    { 
    get_mails(); 
    get_images(); 
    sleep(time_to_next_check()); 
    } 
    disconnect(); 
?> 
+2

Tôi nghĩ rằng daemon sẽ là đặt cược tốt nhất của tôi và giữ IMAP mở nên mọi thứ nhanh hơn rất nhiều. Cảm ơn vì lời khuyên! – mike

10

Tôi không phải là một anh chàng PHP nhưng ... điều gì ngăn cản bạn chạy tập lệnh dưới dạng daemon? Tôi đã viết nhiều kịch bản perl chỉ làm điều đó.

+0

Tôi chưa bao giờ viết một daemon trước đây, nhưng tôi sẽ bắt đầu thực hiện một số nghiên cứu thêm ngay bây giờ. Cám ơn vì sự gợi ý. – mike

+0

Về cơ bản ... bạn chỉ cần bọc mọi thứ trong một 'while (1)' và chạy tập lệnh trong nền. Nếu điều quan trọng là nó kết thúc làm một cái gì đó thay vì chỉ bị giết, nhìn vào xử lý tín hiệu để bạn có thể làm sạch trước khi thoát. Điểm thưởng cho forking hơn là yêu cầu rằng nó được chạy từ vỏ trong backgorund :) –

+0

Tôi sẽ đề nghị 2 tập tin: người đầu tiên tạo ra một quá trình chạy daemon. Việc đầu tiên sẽ chỉ chờ một vài giây và kiểm tra xem daemon vẫn đang chạy. Nếu không, nó có thể khởi động lại nó. Tôi không thực sự tin tưởng PHP để chạy như vậy một thời gian dài, vì vậy tôi nghĩ rằng nó tốt hơn để có biện pháp phòng ngừa. – Savageman

3

Tôi đã có một số kịch bản như thế này, mà tôi không muốn chạy chúng từ cron trong trường hợp họ ngăn xếp -lên.

#!/bin/sh 
php -f fetchFromImap.php 
sleep 60 
exec $0 

Phần exec $0 bắt đầu kịch bản chạy lại, thay thế bản thân trong bộ nhớ, vì vậy nó sẽ chạy mãi mãi không có vấn đề. Bất kỳ bộ nhớ nào mà tập lệnh PHP sử dụng đều được dọn sạch bất cứ khi nào nó thoát, do đó, đó cũng không phải là vấn đề.

Một dòng đơn giản sẽ bắt đầu nó, và đặt nó vào nền:

cd /x/y/z ; nohup ./loopToFetchMail.sh & 

hoặc nó có thể được tương tự bắt đầu khi máy bắt đầu với phương tiện khác nhau (chẳng hạn như Cron của '@reboot ....')

0

fcron http://fcron.free.fr/ sẽ không bắt đầu công việc mới nếu cũ vẫn đang chạy, Bạn có thể sử dụng @ 1 command và không phải lo lắng về điều kiện chủng tộc.

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