Налог на рукопожатие
Ваша интеграция с Magento может работать медленно из-за скрытых сетевых затрат.
Однажды я запускал экспорт товаров, который взаимодействовал с API цен. Один товар обрабатывался быстро. Весь каталог обрабатывался целую вечность. Моя база данных простаивала. Профайлер показал, что проблема была в сети.
Код создавал новый HTTP-клиент внутри цикла.
Прежде чем отправить данные по HTTPS, ваша машина выполняет тяжелую работу. Она выполняет TCP-рукопожатие для открытия сокета. Затем она выполняет TLS-рукопожатие для обмена сертификатами и согласования ключей. Это требует нескольких циклов приема-передачи (round trips).
Если вы делаете это один раз, затраты невелики. Если вы делаете это внутри цикла из 40 000 товаров, вы платите эту цену 40 000 раз. Сами данные малы. Настройка — вот самая дорогая часть.
В PHP часто кажется, что нужно создать клиент и тут же его выбросить. Это работает для одного веб-запроса. Это не работает в долгоживущих процессах.
Избегайте такого паттерна в cron-задачах, консольных командах или потребителях очередей сообщений:
- foreach ($products as $product) {
- $client = new \GuzzleHttp\Client();
- $client->post('https://api.example.com/sync', [...]);
- }
Этот код открывает новое соединение и выполняет полное рукопожатие для каждого отдельного товара.
Guzzle поддерживает соединения открытыми, если вы используете один и тот же экземпляр клиента. Вынесите клиент за пределы цикла:
- $client = new \GuzzleHttp\Client(['base_uri' => 'https://api.example.com']);
- foreach ($products as $product) {
- $client->post('/sync', [...]);
- }
Теперь сокет и TLS-сессия остаются открытыми. Вы выполняете рукопожатие один раз, а затем передаете поток данных. В Magento внедряйте настроенный клиент через конструктор вместо того, чтобы создавать его вручную.
Несоблюдение этого правила приводит не только к задержкам. У вас могут закончиться исходящие порты. Закрытые соединения накапливаются в состоянии TIME_WAIT быстрее, чем ваша ОС успевает их освобождать. Ваш сервис может полностью перестать открывать новые сокеты.
Проверьте свой код на наличие этой ошибки. Выполните эту команду в терминале:
grep -rn "new .*Client(" app/code | grep -i http
Ищите любое создание нового клиента внутри цикла. Вынесите клиент из цикла. Это изменение в одну строку обеспечит колоссальное ускорение при больших объемах синхронизации.
Source: https://dev.to/iamrobindhiman/the-handshake-tax-reuse-your-http-client-in-magento-integrations-3kk7
