Đặt thời gian chờ của Curl trong PHP


230

Tôi đang chạy một yêu cầu curl trên cơ sở dữ liệu eXist thông qua php. Bộ dữ liệu rất lớn và do đó, cơ sở dữ liệu luôn mất một khoảng thời gian dài để trả về phản hồi XML. Để khắc phục điều đó, chúng tôi thiết lập một yêu cầu cuộn tròn, với thời gian được cho là đã hết thời gian dài.

$ch = curl_init();
$headers["Content-Length"] = strlen($postString);
$headers["User-Agent"] = "Curl/1.0";

curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:');
curl_setopt($ch,CURLOPT_TIMEOUT,1000);
$response = curl_exec($ch);
curl_close($ch);

Tuy nhiên, yêu cầu curl luôn kết thúc trước khi yêu cầu được hoàn thành (<1000 khi được yêu cầu qua trình duyệt). Có ai biết nếu đây là cách thích hợp để đặt thời gian chờ trong curl?

Câu trả lời:


346

Xem tài liệu: http://www.php.net/manual/en/feft.curl-setopt.php

CURLOPT_CONNECTTIMEOUT- Số giây chờ trong khi cố gắng kết nối. Sử dụng 0 để chờ đợi vô thời hạn.
CURLOPT_TIMEOUT- Số giây tối đa để cho phép các hàm cURL thực thi.

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds

cũng đừng quên phóng to thời gian thực thi tập lệnh php:

set_time_limit(0);// to infinity for example

13
Bạn không cần set_time_limit(0);nếu tập lệnh đang chạy trên bảng điều khiển.
CONvid19

6
@PedroLobito những gì bạn đề cập là cấu hình mặc định của php trên cli, nhưng có thể điều này có thể đã được sửa đổi.
cherouvim

