3 secrets to build web APIs in Go Matt Aimonetti - splice.com - @mattetti

Matt Aimonetti

golangbootcamp.com

splice: Go, Ruby, JS, Obj-C, C#, C++, C

Splice

Splice

Architecture clients

APIs / core logic

web rendering

Architecture Obj-C

C Go

Web API: Synchronization File upload File download Notifications

C#

Architecture

file parsing/analysis (sessions, media) deduplication/storage intermediate representation

Architecture

internal/private API (application logic)

“public” API (states retrieval/change)

Architecture

Message Bus HTTP

Long running async tasks

Go vs Ruby

20-100x faster to run 10-20% slower to write 60-80% less maintenance required batteries included

• • •

Deployment Routing Monitoring

Deployment

Zero downtime deployments bitbucket.org/splice/go.grace

g h t i w l u f care

s e n i t orou

Deployment

Version Control

CI

Storage

Deployment

Deployment

current/api

symlink

2014-06-23-183000/api

2014-06-23-204500/api

Deployment

current/api

symlink

2014-06-23-183000/api

2014-06-23-204500/api

$ kill -USR2 {api PID}

Routing var V42Routes = Endpoints{ // create Ableton Live session { Verb: "POST", Path: "/v42/live/sessions", Handler: handlers.AlsUpload, RequiredParams: handlers.AlsUploadReqParams, Auth: splice.ClientAuth, }, // create Logic session { Verb: "POST", Path: "/v42/logic/sessions", Handler: handlers.LogicUpload, RequiredParams: handlers.LogicUploadReqParams, Auth: splice.ClientAuth, }, }

Routing

package router   type Endpoint struct { Verb string Path string RequiredParams []string Auth func(*splice.ReqEnv, bool) bool Handler splice.Handler }

Routing type Endpoints []Endpoint   // Activate all the endpoint API routes.

func (es Endpoints) Activate(p *pat.PatternServeMux) { for _, e := range es { // [..] set authentication calls // [..] check param requirements

handler := splice.ReqWrap(e.Handler, e.Auth) p.Add(e.Verb, e.Path, handler) // [..] collect all CORS verbs accepted for this endpoint so we can create OPTIONS routes.

} }

Routing func ReqWrap(handler *Handler, checkAuthFn func(*ReqEnv, bool) bool) http.Handler { !   return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() defer reportRequest(req, start, handler.Metrics) reqUuid := uuid.GenUUID() req := &ReqEnv{ ReqUuid: reqUuid, Request: r, Response: &statusResponseWriter{w, 0}, } // [..] set headers (content type, req ID, build) if !checkAuthFn(req, checkAuth) { return }

! ! !

Routing ! ! !

// We must return a 400 and stop here if there was a problem // parsing the request. err := req.ParseParams() if err != nil { // […]return 400 return } // convert a panic into a 500 defer req.handlePanic() handler.Handle(req) })

}

Monitoring

Monitor all the things!

runtime.ReadMemStats http://golang.org/pkg/runtime/#MemStats

Lessons learned

low memory usage

Lessons learned

detect issues

Lessons learned

detect issues

Low memory usage

use streaming io.Reader/io.Writer io.Copy

Encoder/Decoder instead of ReadAll and Unmarshal

Monitoring

Monitor all the things! Per endpoint: • # of requests • Status codes • Response times

@mattetti http://matt.aimonetti.net

go at splice - gosf

to build web APIs in Go. Matt Aimonetti - splice.com - @ ... Architecture. Web API: Synchronization. File upload. File download. Notifications. Obj-C. C#. C. Go ...

6MB Sizes 1 Downloads 121 Views

Recommend Documents

No documents