如何读取请求JSON正文,以便在响应请求后可以使用它?

时间:2019-07-11 01:24:04

标签: json http ssl go

我正在编写一个HTTP服务器来处理Cisco Meraki Scanning API。它是一个推式API,Cisco在其中定期通过POST请求和JSON正文调用您的端点。 API必须能够在不到500毫秒的时间内响应此POST请求。如果没有,思科将停止向您发送数据,并且您将无法恢复该信息。

因此,我一直在寻找尽快处理这些请求的方法。

我做的第一件事是通过使用队列来分离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 个答案:

答案 0 :(得分:1)

看起来您读得更快,特别是如果您已经尝试仅执行ioutil.ReadAll(r.Body)而不是对其进行解码的话。

由于您所观察到的大多数请求的确确实是快速的,所以可能您的问题不是那个handleData函数。

以下是一些可以尝试的东西:

  • 使用不同的“ max_workers”设置播放

如果未决请求的数量太大,即使goroutine很便宜,它们也确实会占用一些内存,因此您的服务器可能无论如何都会变慢,特别是如果垃圾回收在其中起作用的话,这将使我们进入下一个子弹。

  • 尝试对GC进行配置文件,或者使用其他设置进行播放

这里有运行时文档,包括您可以尝试调整的GOGC变量,以及一些可以用来配置GC暂停的标志(例如,请参见那里的gctrace标志)

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

这些博客也可能会有所帮助,它们详细介绍了处理大量GC时遇到的一些问题,以及如何解决那些改善GC性能的问题:

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

  • 水平缩放

您没有描述整个设置,但是可能您有一组服务器负载均衡?如果数量很高,则可能的原因是您拥有的服务器数量无法处理负载,在这种情况下,您可以尝试添加更多服务器。