I am writing an HTTP server to handle Cisco Meraki Scanning API. It is a push API, in which Cisco periodically calls your endpoint with a POST request and a JSON body. The API must be able to respond to this POST request in less than 500ms. If not, Cisco will stop sending you data, and you can't recover that information.
So, I have been looking for ways to handle these requests as fast as I can.
The first thing I did was decouple the processing of the JSON body by using a queue. I take the Body from the request, put it in the queue, and respond. Then, several workers will process the body and store it on S3 asynchronously. I also tried to make the server as simple as possible.
Most requests work in less than 500ms, but some don't. Looking at where I am, the only thing that comes to mind to improve these times is to process the body of the request faster.
The whole server is available on this link: meraki_endpoint.go. And this is how I am handling the request body at the moment:
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)
}
At the moment I am decoding the JSON as I read if from the body, instead of reading it and store it as a list of bytes using ioutil.ReadAll(r.Body)
. After trying both ways, I couldn't find a significant speed improvement.
How can I improve the performance of the server? Or, how can I read the body of the request faster so I can work on it later on the queue?
Edit #1
I moved my stack to another AWS region, closer to the source of the data, and the roundtrip time descended to a fifth of what it was before.