38
Skalierbare Anwendungen mit Google Go

Skalierbare Anwendungen mit Google Go

Embed Size (px)

DESCRIPTION

Vortrag der OOP 2014 Überblick über die Vorteile der Programmiersprache Go für skalierbare Anwendungen sowie ein Einblick in hierbei zu beachtende Probleme und ihre Lösung.

Citation preview

Page 1: Skalierbare Anwendungen mit Google Go

Skalierbare Anwendungen mit Google Go

Page 2: Skalierbare Anwendungen mit Google Go

Frank Müller

Oldenburg Baujahr 1965

Entwickler Fachautor

!

[email protected] @themue

Page 3: Skalierbare Anwendungen mit Google Go

Moderne Mehrkernsysteme sind wie dieVereinigung von Flüssen

Page 4: Skalierbare Anwendungen mit Google Go

Ihre Energie gilt eseffizient zu nutzen

Page 5: Skalierbare Anwendungen mit Google Go

Hier bietet sich Google Go an

Page 6: Skalierbare Anwendungen mit Google Go

Google Go als multikulturelle Sprache

imperativ

bedingt funktional

bedingt objektorientiert

nebenläufig

Page 7: Skalierbare Anwendungen mit Google Go

❝It’s better to have a permanent income than to be fascinating.

–Oscar Wilde

Page 8: Skalierbare Anwendungen mit Google Go

Nebenläufigkeit in Go

• Leichtgewichtige Goroutines im Thread Pool

• Sehr große Anzahl gleichzeitig möglich

• Kommunikation und Synchronisation über Channels

• Vielfältige Kontrolle durch select Statement

Page 9: Skalierbare Anwendungen mit Google Go

Beispiel: Goroutines als Server

Client

Client

Client

Server

Page 10: Skalierbare Anwendungen mit Google Go

Beispiel: Lastverteilung

Worker

Worker

Master

Client

Client Worker

Page 11: Skalierbare Anwendungen mit Google Go

Netze von Goroutines

B

A

F

E 2E 1

E

E 3

C D

G

Page 12: Skalierbare Anwendungen mit Google Go

Ein Wimmeln wieim Bienenstock

Page 13: Skalierbare Anwendungen mit Google Go

Kapselung in Typen

package service !type Service struct { thisChan chan *This thatChan chan *That foo bool bar int baz string }

Page 14: Skalierbare Anwendungen mit Google Go

Konstruktoren sind Funktionen

