Go - Googles Sprache

für skalierbare Systeme
Frank Müller
Oldenburg

Baujahr 1965

Entwickler

Fachautor

frank.mueller@canonical.com

@themue
Parallelität oder Nebenläufigkeit?
❝Parallelism
Programming as the simultaneous
execution of (possibly related)
computations.

Concurrency
Programming as the...
Sieh, wie wirdies nutzen ...
Bereitgestellte Infrastruktur ...
... ist nichts ohne bereitgestellte Dienste
mysql
wordpress
Bekanntes
Szenario
auf
individuellen
Servern
Höhere Komplexität in Clouds
wordpress
mediawikihaproxy-w mediawiki memcached
haproxy-b wordpress mysql
wordpressvarnish
Ein mühsamer Weg
Juju - Open Source Tool zur
Automatisierung von Clouds
http://jujucharms.com
Plattformen
Plattformen
mediawiki
wordpress
AWS Azure OpenStack Joyent ...
haproxy-w mediawiki memcached
haproxy-b wordpress mysql
wor...
juju generate-config
juju bootstrap
Bootstrap
Bootstrap
API
State
Provisioner
...
Zentrale
Funktionen
Provisionierung
juju deploy juju-gui
juju deploy wordpress
juju deploy mysql
juju expose juju-gui
Bootstrap
juju-gui wordpress mysql
Relationen
juju add-relation wordpress mysql
juju expose wordpress
Bootstrap
juju-gui wordpress mysql
Konfiguration
juju set mysql dataset-size=50%
juju set wordpress tuning=optimized
Bootstrap
juju-gui wordpress* mysql*
Skalieren
juju deploy memcached
juju add-relation wordpress memcached
juju add-unit wordpress
wordpress*
Bootstrap
juju-gui wordpres...
Varianten
Unit
Unit
Unter-
geordnete
Unit
Unit
Unit
Unit
Container
Direkte
Abhängigkeit
Standard
Einige Charms
ceph
mediawiki mongodb
cassandra
rails
mysql
wordpress
rabbitmq
haproxy
apache2
hadoop
squid
hbase
couchdb
p...
Viel Spaß in den Wolken
Wie hilft uns Google Go hier?
Moderne Mehrkernsysteme sind

wie die Vereinigung von Flüssen
Ihre Energie gilt es

effizient zu nutzen
Google Go als Multi-Paradigmen-Sprache
imperativ
bedingt funktional
bedingt objektorientiert
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

• Kommunikati...
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 := &Th...
Beispiel: Goroutines als Server
Client
Client
Client
Server
Beispiel: Lastverteilung
Client
Client
Worker
Worker
Worker
Master
Netze von Goroutines
A C D
GFEB
E1 E2 E3
Goroutines können
eigene Wege

