Массовая запись PHP Mongo

Пожалуйста, может кто-нибудь помочь с этой проблемой. Спасибо.

Приведенный ниже PHP-скрипт вызывает следующую ошибку при попытке выполнить строку массовой записи.

[russell@hawk mongo]$ cat error_log
[29-Apr-2023 05:04:22 UTC] PHP Fatal error:  Uncaught MongoDB\Driver\Exception\ConnectionTimeoutException: No suitable servers found (`serverSelectionTryOnce` set): [connection closed calling ismaster on 'cluster0-shard-00-00.tx3cl.mongodb.net:27017'] [connection closed calling ismaster on 'cluster0-shard-00-01.tx3cl.mongodb.net:27017'] [connection closed calling ismaster on 'cluster0-shard-00-02.tx3cl.mongodb.net:27017'] in /home/mongo/2_test_mongo.php:13
Stack trace:
#0 /home/mongo/2_test_mongo.php(13): MongoDB\Driver\Manager->executeBulkWrite()
#1 {main}
  thrown in /home/mongo/2_test_mongo.php on line 13

Интересно, что ошибка показывает номер порта. Также интересно, что строка подключения, напечатанная обратно в консоль, не имеет +srv.

Но вам не разрешено включать номер порта с типом подключения mongo+srv. Я не указываю номер порта.

В Compass на ноутбуке я получаю эту ошибку при удалении +srv getaddrinfo ENOTFOUND cluster0.tx3cl.mongodb.net а также, если я добавляю номер порта 27017, чтобы компенсировать отсутствие +srv, я получаю ту же ошибку.

Есть ли что-то, что я должен сделать, чтобы переопределить добавленный порт по умолчанию? Технические детали

[prompt]$ php --version
PHP 8.0.18 (cli) (built: Apr 13 2022 10:54:57) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.18, Copyright (c) Zend Technologies
[prompt]$ uname -a
Linux blah.blah.net 3.10.0-962.3.2.lve1.5.67.el7.x86_64 #1 SMP Fri Mar 25 07:13:21 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
[prompt]$ 

Вывод скрипта на консоль следующий

[prompt]$ php script.php
loaded
MongoDB\Driver\Manager Object
(
    [uri] => mongodb://user:[email protected]/?retryWrites=true&w=majority
    [cluster] => Array
        (
        )

)

Сам скрипт есть

<?php
    use MongoDB\Client;
    use MongoDB\Driver\ServerApi;

    echo extension_loaded("mongodb") ? "loaded\n" : "not loaded\n";

    $uri = 'mongodb+srv://user:[email protected]/?retryWrites=true&w=majority';

    $manager = new MongoDB\Driver\Manager($uri);
    print_r($manager);

    $bulk = new MongoDB\Driver\BulkWrite();
    $bulk->insert(['x' => 1]);
    $bulk->insert(['x' => 2]);
    $bulk->insert(['x' => 3]);

    $manager->executeBulkWrite('TestyDB.TestyCollection', $bulk);
    
    $filter = ['x' => ['$gt' => 1]];
    $options = [
        'projection' => ['_id' => 0],
        'sort' => ['x' => -1],
    ];
    
    $query = new MongoDB\Driver\Query($filter, $options);
    $cursor = $manager->executeQuery('TestyDB.TestyCollection', $query);
    
    foreach ($cursor as $document) {
        var_dump($document);
    } 
?>

URL-адрес в строке подключения доступен для проверки связи с сервера, с которого я пытаюсь подключиться.

russell@hawk mongo]$ ping cluster0-shard-00-00.tx3cl.mongodb.net
PING ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242) 56(84) bytes of data.
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=1 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=2 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=3 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=4 ttl=228 time=76.7 ms
64 bytes from ec2-52-55-183-242.compute-1.amazonaws.com (52.55.183.242): icmp_seq=5 ttl=228 time=76.6 ms

Похоже, это может быть похоже на: stackoverflow.com/questions/51755165/… Однако не было никакого решения, кроме отладки с помощью curl. Это также драйвер С#, а не PHP.

yogibear 29.04.2023 07:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
1
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я только что изменил версию PHP с 8.0 на 7.4.