func NewService(...) *Service { s := &Service{ thisChan: make(chan *This), thatChan: make(chan *That, 10), …, } ! // Start of the backend loop as goroutine. go s.loop() ! return s }

Page 15: Skalierbare Anwendungen mit Google Go

Endlosschleifen und select

func (s *Service) loop() { ticker := time.NewTicker(time.Second) for { select { case this := <-s.thisChan: s.doThis(this) case that := <-s.thatChan: s.doThat(that) case <-ticker.C: s.doTick() } } }

Page 16: Skalierbare Anwendungen mit Google Go

Methoden als externe Schnittstellen

func (s *Service) DoThis(data string) int { respChan := make(chan int) this := &This{data, respChan} ! s.thisChan <- this return <-respChan }

Page 17: Skalierbare Anwendungen mit Google Go

Goroutines können eigene Wege gehen …

Page 18: Skalierbare Anwendungen mit Google Go

… oder gemeinsame

Page 19: Skalierbare Anwendungen mit Google Go

Herausforderungen nebenläufiger Anwendungen

Rechenleistung nutzen

Rennen kontrollieren

Konflikte vermeiden

Probleme abfedern

Page 20: Skalierbare Anwendungen mit Google Go

Sehr naive Parallelisierung (1)

func process(in []int) []int { resultChan := make(chan int) for _, value := range in { // One goroutine per value. go processValue(value, resultChan) } out := make([]int, 0) for i := 0; i < len(in); i++ { out = append(out, <-resultChan) } return out }

Page 21: Skalierbare Anwendungen mit Google Go

Sehr naive Parallelisierung (2)

func processValue( inValue int, resultChan chan int) { // Time of result calculation depends // on value. outValue := inValue … ! resultChan <- outValue }

Page 22: Skalierbare Anwendungen mit Google Go

Verbesserung

• Index in der Verarbeitung mitführen

• Output mit richtiger Größe initialisieren

• Ergebnis gemäß Index setzen

Page 23: Skalierbare Anwendungen mit Google Go

Verbesserung (1)

func process(in []int) []int { resultChan := make(chan *result) for index, value := range in { // One goroutine per value. go processValue(index, value, resultChan) } out := make([]int, len(in)) for i := 0; i < len(in); i++ { result <- resultChan out[result.index] = result.value } return out }

Page 24: Skalierbare Anwendungen mit Google Go

Verbesserung (2)type result struct { index int value int } !func processValue( index, inValue int, resultChan chan *result) { // Time of result calculation depends // on value. outValue := inValue … ! // Send index with result. resultChan <- &result{index, outValue} }

Page 25: Skalierbare Anwendungen mit Google Go

Isolierung von Zugriffen

• Loops serialisieren Zugriffe

• Synchronisation über Channels oder Package sync

• Referenzen nur an eine Goroutine senden

• Aufteilung von Arrays und Slices

Page 26: Skalierbare Anwendungen mit Google Go

Unabhängigkeit von Goroutines

• Keine Beziehung zwischen Goroutines

• Kontrolle nur über Channels

• Externe Packages helfen

• git.tideland.biz/goas/loop

• launchpad.net/tomb

Page 27: Skalierbare Anwendungen mit Google Go

Schleifenfunktion

func (t *MyType) backendLoop(l loop.Loop) error { for { select { case <-l.ShallStop(): return nil case foo := <-t.fooChan: if err := t.processFoo(foo); err != nil { return err } case …: … } } }

Page 28: Skalierbare Anwendungen mit Google Go

Kontrolle der Schleifenfunktion

// Start of the goroutine in constructor. t.loop = loop.Go(t.backendLoop) !// Tell loop to stop. err := t.loop.Stop() !// Kill loop with passed error and wait. t.loop.Kill(myError) err := t.loop.Wait() !// Retrieve status and possible error. status, err := t.loop.Error()

Page 29: Skalierbare Anwendungen mit Google Go

Deadlocks vermeiden (Timeout)

func (t *MyType) Foo(foo *Foo) error { select { case t.fooChan <- foo: case <-time.After(timeout): return errors.New("timed out") } return nil }

Page 30: Skalierbare Anwendungen mit Google Go

Deadlocks vermeiden (Loop)

func (t *MyType) Foo(foo *Foo) error { select { case t.fooChan <- foo: case <-t.loop.IsStopping(): return errors.New("not running anymore") } return nil }

Page 31: Skalierbare Anwendungen mit Google Go

Vernetzung

Page 32: Skalierbare Anwendungen mit Google Go

Hilfreiche Packages

• net, …/http für IP und Web

• html/template, mime/… für Inhalte

• encoding/gob, …/json, …/xml für die Serialisierung

• compress/… zur Komprimierung

• crypto/… zur Verschlüsselung

Page 33: Skalierbare Anwendungen mit Google Go

Externe Packages von Google

• WebSocket, SPDY, Dict und mehr in code.google.com/p/go.net

• Weitere Crypto Packages (u.a. OpenPGP) in code.google.com/p/go.crypto

Page 34: Skalierbare Anwendungen mit Google Go

Serialisierung via JSON

type OrderItem struct { Id int `json:"ArticleNo"` Quantity int } !type Order struct { Name string Street string City string Remarks string `json:",omitempty"` Items []OrderItem }

Page 35: Skalierbare Anwendungen mit Google Go

Marshalling

order := Order{ Name: "Foo Bar", … Items: []OrderItem{{4711, 1}, {4712, 5}, …}, } !marshalledOrder, err := json.Marshal(order) if err != nil { … } !n, err := anyWriter.Write(marshalledOrder)

Page 36: Skalierbare Anwendungen mit Google Go

Unmarshalling

var order Order !err := json.Unmarshal(marshalledOrder, &order) if err != nil { … } !fmt.Printf("Name: %s\n", order.Name)

Page 37: Skalierbare Anwendungen mit Google Go

Fallbeispiel einer API

Netz und Crypto

Reflection für Dispatching

WebSockets

Serialisierung via JSON

Page 38: Skalierbare Anwendungen mit Google Go

❝Zitat hier eingeben.

–Christian BauerBildquellen 123RFiStockphotoeigene Quellen