Gustavo Niemeyer

Canonical

Keith Rarick

Heroku

What is Heroku?

  • PaaS for web applications in all languages
  • 1.9 million apps
  • About 85 employees
  • Each active app runs one or more “dynos” – lightweight process containers

Routing Table

  • Changes whenever a Heroku dyno starts, stops, or moves
  • For example, heroku scale web=5
  • >1.9 million Heroku apps; a fraction of these are active at any time
  • Plenty of churn

Routing Table Service

  • Originally all Ruby
  • Accepts updates from the process manager
  • HTTP router gets state from HTTP calls to this service
  • Initial JSON dump to each HTTP router instance
  • Followed by a stream of updates

The Problem

  • Route lookups are fast – no IPC
  • But bootstrapping a new router instance is slow
  • Why? Generating the initial dump

Enter Go

  • Goal: drop-in replacement for the “streaming updates” piece
  • Easy enough to play with during a single afternoon
  • Working prototype after a couple of hours

Slam Dunk

  • 10× speedup
  • Generating process (in Go) is no longer the bottleneck
  • (Nor is the network)
  • Easy to deploy and monitor, works great, so now in production

Go at Heroku

  • Started with experiments and side projects
  • Now using Go for a handful of production services
  • The list is growing

Evan Shaw

Iron.io

Iron.io
  • Cloud application services
  • Remove infrastructure worries
  • Enable small teams to do big things
IronWorker
  • Massively parallel worker platform
  • API originally written with Ruby on Rails
  • It was too slow
  • Rewriting it in Go made it faster

Other products

  • IronMQ, scalable message queue
  • IronCache, distributed key/value store
  • REST/HTTP API and text protocol support

The flow of IronWorker tasks

Handling an HTTP request

  • Compose HTTP handlers
    • Authentication
    • Database connection sharing
    • Statistics and usage

Concurrency

  • HTTP requests handled in separate goroutines by the HTTP package
  • For text protocols, one goroutine per client connection
  • Asynchronous I/O is automatic

Concurrency as an optimization

  • Non-critical operations can be moved to a separate goroutine
  • Even less critical operations can be batched together in a dedicated goroutine

Concurrency as an optimization

Before:

func handler(w http.ResponseWriter, r *http.Request) {
  projectId := getProjectId(r)
  updateStatistics(projectId)
  // ...
}

After:

func handler(w http.ResponseWriter, r *http.Request) {
  go func() {
    projectId := getProjectId(r)
    go updateStatistics(projectId)
  }()
  // ...
}

Why Go?

  • Fast
  • Still reasonably expressive
  • Rich standard library
  • Not tied to a VM
  • Awesome

Patrick Crosby

StatHat

Q&A

Questions: http://goo.gl/KZsoo