Ответ прост: скрипт работает с PHP 7.4. Намек на то, что проблема не в сети, заключается в том, что та же строка подключения работает с ноутбуком, на котором запущен компас.

Теперь вопрос в том, какой правильный синтаксис для PHP8.0 :-)

Дополнительные новости. Я связался с поддержкой моей хостинговой компании по этому поводу. Они открыл порт на 27017 и этот скрипт теперь работает с PHP 8.0 и 7.4

Я отправил вопрос на форумы монога здесь, если кому-то интересно. https://www.mongodb.com/community/forums/t/why-does-php-8-0-remove-the-srv/224252

Что помогло мне решить проблему с версиями, так это увидеть тот же код здесь: https://help.ovhcloud.com/csm/en-gb-public-cloud-databases-mongodb-connect-php?id=kb_article_view&sysparm_article= KB0049087 Они указали версию PHP, которую они использовали, и код был практически таким же, как у меня.

До этого я думал, что провел исследование для PHP 8.0 и Mongo. Вот если бы я это сделал, а это баг, то будет интересно. Не могу дождаться, чтобы увидеть, что говорят форумы монго.

Вкратце: я не вижу никаких признаков ошибки драйвера или каких-либо различий в поведении между PHP 7.4 и 8.0. Основной причиной оказалась ограничительная сетевая политика на сервере приложений PHP 8.0 (согласно вашего ответа).

Объяснение исключения ConnectionTimeoutException

Документы MongoDB PHP Library включают часто задаваемые вопросы, в которых есть раздел Ошибки выбора сервера. Чтение этого должно позволить вам понять ошибку «Подходящие серверы не найдены», но я также разберу ее здесь:

Uncaught MongoDB\Driver\Exception\ConnectionTimeoutException:
  No suitable servers found (`serverSelectionTryOnce` set):
  [connection closed calling ismaster on 'cluster0-shard-00-00.tx3cl.mongodb.net:27017']
  [connection closed calling ismaster on 'cluster0-shard-00-01.tx3cl.mongodb.net:27017']
  [connection closed calling ismaster on 'cluster0-shard-00-02.tx3cl.mongodb.net:27017']
  in /path/to/script...

Драйверу не удалось выбрать какой-либо сервер для операции с базой данных, и он сообщает о самой последней ошибке при каждом подключении к серверу. Тот факт, что здесь присутствуют три сервера, говорит нам о том, что исходный mongodb+srv:// URI был успешно преобразован в начальный список из трех хостов.

Увидев «соединение закрыто» в сообщении об ошибке сокета, я предполагаю, что что-то немедленно отклонило соединение. Среди многих возможных причин этого могут быть ограничительная конфигурация сети, брандмауэр или удаленный хост, отклоняющий соединение. Что касается MongoDB Atlas, эта ошибка также распространена, если IP-адрес сервера приложений PHP не включен в Записи списка доступа IP.

Выявление основной причины

В вашем ответе вы указали:

Я связался с поддержкой моей хостинговой компании по этому поводу. Они открыли порт на 27017, и этот скрипт теперь работает с PHP 8.0 и 7.4.

Если я правильно понимаю, сетевая конфигурация вашей хостинговой компании блокировала PHP от исходящих подключений к порту 27017. Это, безусловно, объяснило бы ошибку подключения и не предполагает каких-либо проблем с PHP или драйвером MongoDB.

Устранение некоторых недоразумений

Интересно, что ошибка показывает номер порта.

Хосты и порты, обнаруженные в ошибке выбора сервера, не имеют прямого отношения к mongodb+srv:// URI. Вы упускаете из виду, что драйвер будет запрашивать DNS и создавать начальный список, похожий на mongodb:// URI. Формат подключения DNS Seed List в документации MongoDB объясняет это более подробно.

27017 — это просто порт по умолчанию.

Но вам не разрешено включать номер порта с типом подключения mongo+srv. Я не указываю номер порта.

Вы правы, что mongodb+srv:// URI не включает порт. Порт для каждого сервера в начальном списке фактически получается из записей DNS.

