Skalierbare Anwendungen
mit Google Go
Frank Müller

Oldenburg
Baujahr 1965
Entwickler
Fachautor
!

frank@mweb.de
@themue
Moderne
Mehrkernsysteme

sind wie die

Vereinigung von Flüssen
Ihre Energie gilt es

effizient zu nutzen
Hier bietet sich

	 	 	 	 	 	 	 Google Go an
imperativ

bedingt objektorientiert

Google Go als multikulturelle Sprache

bedingt funktional

nebenläufig
❝
It’s better to have a permanent
income than to be fascinating.
–Oscar Wilde
Nebenläufigkeit in Go

•

Leichtgewichtige Goroutines im Thread
Pool


• Sehr große Anzahl gleichzeitig möglich

• Kommunik...
Beispiel: Goroutines als Server
Client

Client

Client

Server
Beispiel: Lastverteilung
Worker

Client

Master

Client

Worker

Worker
Netze von Goroutines
A
C

D

B
E

F

G
E1

E2

E3
Ein Wimmeln wie

im Bienenstock
Kapselung in Typen
package service
!

type Service struct {
	 thisChan	 chan *This
	 thatChan	 chan *That
	 foo	 	 	 bool
...
Konstruktoren sind Funktionen
func NewService(...) *Service {
	 s := &Service{
	 	 thisChan: make(chan *This),
	 	 thatCha...
Endlosschleifen und select
func (s *Service) loop() {
	 ticker := time.NewTicker(time.Second)
	 for {
	 	 select {
	 	 cas...
Methoden als externe Schnittstellen

func (s *Service) DoThis(data string) int {
	 respChan := make(chan int)
	 this := &T...
Goroutines können
eigene Wege

gehen …
… oder gemeinsame
Rechenleistung nutzen

Konflikte vermeiden

Herausforderungen nebenläufiger Anwendungen

Rennen kontrollieren

Probleme abfe...
Sehr naive Parallelisierung (1)
func process(in []int) []int {
	 resultChan := make(chan int)
	 for _, value := range in {...
Sehr naive Parallelisierung (2)

func processValue(
	 inValue int, resultChan chan int) {
	 // Time of result calculation ...
Verbesserung

•
• Output mit richtiger Größe initialisieren

Ergebnis gemäß Index setzen
•
Index in der Verarbeitung mitfü...
Verbesserung (1)
func process(in []int) []int {
	 resultChan := make(chan *result)
	 for index, value := range in {
	 	 //...
Verbesserung (2)
type result struct {
	 index int
	 value int
}
!

func processValue(
	 index, inValue int, resultChan cha...
Isolierung von Zugriffen

• Loops serialisieren Zugriffe

• Synchronisation über Channels oder
Package sync


• Referenzen ...
Unabhängigkeit von Goroutines

• Keine Beziehung zwischen Goroutines

Kontrolle nur über Channels

•
• Externe Packages he...
Schleifenfunktion
func (t *MyType) backendLoop(l loop.Loop) error {
	 for {
	 	 select {
	 	 case <-l.ShallStop():
	 	 	 r...
Kontrolle der Schleifenfunktion
// Start of the goroutine in constructor.
t.loop = loop.Go(t.backendLoop)
!

// Tell loop ...
Deadlocks vermeiden (Timeout)

func (t *MyType) Foo(foo *Foo) error {
	 select {
	 case t.fooChan <- foo:
	 case <-time.Af...
Deadlocks vermeiden (Loop)

func (t *MyType) Foo(foo *Foo) error {
	 select {
	 case t.fooChan <- foo:
	 case <-t.loop.IsS...
Vernetzung
Hilfreiche Packages

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

html/template, mime/… für Inhalte

•
• encoding/gob, …/json, …/xml für ...
Externe Packages von Google

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


• Weitere Crypto Packages (u.a...
Serialisierung via JSON
type OrderItem struct {
	 Id	 	 	 	 int		 	 `json:"ArticleNo"`
	 Quantity		 int
}
!

type Order st...
Marshalling
order := Order{
	 Name: 	 "Foo Bar",
	 …
	 Items:	 []OrderItem{{4711, 1}, {4712, 5}, …},
}
!

marshalledOrder,...
Unmarshalling

var order Order
!

err := json.Unmarshal(marshalledOrder, &order)
if err != nil {
	 …
}
!

fmt.Printf("Name...
Netz und Crypto

WebSockets

Fallbeispiel einer API

Reflection für Dispatching

Serialisierung via JSON
❝
Zitat hier eingeben.
Bildquellen –Christian Bauer
123RF

iStockphoto

eigene Quellen
Nächste SlideShare
Wird geladen in …5
×

Skalierbare Anwendungen mit Google Go

618 Aufrufe

Veröffentlicht am

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.

Veröffentlicht in: Technologie, Business
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
618
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
1
Aktionen
Geteilt
0
Downloads
2
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Skalierbare Anwendungen mit Google Go

  1. 1. Skalierbare Anwendungen mit Google Go
  2. 2. Frank Müller Oldenburg Baujahr 1965 Entwickler Fachautor ! frank@mweb.de @themue
  3. 3. Moderne Mehrkernsysteme
 sind wie die
 Vereinigung von Flüssen
  4. 4. Ihre Energie gilt es
 effizient zu nutzen
  5. 5. Hier bietet sich
 Google Go an
  6. 6. imperativ bedingt objektorientiert Google Go als multikulturelle Sprache bedingt funktional nebenläufig
  7. 7. ❝ It’s better to have a permanent income than to be fascinating. –Oscar Wilde
  8. 8. 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
  9. 9. Beispiel: Goroutines als Server Client Client Client Server
  10. 10. Beispiel: Lastverteilung Worker Client Master Client Worker Worker
  11. 11. Netze von Goroutines A C D B E F G E1 E2 E3
  12. 12. Ein Wimmeln wie
 im Bienenstock
  13. 13. Kapselung in Typen package service ! type Service struct { thisChan chan *This thatChan chan *That foo bool bar int baz string }
  14. 14. 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 }
  15. 15. 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() } } }
  16. 16. Methoden als externe Schnittstellen func (s *Service) DoThis(data string) int { respChan := make(chan int) this := &This{data, respChan} ! s.thisChan <- this return <-respChan }
  17. 17. Goroutines können eigene Wege
 gehen …
  18. 18. … oder gemeinsame
  19. 19. Rechenleistung nutzen Konflikte vermeiden Herausforderungen nebenläufiger Anwendungen Rennen kontrollieren Probleme abfedern
  20. 20. 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 }
  21. 21. Sehr naive Parallelisierung (2) func processValue( inValue int, resultChan chan int) { // Time of result calculation depends // on value. outValue := inValue … ! resultChan <- outValue }
  22. 22. Verbesserung • • Output mit richtiger Größe initialisieren Ergebnis gemäß Index setzen • Index in der Verarbeitung mitführen
  23. 23. 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 }
  24. 24. 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} }
  25. 25. Isolierung von Zugriffen • Loops serialisieren Zugriffe • Synchronisation über Channels oder Package sync • Referenzen nur an eine Goroutine senden Aufteilung von Arrays und Slices •
  26. 26. Unabhängigkeit von Goroutines • Keine Beziehung zwischen Goroutines Kontrolle nur über Channels • • Externe Packages helfen git.tideland.biz/goas/loop • • launchpad.net/tomb
  27. 27. 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 …: … } } }
  28. 28. 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()
  29. 29. 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 }
  30. 30. 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 }
  31. 31. Vernetzung
  32. 32. 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
  33. 33. 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
  34. 34. 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 }
  35. 35. 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)
  36. 36. Unmarshalling var order Order ! err := json.Unmarshal(marshalledOrder, &order) if err != nil { … } ! fmt.Printf("Name: %sn", order.Name)
  37. 37. Netz und Crypto WebSockets Fallbeispiel einer API Reflection für Dispatching Serialisierung via JSON
  38. 38. ❝ Zitat hier eingeben. Bildquellen –Christian Bauer 123RF iStockphoto eigene Quellen

×