การตั้งค่าการหมดเวลาของ Curl ใน PHP


230

ฉันกำลังขอ curl ในฐานข้อมูล eXist ผ่าน php ชุดข้อมูลมีขนาดใหญ่มากและเป็นผลให้ฐานข้อมูลใช้เวลานานในการส่งคืนการตอบกลับ XML อย่างสม่ำเสมอ ในการแก้ไขปัญหานั้นเราตั้งค่าคำขอ curl โดยที่ควรจะหมดเวลานาน

$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);

อย่างไรก็ตามคำขอ curl สิ้นสุดลงอย่างต่อเนื่องก่อนที่คำขอจะเสร็จสมบูรณ์ (<1,000 เมื่อร้องขอผ่านเบราว์เซอร์) ไม่มีใครรู้ว่านี่เป็นวิธีที่เหมาะสมในการตั้งค่าการหมดเวลาในขด?

คำตอบ:


346

ดูเอกสาร: http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT- จำนวนวินาทีที่รอในขณะที่พยายามเชื่อมต่อ ใช้ 0 เพื่อรออย่างไม่มีกำหนด
CURLOPT_TIMEOUT- จำนวนวินาทีสูงสุดเพื่ออนุญาตให้ฟังก์ชัน cURL สามารถดำเนินการได้

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

ยังไม่ลืมที่จะขยายการดำเนินการเวลาของสคริปต์ PHP ด้วยตนเอง:

set_time_limit(0);// to infinity for example

13
คุณไม่ต้องการset_time_limit(0);ถ้าสคริปต์ทำงานบนคอนโซล
CONVID19

6
@PedroLobito สิ่งที่คุณพูดถึงคือการกำหนดค่าเริ่มต้นของ php บน cli แต่เป็นไปได้ว่าอาจมีการแก้ไข
cherouvim

4
@cherouvim ถูกต้องชัดเจนที่นี่ (เพียงแค่เรียกใช้php -d max_execution_time=1 -r 'while(true){$r=1*1;}'หรือสิ่งที่ต้องสังเกตในการกระทำที่ cli ไม่ได้มีธง 'เสมอไม่ จำกัด ' เวทย์มนตร์
Wrikken

@Pedro Lobito คุณไม่จำเป็นset_time_limit(0)ถ้าคุณไม่ได้ใช้มันในวง
Viktor Joras

58

อืมดูเหมือนว่าฉันจะCURLOPT_TIMEOUTกำหนดระยะเวลาที่ฟังก์ชัน cURL ใด ๆ ที่ได้รับอนุญาตให้ดำเนินการ ฉันคิดว่าคุณควรจะดูCURLOPT_CONNECTTIMEOUTแทนจริง ๆเพราะนั่นบอก cURL จำนวนเวลาสูงสุดที่จะรอให้การเชื่อมต่อเสร็จสมบูรณ์


ในขณะที่เอกสารใน PHPบอกCURLOPT_TIMEOUTว่าฟังก์ชั่นใช้เวลานานเท่าไหร่เอกสารห้องสมุดที่ม้วนงอดูเหมือนจะบอกว่ามันเกี่ยวกับระยะเวลาของการร้องขอซึ่งเป็นความแตกต่างที่น่าสนใจ - ไม่แน่ใจว่าวิธีการอ่านนั้น!
พัฒนาระบบ

ฉันคิดว่านี่คือการตีความที่ดีที่สุด: stackoverflow.com/questions/27776129/…
fideloper

33

มีการเล่นโวหารกับสิ่งนี้ที่อาจเกี่ยวข้องกับบางคน ... จากความคิดเห็นเอกสาร PHP

หากคุณต้องการให้หมดเวลา cURL ในเวลาน้อยกว่าหนึ่งวินาทีคุณสามารถใช้CURLOPT_TIMEOUT_MSแม้ว่าจะมีข้อบกพร่อง / "คุณสมบัติ" ใน "ระบบ Unix-like" ที่ทำให้ libcurl หมดเวลาทันทีหากค่า <1,000 ms พร้อมข้อผิดพลาด "cURL ข้อผิดพลาด (28): ถึงกำหนดหมดเวลา " คำอธิบายสำหรับพฤติกรรมนี้คือ:

"ถ้า libcurl ถูกสร้างขึ้นเพื่อใช้ตัวแก้ไขชื่อระบบมาตรฐานส่วนของการถ่ายโอนนั้นจะยังคงใช้ความละเอียดเต็มวินาทีสำหรับการหมดเวลาด้วยการหมดเวลาต่ำสุดที่อนุญาตหนึ่งวินาที"

สิ่งนี้หมายถึงนักพัฒนา PHP คือ "คุณไม่สามารถใช้ฟังก์ชั่นนี้โดยไม่ทดสอบก่อนเพราะคุณไม่สามารถบอกได้ว่า libcurl ใช้ตัวแก้ไขชื่อระบบมาตรฐาน (แต่คุณมั่นใจได้เลยว่ามันคือ")

