Отправка асинхронных запросов cURL в AWS в C ++ - PullRequest
0 голосов
/ 30 ноября 2018

Для проекта я пытаюсь использовать 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;
}

У меня есть два вопроса относительно вышеуказанного кода:

  1. Когда я превышаю 50-100 работников AWS, я наблюдаю за OpenSSLошибки в моих журналах, если я не заставляю потоки спать некоторое время.Это разумно, или я делаю что-то не так?Я считаю, что я правильно использую многопоточный подход, так как я вызываю curl_global_init один раз, прежде чем запускать свои потоки, что упоминается в документации .Есть ли более чистый способ сделать то, что я пытаюсь сделать?
  2. Лямбда-работники называют дочерний процесс (я использую worker.js в AWS, который вызывает скомпилированную среду выполнения C ++ как дочерний процесс), иони дают функцию, отвечающую за возврат объекта JSON (просто некоторый журнал) в качестве обратного вызова для дочернего процесса.Другими словами, шлюз отвечает, когда работники заканчивают свою работу или просто получают тайм-аут (15 минут).Следовательно, я вижу сообщения таймаута в моем журнале, приходящие от моих создателей.Просмотр сообщений о тайм-ауте от cURL не имеет большого значения, так как моя логика алгоритма в главном процессе знает, что происходит, проверяя рабочие индексы, прикрепленные к рабочим сообщениям.Вопрос в том, могу ли я найти решение, в котором я просто отправляю запросы cURL на шлюз без ожидания ответа и одновременно , гарантируя, что рабочие порождаются (без SSLпроблемы вообще).

Спасибо заранее за ваше время!

...