Для проекта я пытаюсь использовать AWS Lambda , чтобы увеличить мои вычисления.Поскольку проекту требуются связь / синхронизация между рабочими узлами, я запускаю статический основной процесс (обычно мой ноутбук) для координации между рабочими.
Однако у меня возникли некоторые проблемы при использовании cURL Easy C-API , особенно когда я имею дело с W > 256
лямбда-работниками.По сути, я формирую запросы POST и отправляю его в API шлюза AWS, используя несколько потоков (для этого я использую C ++ 11).Примерная выдержка из кода выглядит следующим образом:
/* #include cURL and other libraries */
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
auto data = static_cast<string *>(userdata);
*data = string(ptr, nmemb);
return nmemb;
}
void spawn_worker(const string &gateway, const string &address,
const uint16_t port, const index_t widx) {
// Below was needed to overcome excessive SSL library errors
this_thread::sleep_for(chrono::milliseconds(widx * 10));
const string post(/* post data */);
CURL *handle = nullptr;
string data;
ofstream log("worker-" + to_string(widx) + ".log");
do {
curl_easy_cleanup(handle);
handle = curl_easy_init();
try {
if (handle != nullptr) {
curl_easy_setopt(handle, CURLOPT_URL, gateway.c_str());
curl_easy_setopt(handle, CURLOPT_POST, 1);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, post.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
log << "Sending the post data: " << post << '\n';
CURLcode res = curl_easy_perform(handle);
if (res != CURLE_OK)
throw runtime_error(curl_easy_strerror(res));
log << "curl_easy_perform() returned:\n" << data << '\n';
break;
} else
throw runtime_error("Cannot initialize cURL.");
} catch (const exception &e) {
log << "Exception occured: " << e.what() << '\n';
this_thread::sleep_for(chrono::milliseconds(10));
};
} while (true);
curl_easy_cleanup(handle);
}
int main(int argc, char *argv[]) {
/* variables */
curl_res = curl_global_init(CURL_GLOBAL_ALL);
if (curl_res != 0)
return -1;
/* W: the total number of active Lambda functions needed */
vector<thread> spawners(W);
index_t w{0};
for (auto &spawner : spawners)
spawner = thread(spawn_worker, gateway, address, port, w++);
/* algorithm logic */
curl_global_cleanup();
return 0;
}
У меня есть два вопроса относительно вышеуказанного кода:
- Когда я превышаю 50-100 работников AWS, я наблюдаю за OpenSSLошибки в моих журналах, если я не заставляю потоки спать некоторое время.Это разумно, или я делаю что-то не так?Я считаю, что я правильно использую многопоточный подход, так как я вызываю
curl_global_init
один раз, прежде чем запускать свои потоки, что упоминается в документации .Есть ли более чистый способ сделать то, что я пытаюсь сделать? - Лямбда-работники называют дочерний процесс (я использую
worker.js
в AWS, который вызывает скомпилированную среду выполнения C ++ как дочерний процесс), иони дают функцию, отвечающую за возврат объекта JSON (просто некоторый журнал) в качестве обратного вызова для дочернего процесса.Другими словами, шлюз отвечает, когда работники заканчивают свою работу или просто получают тайм-аут (15 минут).Следовательно, я вижу сообщения таймаута в моем журнале, приходящие от моих создателей.Просмотр сообщений о тайм-ауте от cURL не имеет большого значения, так как моя логика алгоритма в главном процессе знает, что происходит, проверяя рабочие индексы, прикрепленные к рабочим сообщениям.Вопрос в том, могу ли я найти решение, в котором я просто отправляю запросы cURL на шлюз без ожидания ответа и одновременно , гарантируя, что рабочие порождаются (без SSLпроблемы вообще).
Спасибо заранее за ваше время!