ปัญหาคือว่าเมื่อ (Li | U) ระวังเมื่อ libcurl ใช้ตัวแก้ไขชื่อมาตรฐาน SIGALRM จะเพิ่มขึ้นในระหว่างการแก้ไขชื่อที่ libcurl คิดว่าเป็นสัญญาณเตือนการหมดเวลา

วิธีแก้ไขคือปิดใช้งานสัญญาณโดยใช้ CURLOPT_NOSIGNAL นี่คือตัวอย่างสคริปต์ที่ขอตัวเองทำให้เกิดความล่าช้า 10 วินาทีเพื่อให้คุณสามารถทดสอบหมดเวลา:

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.";
}

จากhttp://www.php.net/manual/th/function.curl-setopt.php#104597


สวัสดีรหัสนี้ใช้งานได้ แต่ไฟล์ต้นฉบับคือ 7MB และดาวน์โหลดนี้ฉันเพียง 52KB สิ่งที่อาจผิด URL เป็นสิ่งที่คล้ายกับwebserver.tld / folder / download / …
Muflix

@Simon East โปรดช่วยฉันได้ที่stackoverflow.com/questions/30861112/…
นาธาน Srivi

ควรสังเกตว่าคุณคาดหวังว่าจะเกิดข้อผิดพลาดการหมดเวลากับสคริปต์นี้
kmoney12


13

คุณจะต้องตรวจสอบให้แน่ใจเกี่ยวกับการหมดเวลาระหว่างคุณและไฟล์ ในกรณีนี้ PHP และ Curl

ที่จะบอก Curl จะไม่หมดเวลาเมื่อมีการถ่ายโอนยังคงใช้งานคุณจะต้องตั้งค่าCURLOPT_TIMEOUTการแทน01000

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

ใน PHP อีกครั้งคุณต้องลบการ จำกัด เวลาหรือ PHP ด้วยตนเอง (หลังจาก 30 วินาทีโดยค่าเริ่มต้น) จะฆ่าสคริปต์ตามคำขอของ Curl นี้เพียงอย่างเดียวควรแก้ไขปัญหาของคุณ
นอกจากนี้หากคุณต้องการความถูกต้องของข้อมูลคุณสามารถเพิ่มระดับความปลอดภัยโดยใช้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);

การตัดการเชื่อมต่อของไคลเอ็นต์จะขัดจังหวะการทำงานของสคริปต์และอาจทำให้ข้อมูลเสียหาย
เช่น แบบสอบถามฐานข้อมูลที่ไม่ใช่การนำส่งการสร้างไฟล์ปรับแต่ง ecc. ในขณะที่ในกรณีของคุณมันจะดาวน์โหลดไฟล์บางส่วน ... และคุณอาจสนใจเรื่องนี้หรือไม่

CURL_TIMEOUTตอบคำถามเก่านี้เพราะหัวข้อนี้อยู่ที่ด้านบนในการค้นหาเครื่องยนต์


8

คุณไม่สามารถเรียกใช้คำขอจากเบราว์เซอร์ได้ซึ่งจะหมดเวลารอให้เซิร์ฟเวอร์ที่เรียกใช้คำขอ CURL เพื่อตอบกลับ เบราว์เซอร์อาจหมดเวลาใน 1-2 นาทีซึ่งเป็นการหมดเวลาเครือข่ายเริ่มต้น

คุณต้องเรียกใช้จากบรรทัดคำสั่ง / เทอร์มินัล


2
+1 - การหมดเวลาน่าจะเป็นของขด คุณสามารถหลีกเลี่ยงการหมดเวลาของเบราว์เซอร์ได้โดยตรวจสอบให้แน่ใจว่าได้ส่งออกบางสิ่งบางอย่างเป็นระยะ เบราว์เซอร์จะรีเซ็ตการหมดเวลาโดยทั่วไปทุกครั้งที่รับข้อมูลเพิ่มเติม แต่นั่นเป็นแฮ็ค การใช้งานผ่าน CLI นั้นดีกว่าหรือไม่
Frank Farmer

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.