2010-04-06 62 views
162

Tôi đang chạy yêu cầu curl trên cơ sở dữ liệu eXist thông qua php. Tập dữ liệu rất lớn và kết quả là 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 curl, với những gì được cho là một thời gian chờ lâu.Đặt thời gian chờ của Curl trong PHP

$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 hoàn tất (< 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 để thiết lập thời gian chờ trong curl?

Trả lời

52

Hmm, có vẻ như tôi là CURLOPT_TIMEOUT xác định khoảng thời gian mà bất kỳ chức năng cURL nào đều được phép thực hiện. Tôi nghĩ rằng bạn thực sự nên tìm kiếm tại CURLOPT_CONNECTTIMEOUT thay vào đó, kể từ đó nói với cURL khoảng thời gian tối đa để chờ kết nối hoàn thành.

+0

Trong khi [tài liệu trong PHP] (http://php.net/manual/en/function.curl-setopt.php) nói 'CURLOPT_TIMEOUT' là khoảng thời gian chức năng thực hiện, [tài liệu thư viện curl cơ bản] (http://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT.html) dường như nói về yêu cầu của bạn mất bao lâu, đó là một sự phân biệt thú vị - không biết phải đọc cách nào! – fideloper

+0

Tôi nghĩ đây là cách giải thích tốt nhất: http://stackoverflow.com/questions/27776129/php-curl-curlopt-connecttimeout-vs-curlopt-timeout – fideloper

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 chờ 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/thiết bị đầu cuối.

+2

+1 - thời gian chờ có thể nằm ngoài lề. 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 một cái gì đó; các trình duyệt thường đặt lại thời gian chờ của chúng mỗi khi chúng nhận được nhiều dữ liệu hơn. Nhưng đó là một hack; chạy qua CLI là (gần như?) luôn luôn thích hợp hơn. –

25

Mã của bạn đặt thời gian chờ là 1000 giây. Trong mili giây, hãy sử dụng CURLOPT_TIMEOUT_MS.

249

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

CURLOPT_CONNECTTIMEOUT - Số giây để chờ đợi trong khi cố gắng kết nối. Sử dụng 0 để chờ 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 hiện php script tự:

set_time_limit(0);// to infinity for example 
+5

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. –

+0

@PedroLobito những gì bạn đề cập đến 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

+0

Bạn đã kiểm tra tài liệu chưa? –

18

Có một điều không minh bạch với điều này có thể có liên quan đối với một số người ... Từ các tài liệu PHP ý kiến.

Nếu bạn muốn cURL để thời gian chờ trong vòng chưa đầy một giây, bạn có thể sử dụng CURLOPT_TIMEOUT_MS, mặc dù có một lỗi/"tính năng" trên "hệ thống Unix-like" gây libcurl để timeout ngay lập tức nếu giá trị là < 1000 mili giây với lỗi "Lỗi cURL (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 đó sẽ vẫn sử dụng độ phân giải đầy đủ cho thời gian chờ với thời gian chờ tối thiểu cho phép một giây".

Điều này có nghĩa với 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 trước, vì bạn không thể biết liệu libcurl có đang sử dụng trình phân giải tên hệ thống tiêu chuẩn hay không."

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

Giải pháp là tắt tín hiệu bằng CURLOPT_NOSIGNAL.Dưới đây là một kịch bản ví dụ mà yêu cầu bản thân gây ra một sự chậm trễ 10 giây, do đó bạn có thể kiểm tra timeout:

<?php 
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/function.curl-setopt.php#104597

+0

Xin chào, mã này hoạt động nhưng nguồn tập tin là 7MB và điều này tải về tôi chỉ 52KB, những gì có thể là sai? URL giống như http: //webserver.tld/folder/download/file.do? Name = file.zip & _lg = en_US – Muflix

+0

@Simon East, bạn có thể vui lòng giúp tôi http://stackoverflow.com/questions/30861112/scrap- amazon-all-deals-php-curl –

+0

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

3

Nếu bạn đang sử dụng PHP như một ứng dụng fastCGI thì chắc chắn rằng bạn kiểm tra cài đặt thời gian chờ fastCGI. Xem: PHP curl put 500 error

5

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

Để yêu cầu Curl không bao giờ hết thời gian chờ khi quá trình chuyển vẫn hoạt động, bạn cần đặt CURLOPT_TIMEOUT thành 0, thay vì 1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0); 

Trong PHP, một lần nữa, bạn phải gỡ bỏ giới hạn thời gian hoặc PHP nó tự (sau 30 giây theo mặc định) sẽ giết kịch bản cùng yêu cầu Curl của. Chỉ riêng việc này sẽ khắc phục sự cố 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); 

Một ngắt kết nối khách hàng sẽ làm gián đoạn việc thực hiện các kịch bản và dữ liệu có thể gây tổn hại,
ví dụ. truy vấn cơ sở dữ liệu không chuyển tiếp, xây dựng một 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ể, hay không, quan tâm đến điều này.

Trả lời câu hỏi cũ này vì chuỗi này nằm ở đầu các tìm kiếm trên động cơ cho CURL_TIMEOUT.

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