4
@cherouvim rõ ràng là chính xác ở đây (chỉ cần chạy php -d max_execution_time=1 -r 'while(true){$r=1*1;}'hoặc một cái gì đó để quan sát trong hành động rằng cli không có cờ 'luôn luôn không giới hạn'.
Wrikken

@Pedro Lobito bạn không cần set_time_limit(0)nếu bạn không sử dụng nó trong vòng lặp.
Viktor Joras

58

Hmm, đối với tôi như CURLOPT_TIMEOUTđịnh nghĩa lượng thời gian mà bất kỳ hàm cURL nào cũng được phép thực hiện. Tôi nghĩ rằng bạn thực sự nên nhìn vào CURLOPT_CONNECTTIMEOUTthay vào đó, vì điều đó cho cURL lượng thời gian tối đa để chờ kết nối hoàn tất.


Mặc dù các tài liệu trong PHP nói CURLOPT_TIMEOUTlà về thời gian của hàm, các tài liệu thư viện curl bên dưới dường như nói rằng đó là khoảng thời gian yêu cầu, đó là một sự khác biệt thú vị - không biết nên đọc cách nào!
fideloper

Tôi nghĩ rằng đây là cách giải thích tốt nhất: stackoverflow.com/questions/27776129/ từ
fideloper

33

Có một điều không hay với điều này có thể phù hợp với một số người ... Từ các bình luận tài liệu PHP.

Nếu bạn muốn cURL hết thời gian chờ chưa đến một giây, bạn có thể sử dụng CURLOPT_TIMEOUT_MS, mặc dù có lỗi / "tính năng" trên "các hệ thống giống Unix" khiến libcurl hết thời gian ngay lập tức nếu giá trị <1000 ms bị lỗi "cURL Lỗi (28): Đã hết thời gian chờ ". Giải thích cho hành vi này là:

"Nếu libcurl được xây dựng để sử dụng trình phân giải tên hệ thống tiêu chuẩn, phần chuyển đó vẫn sẽ sử dụng độ phân giải toàn giây cho thời gian chờ với thời gian chờ tối thiểu cho phép là một giây."

Điều này có nghĩa gì với các nhà phát triển PHP là "Bạn không thể sử dụng chức năng này mà không kiểm tra nó trước, bởi vì bạn không thể biết libcurl có đang sử dụng trình phân giải tên hệ thống tiêu chuẩn hay không (nhưng bạn có thể chắc chắn là như vậy)"

Vấn đề là trên (Li | U) nix, khi libcurl sử dụng trình phân giải tên tiêu chuẩn, SIGALRM được đưa ra trong quá trình phân giải tên mà libcurl nghĩ là báo động hết thời gian.

Giải pháp là vô hiệu hóa các tín hiệu bằng cách sử dụng CURLOPT_NOSIGNAL. Đây là tập lệnh ví dụ yêu cầu chính nó gây ra độ trễ 10 giây để bạn có thể kiểm tra thời gian chờ:

if (!isset($_GET['foo'])) {
    // Client
    $ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    // Server
    sleep(10);
    echo "Done.";
}

Từ http://www.php.net/manual/en/feft.curl-setopt.php#104597


Xin chào, mã này hoạt động nhưng tệp nguồn là 7MB và tải xuống này chỉ cho tôi 52KB, điều gì có thể sai? URL là một cái gì đó giống như webserver.tld / thư mục / tải xuống /
Lỗi

@Simon East bạn có thể vui lòng giúp tôi stackoverflow.com/questions/30861112/
Kẻ

Cần lưu ý rằng bạn đang mong đợi một lỗi hết thời gian với tập lệnh này
kmoney12

30

Mã của bạn thiết lập thời gian chờ đến 1000 giây . Trong một phần nghìn giây, sử dụng CURLOPT_TIMEOUT_MS.


13

Bạn sẽ cần đảm bảo về thời gian chờ giữa bạn và tệp. Trong trường hợp này PHP và Curl.

Để báo cho Curl không bao giờ hết thời gian khi chuyển khoản vẫn hoạt động, bạn cần đặt CURLOPT_TIMEOUTthành 0, thay vì 1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

Trong PHP, một lần nữa, bạn phải xóa giới hạn thời gian hoặc PHP tự nó (sau 30 giây theo mặc định) sẽ giết tập lệnh theo yêu cầu của Curl. Điều này một mình nên khắc phục vấn đề của bạn .
Ngoài ra, nếu bạn yêu cầu toàn vẹn dữ liệu, bạn có thể thêm một lớp bảo mật bằng cách sử dụng ignore_user_abort:

# The maximum execution time, in seconds. If set to zero, no time limit is imposed.
set_time_limit(0);

# Make sure to keep alive the script when a client disconnect.
ignore_user_abort(true);

Việc ngắt kết nối máy khách sẽ làm gián đoạn quá trình thực thi tập lệnh và có thể làm hỏng dữ liệu,
vd. truy vấn cơ sở dữ liệu không chuyển tiếp, xây dựng tệp cấu hình, ecc., trong trường hợp của bạn, nó sẽ tải xuống một phần tệp ... và bạn có thể, hoặc không, quan tâm đến điều này.

Trả lời câu hỏi cũ này bởi vì chủ đề này đứng đầu trong các tìm kiếm động cơ CURL_TIMEOUT.


8

Bạn không thể chạy yêu cầu từ trình duyệt, nó sẽ hết thời gian chờ máy chủ chạy yêu cầu CURL phản hồi. Trình duyệt có thể hết thời gian trong 1-2 phút, thời gian chờ mạng mặc định.

Bạn cần chạy nó từ dòng lệnh / terminal.


2
+1 - thời gian chờ có lẽ là bên ngoài để cuộn tròn. Bạn thực sự có thể làm việc xung quanh thời gian chờ của trình duyệt bằng cách đảm bảo định kỳ xuất ra một cái gì đó; các trình duyệt thường đặt lại thời gian chờ của họ mỗi khi họ nhận được nhiều dữ liệu hơn. Nhưng đó là một hack; chạy qua CLI là (hầu như?) luôn luôn thích hợp hơn.
Nông dân Frank

3

Nếu bạn đang sử dụng PHP làm ứng dụng fastCGI thì hãy chắc chắn rằng bạn đã kiểm tra cài đặt thời gian chờ fastCGI. Xem: PHP curl đặt 500 lỗi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.