[IT Free Day] PHP và curl_multi_exec()

Trải nghiệm ngày IT Free Day với một câu hỏi thường trực trong đầu -_-. Cũng không thể gọi đúng nghĩa là Free Day được.

Anyway, trở lại câu hỏi về hàm curl_multi_exec.

do {
      $multi_exec_handle = curl_multi_exec ($this -> curl_parent, $active);
} while ($active > 0);

Ba dòng code này có thể được tìm thấy trong cài đặt của một thư viện của CodeIgniter cho chức năng xử lý multi-curl [3].

Hàm curl_multi_exec nhằm mục đích cố gắng download nhiều trang (webpages dưới dạng HTML hoặc feeds dưới dạng XML) cùng một lúc, song song và độc lập với nhau.

Hàm curl_multi_exec nhận vào hai tham số:

  1. Tham số thứ nhất (ở đâu là $this -> curl_parent): một multi-handler tạo bởi hàm curl_multi_init() ở trước đó, giá trị kiểu resource.
  2. Tham số thứ hai $active: số lượng handler mà hàm đang làm việc, giá trị kiểu int. Ví dụ,  nếu bạn đang xử lý 5 URLs với muti-hander này, hàm curl_multi_exec sẽ trả về giá trị $active = 5 nếu nó đang làm việc với cả 5 URLs, và sau đó mỗi khi xử lý xong một URL, giá trị của $active sẽ được giảm xuống cho đến khi về 0.

Hàm curl_multi_exec trả về một giá trị kiểu int, và có thể nhận các giá trị sau:

  • CURLM_CALL_MULTI_PERFORM (-1): Nghĩa là bạn nên gọi hàm curl_multi_exec() một lần nữa bởi vẫn còn dữ liệu để xử lý.
  • CURLM_OK (0): Nghĩa là mọi việc đều tốt!!! Điều nó ám chỉ là có thể vẫn còn giá trị nhưng nó chưa đến.
  • Một trong các error codes sau: CURLM_BAD_HANDLE, CURLM_OUT_OF_MEMORY, CURLM_INTERNAL_ERROR, or CURLM_BAD_SOCKET. Error code ám chỉ rằng chúng ta cần dừng xử lý.

Với đoạn code 3 dòng của chúng ta, trong điều kiện lý tưởng, vòng lặp sẽ thoát khi giá trị $active bằng 0 (hoặc bằng CURLM_OK). Nhưng chuyện gì sẽ xảy ra nếu trong quá trình xử lý có điều bất thường xảy ra (lỗi mạng, …)? Giá trị của $active sẽ không bao giờ là CURLM_OK và chúng ta sẽ rơi vào vòng lặp vô hạn.

Nhiều cài đặt của hàm này là sẽ đợi cho tất cả các request được hoàn thiện trước khi xử lý chúng. Như vậy khi có quá nhiều request cần xử lý cùng lúc, chúng ta phải đợi cho đến lúc request CHẬM NHẤT được hoàn thiện, dẫn đến việc tốn thời gian đợi không đáng có.

Thêm nữa, khi chạy vòng lặp này, nó thường chiếm dụng CPU (100%) cho đến khi vòng lặp hoàn thành.

Trang manual của hàm này cung câp một đoạn code mẫu như sau (sử dụng hai lần vòng lặp do while giống hệt nhau)

<?php
 $active = NULL;
 do {
      $ret = curl_multi_exec($multi, $active);
 } while ($ret == CURLM_CALL_MULTI_PERFORM);

while ($active && $ret == CURLM_OK) {
       if (curl_multi_select($multi) != -1) {
      do {
            $mrc = curl_multi_exec($multi, $active);
      } while ($mrc == CURLM_CALL_MULTI_PERFORM);
      }
 }
?>

Vòng lặp do while đầu tiên chịu trách nhiệm làm sạch bộ đệm. Vòng lặp do while thứ hai có trách nhiệm đợi thêm dữ liệu và sau đó lấy về dữ liệu này. Điều này dẫn đến cái gọi là blocking I/O, chúng ta block sự thực thi phần còn lại của chương trình cho đến khi Network I/O được hoàn thiện.

Ý nghĩa của vòng lặp while như sau:

(while): Chừng nào vẫn còn kết nối và mọi thứ trông có vẻ ổn … 

    (if) Nếu network socket có vài dữ liệu… 

         (do/while) Xử lý dữ liệu chừng nào hệ thống nói rằng nên dừng lại

Vấn đề bảo mật trong PHP

Tìm hiểu rộng ra về hàm curl_multi_exec, có một vấn đề liên quan đến bảo mật. Khi cấu hình PHP, chúng ta cần lưu ý phải tắt (disable) một số hàm nguy hiểm có thể bị hacker lợi dụng để khai thác website, trong đó có hàm curl_multi_exec.

Danh sách các hàm nguy hiểm cần tắt:

  • exec
  • passthru
  • shell_exec
  • system
  • symlink
  • proc_open
  • popen
  • curl_exec
  • curl_multi_exec
  • parse_ini_file
  • show_source

Tắt các hàm này bằng cách thêm dòng sau vào file php.ini

disable_functions = exec, passthru, shell_exec, system, symlink, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source

Tham khảo

  1. Manual of Function curl_multi_exec: http://php.net/manual/en/function.curl-multi-exec.php
  2. Cách tắt hàm nguy hiểm của PHP (disable_functions) CentOS : https://powernet.vn/knowledgebase/283-Cach-tat-ham-nguy-hiem-cua-PHP-disablefunctions-CentOS.html
  3. Codeigniter library for multi-curl functionality : https://github.com/chadhutchins/codeigniter-mcurl/blob/master/application/libraries/mcurl.php
  4. PHP and curl_multi_exec: http://technosophos.com/2012/10/26/php-and-curlmultiexec.html

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s