Salesforce / PHP - Массовое исходящее сообщение (SOAP), проблема с тайм-аутом - Смотрите обновление # 2
-
20-09-2019 - |
Вопрос
Система Salesforce может отправлять до 100 запросов в одном сообщении SOAP.При отправке этого типа массового запроса на отправку сообщений мой PHP-скрипт завершает выполнение, но SF не может принять ACK, используемый для очистки очереди сообщений на стороне Salesforce.Просматривая журнал исходящих сообщений (мониторинг) Я вижу все сообщения в состоянии ожидания с причиной сбоя доставки "java.net.SocketTimeoutException:Время чтения истекло".Если мой скрипт завершил выполнение, почему я получаю эту ошибку?
Я пробовал эти методы, чтобы увеличить время выполнения на моем сервере, поскольку у меня нет доступа на стороне Salesforce:
- set_time_limit(0) установить временный_лимит_(0);// в сценарии
- максимальное время выполнения = 360 ;Максимальное время выполнения каждого скрипта, в секундах
- max_input_time = 360 ;Максимальное количество времени, которое каждый скрипт может потратить на анализ данных запроса
- memory_limit = 32M ;Максимальный объем памяти, который может потреблять скрипт
Я использовал высокие настройки только для тестирования.
Есть какие-нибудь мысли относительно того, почему из-за этого не удается вернуть подтверждение в Salesforce?
Вот часть кода:Вот как я принимаю и отправляю файл подтверждения для входящего запроса SOAP
$data = 'php://input';
$content = file_get_contents($data);
if($content) {
respond('true');
} else {
respond('false');
}
Функция ответа
function respond($tf) {
$ACK = <<<ACK
<?xml version = "1.0" encoding = "utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<Ack>$tf</Ack>
</notifications>
</soapenv:Body>
</soapenv:Envelope>
ACK;
print trim($ACK);
}
Они находятся в общем сценарии, который я включаю в сценарий, использующий данные для определенного рабочего процесса.Я могу обработать около 25 запросов (которые находятся в 1 ответе SOAP), но как только я перехожу к этому, я получаю ошибку тайм-аута в очереди Salesforce.на 50 запросов обычно моему PHP-скрипту требуется 86,77 секунды.
Может быть, это Apache?PHP?
Я также протестировал простое принятие ответа SOAP на 100 запросов и простое принятие и отправку подтверждения, после чего очередь очищается, так что я знаю, что это на моей стороне.
Я не показываю ошибок в журнале apache, скрипт работает нормально.
Я нашел кое-какую информацию на сайте Salesforce, но по-прежнему безуспешно.Вот связь.
Также я использую PHP Toolkit 11 (от Salesforce).
Другой форум с хорошей справкой по SF
Спасибо за любое понимание этого, --Phill
Обновить:
Если я получу входящее сообщение и распечатаю ответ, должно ли это произойти первым, независимо от того, сделаю ли я что-нибудь еще после?Или он ждет завершения моего процесса, а затем печатает ответ?
ОБНОВЛЕНИЕ №2:
ладно, я думаю, у меня проблема:PHP использует однопоточный подход к обработке и не будет отправлять обратно файл ACK до тех пор, пока поток не завершит его обработку.Есть ли способ сделать это многопоточным процессом?Поток # 1 - примите входящий запрос SOAP и отправьте обратно подтверждение Поток # 2 - Обработайте запрос SOAP
Я знаю, что мог бы разбить его на что-то вроде таблицы базы данных или плоского файла, но есть ли способ добиться этого, не делая этого?
Я собираюсь попытаться закрыть сокет после отправки подтверждения и продолжить обработку, скрестив пальцы, это сработает.
Решение 5
Итак, что я сделал, это:
- Принимайте все входящие OBM, преобразуйте их в базу данных
- Когда это будет сделано, запускайте процесс, который выполняется в фоновом режиме (на самом деле я отправляю его в фоновый режим, чтобы скрипт мог завершиться)
- Отправить файл подтверждения обратно
Просто принимая необработанные данные, разбор на поля и вставка их в базу данных выполняется довольно быстро.Затем я запускаю команду командной строки Linux, которая также отправляет скрипт обработки для запуска в фоновом режиме.Затем я отправляю файл подтверждения в SF, и скрипт завершается в течение отведенного времени.Разбивать процесс написания сценария на два отдельных этапа громоздко, но это работает.
Другие советы
Похоже, что время ожидания исходящего сообщения истекло.Другие пользователи сообщали о таймаутах всего в 10 секунд (см. Ссылку на форум ниже).У экземпляра песочницы, который я использую (cs1), истекает время ожидания примерно через 1 минуту после моего тестирования.Возможно, что время ожидания является параметром уровня организации или экземпляра, которым управляет Salesforce.
Две вещи, которые вы могли бы попробовать:
Откройте запрос в службу поддержки Salesforce, чтобы узнать, могут ли они увеличить время ожидания для исходящих сообщений.Исходя из моего опыта, существует множество настроек, которые они могут изменять на уровне организации - это может быть одна из них.
Разгрузите обработку ваших данных, чтобы подтверждение было немедленно отправлено обратно в Salesforce.Тогда фактическая обработка ваших данных будет происходить асинхронно.т.е.Сообщение очередь, отдельный поток и т.д.
Некоторые другие ресурсы, которые могли бы быть полезны:
Я думаю, что они приостанавливают работу, ожидая завершения Вашего сценария.
Есть способ, которым вы могли бы попытаться это исправить.
Выведите конверт с сообщением ack в начале, а затем сбросьте его, чтобы их сервер получил его до того, как вы завершите обработку.Никакой многопоточности, просто переосмысление приоритетов :)
прочтите это для получения наилучшей информации о содержимом для промывки
Вы на 100% уверены, что Salesforce будет ждать столько времени, сколько потребуется для запуска ваших скриптов?80 секунд мне тоже кажутся долгим сроком.
Если все запросы завершились неудачей, я бы предположил, что Salesforce ожидает, что вы установите Content-Type
заголовок соответствующий, но, похоже, это не тот случай.
Я не знаю насчет Salesforce, но если вы хотите использовать многопоточность с помощью PHP, вам следует взглянуть на этот пример кода а точнее , к pcntl_fork().
N.B:pcntl - это нет включен по умолчанию и не будет работать на платформах Windows.