Обратите внимание, что исходный список по-прежнему является лишь промежуточным источником информации и может не отражать все серверы, к которым в конечном итоге подключается драйвер. Если вам это интересно, вы можете прочитать спецификацию драйвера Обнаружение и мониторинг серверов или Обнаружение и мониторинг серверов в драйверах MongoDB следующего поколения в блоге MongoDB (это немного устарело, но его легче переварить, чем сырой спец).

Также интересно, что строка подключения, напечатанная обратно в консоль, не имеет +srv.

У меня нет объяснения этому, основанного на том, что вы поделились выше, но я также не нашел доказательств того, что драйвер сообщит что-либо, кроме исходного URI, используемого для создания диспетчера.

Обработчик get_debug_info объекта Manager заполняет поле uri с помощью mongoc_uri_get_string() ). Эта функция в libmongoc (драйвер C, на основе которого построен драйвер PHP) возвращает ту же строку , которая использовалась для построения URI, который изначально установлен в mongoc_uri_new_with_error() . Для справки, это та же самая функция , которая используется драйвером PHP при создании объекта Manager.

Я предполагаю, что некоторая другая важная информация опущена. Например, вы упомянули, какие версии PHP использовались (7.4 и 8.0), но ни разу не упомянули версию драйвера PHP (т. е. расширения mongodb), работающего в каждой среде. Также было неясно, где работает каждая среда PHP. Если первоначальная ошибка подключения была вызвана конфигурацией сети вашей хостинговой компании, и они использовали PHP 8.0, это не означает, что проблема в PHP 8.0 (корреляция не подразумевает причинно-следственную связь).

В Compass на ноутбуке я получаю эту ошибку при удалении +srv getaddrinfo ENOTFOUND cluster0.tx3cl.mongodb.net, а также, если я добавляю номер порта 27017, чтобы компенсировать отсутствие +srv, я получаю ту же ошибку.

Хост, используемый для mongodb+srv:// URI, не обязательно совпадает с хостом(ами), на котором запущена MongoDB. cluster0.tx3cl.mongodb.net используется для разрешения DNS, но на основании вышеприведенного исключения ConnectionTimeoutException мы видим, что фактические серверы работают на следующих хостах:

  • кластер0-осколок-00-00.tx3cl.mongodb.net
  • кластер0-осколок-00-01.tx3cl.mongodb.net
  • кластер0-осколок-00-02.tx3cl.mongodb.net

Учитывая это, нет причин ожидать, что сервер MongoDB будет прослушивать cluster0.tx3cl.mongodb.net:27017.

Спасибо за объяснение, однако я не согласен с вашей оценкой, что нет никаких доказательств проблемы. Разница в версиях PHP действительно имеет проблему. Поскольку версия 7.4 работала правильно, а версия 8 вызывала описанные мной проблемы. Это было легко проверить с моим хостинг-провайдером.

yogibear 17.05.2023 10:28

PHP 8.0 удалял +srv, а 7.4 — нет. 7.4 правильно подключался без открытия порта хостинговой компанией. Где, как и в PHP 8.0, +srv был удален, и порт нужно было открыть.

yogibear 17.05.2023 10:31

Если вы можете воспроизвести проблему, когда объект Manager печатает что-либо, кроме своего первого аргумента конструктора, в поле uri своего отладочного вывода, откройте проблему либо в JIRA , либо в mongodb/mongo-php-driver GitHub. проект, и я буду рад продолжить расследование. При этом обязательно укажите точную версию PHP и расширение mongodb.

jmikola 18.05.2023 14:33

Я также добавлю, что ваш хостинг-провайдер, разрешающий PHP 8.0 создавать исходящие соединения на порту 27017, не должен иметь ничего общего с поиском DNS, выполняемым во время построения менеджера. executeBulkWrite() — это первая точка в скрипте, где драйвер попытается подключиться к серверу MongoDB. Поскольку вывод print_r() генерируется до этой точки, единственным фактором, способствующим ошибке драйвера, будет построение менеджера и любое разрешение SRV, которое происходит внутри. Это должно предоставить вам минимальный объем кода для попытки воспроизведения.

jmikola 18.05.2023 14:42

Другие вопросы по теме