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

如何读取请求JSON正文,以便在响应请求后使用它?,json,http,ssl,go,Json,Http,Ssl,Go,我正在编写一个HTTP服务器来处理Cisco Meraki扫描API。这是一个推送API,Cisco在其中定期使用POST请求和JSON正文调用您的端点。API必须能够在500毫秒内响应此POST请求。否则,Cisco将停止向您发送数据,您将无法恢复该信息 因此,我一直在寻找尽可能快地处理这些请求的方法 我做的第一件事是通过使用队列来解耦JSON主体的处理。我从请求中取出主体,将其放入队列,然后响应。然后,几个工作人员将处理主体并将其异步存储在S3上。我还试图使服务器尽可能简单 大多数请求在不到

我正在编写一个HTTP服务器来处理Cisco Meraki扫描API。这是一个推送API,Cisco在其中定期使用POST请求和JSON正文调用您的端点。API必须能够在500毫秒内响应此POST请求。否则,Cisco将停止向您发送数据,您将无法恢复该信息

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

我做的第一件事是通过使用队列来解耦JSON主体的处理。我从请求中取出主体,将其放入队列,然后响应。然后,几个工作人员将处理主体并将其异步存储在S3上。我还试图使服务器尽可能简单

大多数请求在不到500毫秒的时间内工作,但有些请求不工作。看看我现在的处境,要想提高这些时间,我想到的唯一一件事就是更快地处理请求体

整个服务器在此链接上可用:。这就是我目前处理请求机构的方式:

func handleData(w http.ResponseWriter,r*http.Request,jobs-chan-job){
var DeviceSeen DeviceSeen
//我使用的是“github.com/json迭代器/go”而不是“encoding/json”
err:=json.NewDecoder(r.Body.Decode)(&DeviceSeen)
如果错误!=零{
错误(w,“错误请求-无法解码!”,400)
恐慌(错误)
}
//创建作业并将作业推入作业通道
go func(){

jobs看起来你读正文的速度并不是很快,特别是如果你已经尝试过只做一个
ioutil.ReadAll(r.body)
而不是解码它

从您观察到的情况来看,大多数请求确实很快,因此您的问题可能不是
handleData
功能

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

  • 使用不同的“max_workers”设置播放
如果挂起的请求太多,即使goroutine很便宜,它们也会占用一些内存,因此您的服务器可能会慢下来,特别是如果垃圾收集在其中扮演了角色,这将导致我们进入下一步

  • 尝试配置GC,或者使用不同的设置
这里有运行时文档,包括可以尝试调优的
GOGC
变量,以及可以尝试用于分析GC暂停的一些标志(例如,请参见此处的
gctrace
标志)

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

  • 水平缩放

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

为什么不在假设请求正常的情况下对JSON进行evern解码的情况下重新启动?顺便问一下,是500毫秒还是50毫秒0微秒-我不明白为什么需要半秒才能响应,除非有其他事情发生。这是500毫秒的往返时间。我现在修改了代码,不再解码,而是返回到只读取它,并将字节缓冲区传递给队列。使用此:
DeviceSeen,err:=ioutil.ReadAll(r.Body)
它似乎工作得更快。这就是你的意思吗?也许你可以通过预先分配一个
[]字节
基于请求的内容长度标头。另一种解决方案是简单地将
r.Body
传递到一个频道,因为它应该能够在离开请求范围后继续存在。但一般来说,由于代码中找不到的原因,往返次数更可能增加。您是否对其进行了基准测试?这将有助于吃点testdata@MarkusWMahlberg,我已经从我的设置中对它进行了基准测试,它应该可以工作。大部分时间都花在SSL握手上,而不是处理请求。我对将
r.Body
传递到频道有疑问,不应该响应请求关闭读卡器?谢谢你的回答。设置是独立的d在AWS中的自动缩放组中使用m5a.large EC2实例,前面有一个ALB。我将尝试您的第二个建议。