Как я могу прочитать тело запроса JSON, чтобы я мог работать с ним после ответа на запрос? - PullRequest
0 голосов
/ 11 июля 2019

Я пишу HTTP-сервер для обработки API сканирования Cisco Meraki. Это push-API, в котором Cisco периодически вызывает вашу конечную точку с помощью запроса POST и тела JSON. API должен быть в состоянии ответить на этот запрос POST менее чем за 500 мс. Если нет, Cisco прекратит отправку вам данных, и вы не сможете восстановить эту информацию.

Итак, я искал способы обработать эти запросы как можно быстрее.

Первым делом я отделил обработку тела JSON с помощью очереди. Я беру тело из запроса, помещаю его в очередь и отвечаю. Затем несколько рабочих будут обрабатывать тело и асинхронно сохранять его на S3. Я также попытался сделать сервер максимально простым.

Большинство запросов работают менее чем за 500 мс, но некоторые - нет. Глядя на то, где я нахожусь, единственное, что приходит в голову, чтобы улучшить это время, это быстрее обработать тело запроса.

Весь сервер доступен по этой ссылке: meraki_endpoint.go . И вот как я сейчас обрабатываю тело запроса:

func handleData(w http.ResponseWriter, r *http.Request, jobs chan job) {
  var devicesSeen DevicesSeen
  // I am using "github.com/json-iterator/go" instead of "encoding/json"
  err := json.NewDecoder(r.Body).Decode(&devicesSeen)
  if err != nil {
    http.Error(w, "Bad request - Can't Decode!", 400)
    panic(err)
  }
  // Create Job and push the work into the Job Channel
  go func() {
    jobs <- job{devicesSeen}
  }()
  // Render success
  w.WriteHeader(http.StatusAccepted)
}

В данный момент я декодирую JSON при чтении из тела вместо чтения и сохраняю его как список байтов, используя ioutil.ReadAll(r.Body). Попробовав оба пути, я не смог найти существенного улучшения скорости.

Как я могу улучшить производительность сервера? Или как я могу быстрее прочитать тело запроса, чтобы потом работать с ним в очереди?


Редактировать # 1

Я переместил свой стек в другой регион AWS, ближе к источнику данных, и время туда и обратно сократилось до одной пятой от того, что было раньше.

1 Ответ

1 голос
/ 11 июля 2019

Не похоже, что вы могли бы прочитать тело намного быстрее, особенно если вы уже пытались просто сделать ioutil.ReadAll(r.Body) вместо его декодирования.

И поскольку из того, что вы наблюдаете, большинство запросов действительно быстрые,Возможно, ваша проблема не в том, что функция handleData.

Вот некоторые вещи, которые стоит попробовать:

  • Играть с различными настройками "max_workers"

Есликоличество ожидающих запросов слишком велико, несмотря на дешевизну, они занимают некоторую память, так что ваш сервер может все равно замедляться, особенно если здесь играет роль сборщик мусора, что приводит нас к следующему пункту.

  • Попробуйте профилировать GC или поиграйте с другими настройками

Здесь у вас есть документация времени выполнения, включая переменную GOGC, которую вы можете попробовать настроить, плюс некоторые флаги, которые вы можете попробовать использовать для профилированияGC делает паузу (см., Например, gctrace флаг там)

https://golang.org/pkg/runtime/

Эти блоги также могут помочь, они детализируют некоторые проблемы, которые они виделис GC на большом объеме обработки и как они работали с теми, кто улучшал производительность GC: * ​​1026 *

https://blog.cloudflare.com/go-dont-collect-my-garbage/

https://blog.twitch.tv/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap-26c2462549a2

  • Горизонтальное масштабирование

Вы не описываете всю свою установку, но, возможно, у вас есть группа серверов с балансировкой нагрузки?Если объем слишком велик, возможно, что количество имеющихся у вас серверов не справится с нагрузкой, в этом случае вы можете попробовать добавить больше серверов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...