Действия Apache OpenWhisk вызываются путем отправки HTTP-запросов POST в API платформы. Запросы на вызов имеют два разных режима: блокирующий и неблокирующий.
Блокировка вызовов означает, что платформа не будет отправлять HTTP-ответ, пока действие не завершится. Это позволяет включить результат действия в ответ. Блокирующие вызовы используются, когда вы хотите вызвать действие и дождаться результата.
$ wsk action invoke my_action --blocking
ok: invoked /_/my_action with id db70ef682fae4f8fb0ef682fae2f8fd5
{
"activationId": "db70ef682fae4f8fb0ef682fae2f8fd5",
...
"response": {
"result": { ... },
"status": "success",
"success": true
},
...
}
Неблокирующие вызовы возвращаются, как только платформа обрабатывает запрос на вызов. Это происходит до завершения действия. Ответы HTTP от неблокирующих вызовов включают только идентификаторы активации, поскольку результат действия недоступен.
$ wsk action invoke my_action
ok: invoked /_/my_action with id d2728aaa75394411b28aaa7539341195
HTTP-ответы от блокирующего вызова будут ждать только ограниченное время перед возвратом. По умолчанию это значение равно 65 секундам в файле конфигурации платформы. Если вызов действия не завершился до истечения этого тайм-аута, возвращается ответ состояния HTTP 5xx.
Хммм… 🤔
"Итак, как вы можете вызвать действие и дождаться результата, если действия занимают больше времени, чем это ограничение?"
Этот вопрос регулярно возникает у разработчиков, создающих приложения с использованием платформы. Я решил превратить свой ответ в сообщение в блоге, чтобы помочь другим, борющимся с этой проблемой (после того, как снова ответил на этот вопрос на этой неделе 😎).
решение
- Вызовите действие с помощью неблокирующего вызова.
- Используйте возвращенный идентификатор активации для опроса API результатов активации.
- Ответ HTTP для результата активации будет возвращать ответ HTTP 404, пока действие не завершится.
Когда опрос для активации является результатом неблокирующих вызовов, вы должны установить ограничение на максимально допустимое время опроса. Это связано с тем, что ошибки HTTP 404 могут возвращаться из-за других сценариев (например, из-за недопустимых идентификаторов активации). Применение ограничения по времени гарантирует, что в случае проблем в коде приложения или платформе цикл опроса в конечном итоге остановится!
Хорошим подходом является установка максимального времени опроса на время ожидания действия (плюс небольшое смещение).
Действие не может выполняться дольше его тайм-аута. Если запись активации недоступна по истечении этого времени (плюс небольшое смещение для обработки внутренних задержек платформы), что-то пошло не так. Продолжение опроса после этого момента рискует превратить операцию опроса в бесконечный цикл…
пример кода
В этом примере представлена реализация этого подхода для Node.js с использованием JavaScript Client SDK.
"use strict";
const openwhisk = require('openwhisk')
const options = { apihost: <API_HOST>, api_key: <API_KEY> }
const ow = openwhisk(options)
// action duration limit (+ small offset)
const timeout_ms = 85000
// delay between polling requests
const polling_delay = 1000
// action to invoke
const action = 'delay'
const now = () => (new Date().getTime())
const max_polling_time = now() + timeout_ms
const delay = async ms => new Promise(resolve => setTimeout(resolve, ms))
const activation = await ow.actions.invoke({name: action})
console.log(`new activation id: ${activation.activationId}`)
let result = null
do {
try {
result = await ow.activations.get({ name: activation.activationId })
console.log(`activation result (${activation.activationId}) now available!`)
} catch (err) {
if (err.statusCode !== 404) {
throw err
}
console.log(`activation result (${activation.activationId}) not available yet`)
}
await delay(polling_delay)
} while (!result && now() < max_polling_time)
console.log(`activation result (${activation.activationId})`, result)
проверить это
Вот исходный код действия, которое не вернется, пока не пройдет 70 секунд. Блокировка вызовов, запускающих это действие, приведет к тайм-ауту HTTP перед возвратом ответа.
const delay = async ms => new Promise(resolve => setTimeout(resolve, ms))
function main() {
return delay(70*1000)
}
Используя приведенный выше сценарий, результат действия будет получен из неблокирующего вызова.
- Создайте действие из исходного файла в приведенном выше примере.
wsk action create delay delay.js --timeout 80000 --kind nodejs:10
- Запустите скрипт Node.js, чтобы вызвать это действие и опросить результат активации.
node script.js
Если сценарий работает правильно, в сообщениях журнала будет отображаться статус опроса, а затем результат активации.
$ node script.js
new activation id: d4efc4641b544320afc4641b54132066
activation result (d4efc4641b544320afc4641b54132066) not available yet
activation result (d4efc4641b544320afc4641b54132066) not available yet
activation result (d4efc4641b544320afc4641b54132066) not available yet
...
activation result (d4efc4641b544320afc4641b54132066) now available!
activation result (d4efc4641b544320afc4641b54132066) { ... }
Первоначально опубликовано на http://jamesthom.as 14 мая 2019 г.