У меня есть код, который используется для проверки ссылок на веб-сайте и в попытке сделать его «потоковым», код был обновлен для использования pcntl_fork ().
Родительский код работает для URL-адресов SSL и не SSL, но дочерний код работает только для URL-адресов, отличных от SSL. Я заметил в коде, где он работает, а где нет.
Вот мой код вилки. Я знаю, код ниже будет цикл навсегда, я вынул код управления контуром, чтобы он был более читабельным.
$this->initialize_curl(); $this->connect_database(); // prime the queue $this->add_url_to_queue($this->source_url, 0, 0); $this->process_next_url_in_queue($this->get_next_url_in_queue()); // SSL and non-SSL work at this point // loop until we have processed all URL's while (1) { $url = $this->get_next_url_in_queue(); // disconnect from the database before forking since we don't want to // share the database connection with child processes - the first one // will close it and ruin the fun for the other children. curl_close($this->ch); $this->db->close(); // create child $pid = pcntl_fork(); // handle forked processing switch ($pid) { // error case -1: print "Could not fork\n"; exit; // child case 0: // seperate database and curl for the child $this->connect_database(); $this->initialize_curl(); // process the url $this->process_next_url_in_queue($url); // only non-SSL works at this point exit; // parent default: // seperate database and curl for the parent $this->connect_database(); $this->initialize_curl(); break; } }
Как вы можете видеть, мне пришлось открыть и закрыть соединение с базой данных, чтобы оно работало, и я делаю то же самое с CURL. Вот код в initialize_curl()
:
$this->ch = curl_init(); curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, FALSE); curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($this->ch, CURLOPT_HEADER, FALSE);
Я использую CURLOPT_SSL_VERIFYPEER
и CURLOPT_SSL_VERIFYHOST
потому что без него мои запросы SSL CURLOPT_SSL_VERIFYPEER
CURLOPT_SSL_VERIFYHOST
. Это проблема с настройкой сервера, а не с тем, что я могу изменить.
Когда дочерний CURL-URL-адрес SSL, я думаю, что он терпит неудачу, потому что есть проблема с настройкой этих параметров, но я не знаю. Если я установил CURL, чтобы быть подробным, я вижу следующую ошибку:
* About to connect() to HOST port 443 (#0) * Trying IP... * connected * Connected to HOST (IP) port 443 (#0) * NSS error -8023 * Closing connection #0 * SSL connect error
Пожалуйста, дайте мне знать, что я могу сделать, чтобы сделать эту работу.
После многих исследований я обнаружил, что проблема не является новой и представляет собой проблему с реализацией PHP CURL. Эти другие вопросы помогли мне придумать решение, которое я рассказал ниже:
В результате я использовал pcntl_exec, который заменяет текущий дочерний процесс командой.
$this->initialize_curl(); $this->connect_database(); // prime the queue $this->add_url_to_queue($this->source_url, 0, 0); $this->process_next_url_in_queue($this->get_next_url_in_queue()); // loop until we have processed all URL's while (1) { $url = $this->get_next_url_in_queue(); // disconnect from the database before forking since we don't want to // share the database connection with child processes - the first one // will close it and ruin the fun for the other children. curl_close($this->ch); $this->db->close(); // create child $pid = pcntl_fork(); // handle forked processing switch ($pid) { // error case -1: print "Could not fork\n"; exit; // child case 0: // seperate database and curl for the child $this->connect_database(); $this->initialize_curl(); // process the url pcntl_exec('process_next_url_in_queue.php', array($url)); exit; // parent default: // seperate database and curl for the parent $this->connect_database(); $this->initialize_curl(); break; } }