gehen …
… oder gemeinsame
Ein Wimmeln wie im Bienenstock
Einblicke in die Juju Architektur
State - Watcher - Worker
State
API Networker
Provisioner
Uniter
Deployer
...
!
Collections
Individuelle Objekte
Lebenszykl...
Lauter nebenläufige Arbeit
Agent
State
Worker
Goroutine
Goroutine
Worker
Goroutine
Goroutine
Worker
Goroutine
Goroutine
Beispiel Firewaller
unitd Loop
unitd Loop
machined Loop
State Main Loop
machined Loop
unitd Loop
serviced Loop
Environment...
Herausforderungen nebenläufiger Anwendungen
Rechenleistung nutzen
Rennen kontrollieren
Konflikte vermeiden
Probleme abfedern
Sehr naives Parallelisieren (1)
func process(in []int) []int {
	 resultChan := make(chan int)
	 for _, value := range in {...
Sehr naives Parallelisieren (2)
func processValue(
	 inValue int, resultChan chan int) {
	 // Time of result calculation m...
Problem und Verbesserung
• Unterschiedliche Laufzeiten führen zu
falscher Indizierung im Ergebnis

• Index in der Verarbei...
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 chan *...
Isolierung von Zugriffen
• Loops serialisieren Zugriffe

• Synchronisation über Channels oder
Package sync

• Referenzen nu...
Arbeitsteilung (1)
// Process all data passed by reference.
func process(ds []*Data) {
var wg sync.WaitGroup
for i := 0; i...
Arbeitsteilung (2)
// Processing a chunk of data passed by reference.
func processChunk(ds []*Data, wg sync.WaitGroup) {
/...
Kontrolle von Goroutines
• Keine direkte Beziehung zwischen
Goroutines

• Kontrolle nur über Channels

• Externe Packages ...
Operation in einer Schleife
func (t *T) loop() {
defer t.tomb.Done()
for {
select {
case <-t.tomb.Dying():
// Cleanup ...
...
Steuerung von außen
// Stop ends the main loop.
func (t *T) Stop() error {
// Kill(nil) means no error as reason.
t.tomb.K...
Prüfung des Backends
func (t *T) Foo(foo *Foo) (*Bar, error) {
env := &fooEnv{foo, make(chan *Bar)}
select {
case t.fooCha...
Schnittstellen
Flexible Nutzung
• Nur Deklaration

• Einbettung in umfassendere Interfaces

• Implizites Duck Typing

• Anwendbar auf jed...
Verhalten definieren und kombinieren
type StorageReader interface {
Get(name string) (io.ReadCloser, error)
List(prefix stri...
Teilnutzung möglich
// Only the writing is needed.
func Write(sw StorageWriter) error {
...
return sw.Put(myName, myReader...
Implementierung pro Provider
Environ
Storage Azure
AWS
MAAS
OpenStack
...
Vernetzung
Hilfreiche Packages
• net, …/http für IP und Web

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

• encoding/gob, …/json, …/xml für d...
Externe Packages von Google
• WebSocket, SPDY, Dict und mehr in
golang.org/x/net

• Weitere Crypto Packages (u.a. OpenPGP)...
Serialisierung via JSON
type Parameters map[string]interface{}
type Action struct {
	 Tag string `json:"tag"`
	 Receiver s...
Marshalling
action := Action{
	 Tag: "FooBar",
	 …
	 Paramaters: Parameters{"foo": 4711, "bar": true},
}
marshalledAction,...
Unmarshalling
var action Action
err := json.Unmarshal(marshalledAction, &action)
if err != nil {
	 …
}
fmt.Printf("Tag: %s...
API in Juju
Netz und Crypto
Reflection für Dispatching
WebSockets
Serialisierung via JSON
Bildquellen
123RF

iStockphoto

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

Go - Googles Sprache für skalierbare Systeme

610 Aufrufe

Veröffentlicht am

Talk about Google Go given at the DevOpsCon 2015 in Berlin.

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

Keine Downloads
Aufrufe
Aufrufe insgesamt
610
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
10
Aktionen
Geteilt
0
Downloads
3
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Go - Googles Sprache für skalierbare Systeme

  1. 1. Go - Googles Sprache
 für skalierbare Systeme
  2. 2. Frank Müller Oldenburg Baujahr 1965 Entwickler Fachautor frank.mueller@canonical.com @themue
  3. 3. Parallelität oder Nebenläufigkeit?
  4. 4. ❝Parallelism Programming as the simultaneous execution of (possibly related) computations. Concurrency Programming as the composition of independently executing processes. Rob Pike
  5. 5. Sieh, wie wirdies nutzen ...
  6. 6. Bereitgestellte Infrastruktur ...
  7. 7. ... ist nichts ohne bereitgestellte Dienste
  8. 8. mysql wordpress Bekanntes Szenario auf individuellen Servern
  9. 9. Höhere Komplexität in Clouds wordpress mediawikihaproxy-w mediawiki memcached haproxy-b wordpress mysql wordpressvarnish
  10. 10. Ein mühsamer Weg
  11. 11. Juju - Open Source Tool zur Automatisierung von Clouds http://jujucharms.com
  12. 12. Plattformen
  13. 13. Plattformen mediawiki wordpress AWS Azure OpenStack Joyent ... haproxy-w mediawiki memcached haproxy-b wordpress mysql wordpressvarnish
  14. 14. juju generate-config juju bootstrap Bootstrap
  15. 15. Bootstrap API State Provisioner ... Zentrale Funktionen
  16. 16. Provisionierung
  17. 17. juju deploy juju-gui juju deploy wordpress juju deploy mysql juju expose juju-gui Bootstrap juju-gui wordpress mysql
  18. 18. Relationen
  19. 19. juju add-relation wordpress mysql juju expose wordpress Bootstrap juju-gui wordpress mysql
  20. 20. Konfiguration
  21. 21. juju set mysql dataset-size=50% juju set wordpress tuning=optimized Bootstrap juju-gui wordpress* mysql*
  22. 22. Skalieren
  23. 23. juju deploy memcached juju add-relation wordpress memcached juju add-unit wordpress wordpress* Bootstrap juju-gui wordpress* mysql* memcached
  24. 24. Varianten
  25. 25. Unit Unit Unter- geordnete Unit Unit Unit Unit Container Direkte Abhängigkeit Standard
  26. 26. Einige Charms ceph mediawiki mongodb cassandra rails mysql wordpress rabbitmq haproxy apache2 hadoop squid hbase couchdb postgresql nfs ntp
  27. 27. Viel Spaß in den Wolken
  28. 28. Wie hilft uns Google Go hier?
  29. 29. Moderne Mehrkernsysteme sind
 wie die Vereinigung von Flüssen
  30. 30. Ihre Energie gilt es
 effizient zu nutzen
  31. 31. Google Go als Multi-Paradigmen-Sprache imperativ bedingt funktional bedingt objektorientiert nebenläufig
  32. 32. ❝It’s better to have a
 permanent income
 than to be
 fascinating. Oscar Wilde
  33. 33. 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
  34. 34. Kapselung in Typen package service type Service struct { thisChan chan *This thatChan chan *That foo bool bar int baz string }
  35. 35. 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 }
  36. 36. 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() } } }
  37. 37. Methoden als externe Schnittstellen func (s *Service) DoThis(data string) int { respChan := make(chan int) this := &This{data, respChan} s.thisChan <- this return <-respChan }
  38. 38. Beispiel: Goroutines als Server Client Client Client Server
  39. 39. Beispiel: Lastverteilung Client Client Worker Worker Worker Master
  40. 40. Netze von Goroutines A C D GFEB E1 E2 E3
  41. 41. Goroutines können eigene Wege
 gehen …
  42. 42. … oder gemeinsame
  43. 43. Ein Wimmeln wie im Bienenstock
  44. 44. Einblicke in die Juju Architektur
  45. 45. State - Watcher - Worker State API Networker Provisioner Uniter Deployer ... ! Collections Individuelle Objekte Lebenszyklen Client
  46. 46. Lauter nebenläufige Arbeit Agent State Worker Goroutine Goroutine Worker Goroutine Goroutine Worker Goroutine Goroutine
  47. 47. Beispiel Firewaller unitd Loop unitd Loop machined Loop State Main Loop machined Loop unitd Loop serviced Loop Environment Configuration Machines Machine Units Exposes Ports
  48. 48. Herausforderungen nebenläufiger Anwendungen Rechenleistung nutzen Rennen kontrollieren Konflikte vermeiden Probleme abfedern
  49. 49. Sehr naives Parallelisieren (1) func process(in []int) []int { resultChan := make(chan int) for _, value := range in { // One goroutine per value. go processValue(value, resultChan) } // Collecting the results. out := make([]int, len(in)) for i := 0; i < len(in); i++ { out[i] = <-resultChan } return out }
  50. 50. Sehr naives Parallelisieren (2) func processValue( inValue int, resultChan chan int) { // Time of result calculation may vary. outValue := inValue … resultChan <- outValue }
  51. 51. Problem und Verbesserung • Unterschiedliche Laufzeiten führen zu falscher Indizierung im Ergebnis • Index in der Verarbeitung mitführen • Ergebnis gemäß Index setzen
  52. 52. 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 }
  53. 53. Verbesserung (2) type result struct { index int value int } func processValue( index, inValue int, resultChan chan *result) { // Time of result calculation may vary. outValue := inValue … // Send index with result. resultChan <- &result{index, outValue} }
  54. 54. Isolierung von Zugriffen • Loops serialisieren Zugriffe • Synchronisation über Channels oder Package sync • Referenzen nur an eine Goroutine senden • Aufteilung von Arrays und Slices
  55. 55. Arbeitsteilung (1) // Process all data passed by reference. func process(ds []*Data) { var wg sync.WaitGroup for i := 0; i < len(ds); i += chunkSize { // Process one chunk in the background. go processChunk(ds[i:i+chunkSize], wg) } // Wait for all processing to complete. wg.Wait() }
  56. 56. Arbeitsteilung (2) // Processing a chunk of data passed by reference. func processChunk(ds []*Data, wg sync.WaitGroup) { // Increment WaitGroup counter and signal when done. wg.Add(1) defer wg.Done() // Process each data. for _, d := range ds { if d != nil { // Direct manipulation. d.Foo = ... ... } } }
  57. 57. Kontrolle von Goroutines • Keine direkte Beziehung zwischen Goroutines • Kontrolle nur über Channels • Externe Packages helfen • gopkg.in/tomb.v2 • github.com/tideland/goas/v2/loop
  58. 58. Operation in einer Schleife func (t *T) loop() { defer t.tomb.Done() for { select { case <-t.tomb.Dying(): // Cleanup ... return case f := <-t.fooChan: if err := t.foo(f); err != nil { t.tomb.Kill(err) } case b := <-t.barChan: // ... } } }
  59. 59. Steuerung von außen // Stop ends the main loop. func (t *T) Stop() error { // Kill(nil) means no error as reason. t.tomb.Kill(nil) return t.tomb.Wait() } // Err retrieves the error in case the backend loop died. func (t *T) Err() error { return t.tomb.Err() }
  60. 60. Prüfung des Backends func (t *T) Foo(foo *Foo) (*Bar, error) { env := &fooEnv{foo, make(chan *Bar)} select { case t.fooChan <- env: case <-t.tomb.Dead(): return nil, errors.New("backend dead") } select { case bar := <- env.barChan: return bar, nil case <-t.tomb.Dead(): return nil, errors.New("backend dead") } }
  61. 61. Schnittstellen
  62. 62. Flexible Nutzung • Nur Deklaration • Einbettung in umfassendere Interfaces • Implizites Duck Typing • Anwendbar auf jede Typdefination
  63. 63. Verhalten definieren und kombinieren type StorageReader interface { Get(name string) (io.ReadCloser, error) List(prefix string) ([]string, error) URL(name string) (string, error) } type StorageWriter interface { Put(name string, r io.Reader, length int64) error Remove(name string) error } type Storage interface { StorageReader StorageWriter }
  64. 64. Teilnutzung möglich // Only the writing is needed. func Write(sw StorageWriter) error { ... return sw.Put(myName, myReader, myLen) } // Full storage access here. func RemoveFirst(s Storage, prefix string) error { l, err := s.List(prefix) if err != nil { return err } return s.Remove(l[0]) }
  65. 65. Implementierung pro Provider Environ Storage Azure AWS MAAS OpenStack ...
  66. 66. Vernetzung
  67. 67. 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
  68. 68. Externe Packages von Google • WebSocket, SPDY, Dict und mehr in golang.org/x/net • Weitere Crypto Packages (u.a. OpenPGP) in golang.org/x/crypto
  69. 69. Serialisierung via JSON type Parameters map[string]interface{} type Action struct { Tag string `json:"tag"` Receiver string `json:"receiver"` Name string `json:"name"` Parameters Parameters `json:"parameters,omitempty"` }
  70. 70. Marshalling action := Action{ Tag: "FooBar", … Paramaters: Parameters{"foo": 4711, "bar": true}, } marshalledAction, err := json.Marshal(action) if err != nil { … } n, err := anyWriter.Write(marshalledAction)
  71. 71. Unmarshalling var action Action err := json.Unmarshal(marshalledAction, &action) if err != nil { … } fmt.Printf("Tag: %sn", action.Tag)
  72. 72. API in Juju Netz und Crypto Reflection für Dispatching WebSockets Serialisierung via JSON
  73. 73. Bildquellen 123RF iStockphoto eigene Quellen

×