SlideShare a Scribd company logo
1 of 37
Download to read offline
Verteilte Entwicklung in Go
RESTful APIs und gRPC
Frank Müller
•Oldenburg, Deutschland


•1965 geboren


•Kubermatic


•Team Lead Development


•@themue
Einführung Frank Müller
Modularisierung hat sich verändert
• Laufzeitumgebung sind Clouds und Cluster


• Komponenten sind Microservices


• Aufteilung bringt Flexibilität und Skalierbarkeit


• APIs auf Basis von REST oder gRPC bringen
Sprachunabhängigkeit
Runtime im Netz Frank Müller
RESTful APIs in Go
• HTTP Bibliothek ist genug


• URL bezeichnet Typ und gegebenenfalls Ressource


• HTTP Methode bestimmt Aktion


• Create / Read / Update / Delete ist POST / GET / PUT / DELETE


• Body enthält die Daten


• Content Type ist in der Regel JSON
Einfache Struktur Frank Müller
POST /api/cards/12345/items


Content-Type: application/json


{


"articleNo": "9876",


"spec": {


"size": "XL",


"color": "red"


},


"number": 2


}
Beispiel Frank Müller
• Package net/http enthält Server, Request und Response


• Es definiert den Handler und implementiert ihn als ServeMux


• Nicht hinreichend, aber leicht zu ergänzen


• Ein eigenes Package httpx hilft


‣ Pfade abbilden


‣ Methoden abbilden
Standardbibliothek genügt beinahe Frank Müller
// NestedHandler allows to nest handler following the


// pattern /handlerA/{entityID-A}/handlerB/{entityID-B}.


type NestedHandler struct {


resource string


handler http.Handler


nested map[string]http.Handler


}


func NewNestedHandler(resource string, handler http.Handler) *NestedHandler {


return &NestedHandler{


resource: resource,


handler: handler,


nested: make(map[string]http.Handler),


}


}
Pfade abbilden (1) Frank Müller
// Nest nests another nested handler.


func (h *NestedHandler) Nest(handler *NestedHandler) *NestedHandler {


h.nested[handler.resource] = handler


return handler


}


// NestHandler nests any handler as new nested handler.


func (h *NestedHandler) NestHandler(


resource string, handler http.Handler) *NestedHandler {


nh := NewNestedHandler(resource, handler)


h.nested[resource] = nh


return nh


}
Pfade abbilden (2) Frank Müller
func (h *NestedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {


// Check if own or one of the nested handler is addressed.


eh, ok := h.analyzePath(r.URL.Path)


if ok {


eh.ServeHTTP(w, r)


return


}


// Handler not found.


http.NotFound(w, r)


}


Pfade abbilden (3) Frank Müller
// CreateHandler care for create requests, aka POST.


type CreateHandler interface {


Create(w http.ResponseWriter, r *http.Request)


}


// ReadHandler care for read requests, aka GET.


type ReadHandler interface {


Read(w http.ResponseWriter, r *http.Request)


}


.


.


.
Methoden abbilden (1) Frank Müller
// MethodHandler maps requests to according methods.


type MethodHandler struct {


handler http.Handler


}


// NewMethodHandler wraps a handler for automatic method mapping.


func NewMethodHandler(h http.Handler) *MethodHandler {


return &MethodHandler{


handler: h,


}


}


Methoden abbilden (2) Frank Müller
// ServeHTTP implements http.Handler and cares for the mapping.


func (h *MethodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {


	
switch r.Method {


	
case http.MethodPost:


	
	
if ch, ok := h.handler.(CreateHandler); ok {


	
	
	
ch.Create(w, r)


	
	
	
return


	
	
}


case http.MethodGet:


...


}


// Fallback.


h.handler.ServeHTTP(w, r)


}
Methoden abbilden (3) Frank Müller
Teamwork
• Handler jeweils für Logik von Shopping Cards und Items


• Wrapping durch MethodHandler


• Kombination durch NestedHandler
Beispiel Shopping API (1) Frank Müller
type CardsHandler struct { ... }


// Create to handle POST requests.


func (h *CardsHandler) Create(w http.ResponseWriter, r *http.Request) { ... }


// Read to handle GET requests.


func (h *CardsHandler) Read(w http.ResponseWriter, r *http.Request) { ... }


type ItemsHandler struct { ... }


// Create to handle POST requests.


func (h *ItemsHandler) Create(w http.ResponseWriter, r *http.Request) { ... }


// Read to handle GET requests.


func (h *ItemsHandler) Read(w http.ResponseWriter, r *http.Request) { ... }
Beispiel Shopping API (2) Frank Müller
// Little helper for convenience, wrapping with logging,


// authentication/authorization, and method handling.


wrap := func(h http.Handler) http.Handler {


return httpx.NewLogHandler(httpx.NewAuthHandler(httpx.NewMethodHandler(h)))


}


// Wrap the handlers for business logic.


ch := wrap(NewCardsHandler())


ih := wrap(NewItemsHandler())


// Nest the handlers for business logic of cards and their items.


ncih := httpx.NewNestedHandler("cards", ch).Nest("items", ih)


Beispiel Shopping API (3) Frank Müller
// Use standard multiplexer for all handlers.


mux := http.NewServeMux()


mux.Handle("/cards/", ncih)


// Configure and start server using the multiplexer.


s := &http.Server{


	
Addr: ":8080",


	
Handler: mux,


	
ReadTimeout: 10 * time.Second,


	
WriteTimeout: 10 * time.Second,


	
MaxHeaderBytes: 1 << 20,


}


log.Fatal(s.ListenAndServe())
Beispiel Shopping API (4) Frank Müller
• Analyse des Pfads an einer Position für Resource Identifier


• Analyse des Content Type


• Analyse weiterer Header


• Marshal und Unmarshal direkt in oder aus dem Body
Weitere Helfer für das Package Frank Müller
• Wenig Dependencies, wenig Komplexität, leichte Erweiterbarkeit


• Wrapping ist praktisch für modulare Erweiterung


‣ Authentisierung und Autorisierung


‣ Logging


• Testing der Geschäftslogik ist losgelöst von diesen Aspekten
Vorteile Frank Müller
• Eigenes Package erfordert Vorarbeit und eigene Wartung


• Marshalling und Unmarshalling der Transportobjekte bringt
manuelle Aufwände mit sich
Nachteile Frank Müller
Entfernt aufrufen
•Remote Procedure Calls


•Bei Google entwickelt


•Nutzen in der Regel Protocol
Buffers


•Server bietet Dienste an


•Clients nutzen sie
Eigentlich nichts besonderes Frank Müller
Go Service
JS Client Java Client
gRPC


Server
gRPC


Stub
gRPC


Stub
Proto Request
Proto Request
Proto Response
Proto Responses
• Protocol Buffers beschreiben Datenstrukturen


‣ sprachunabhängig


‣ plattformunabhängig


‣ erweiterbar


• Serialisiert Daten für den Transport


•Stubs werden für Zielsprache und -plattform generiert
Grundlagen Frank Müller
• Definition in Proto-Datei


• Übertragung der Daten als Messages


• Verschiedene Felder stehen zur Verfügung


‣ Verschiedene Integers, String, Bool, Floats, Slice of Bytes


‣ Optionales, OneOf, Enumerations, Wiederholungen


‣ Default Value und Schachtelungen
Transport der Daten Frank Müller
// Message to add one item to an existing card.


message AddItemRequest {


required string card_id = 1;


required string article_no = 2;


optional group spec = 3 {


optional string size = 4;


optional string color = 5;


}


required uint64 number = 6;


}


// Message to reply to the adding of an article.


message AddItemReply { ... }
Nachrichten Frank Müller
// Service for the management of a shopping card.


service Cards {


// Create a new card.


rpc NewCard () returns (NewCardReply) {}


// Add an item.


rpc AddItem (AddItemRequest) returns (AddItemReply) {}


...


}
Services Frank Müller
Vorbereitung Frank Müller
## Installation der Plugins


$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26


$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1


## Pfad erweitern


$ export PATH="$PATH:$(go env GOPATH)/bin"


## gRPC Code generieren


$ protoc -I $SRCDIR --go_out $DSTDIR $SRCDIR/myshop.proto
// AddItem handels the AddItem call.


func (s *cardService) AddItem(


ctx context.Context, in *pb.AddItemRequest) (*pb.AddItemReply, error) {


// Use data of AddItemRequest in to add the item, e.g.


card, err := s.loadCard(in.CardId)


if err != nil {


return nil, err


}


...


// Return the reply.


return &pb.AddItemReply{


...


}, nil


}
Server (1) Frank Müller
// Start listener and GRPC server.


lis, err := net.Listen("tcp", ":10000")


if err != nil {


log.Fatalf("failed to listen: %v", err)


}


grpcServer := grpc.NewServer()


// Register card service.


myshop.RegisterCardServer(grpcServer, &cardService{})


// Start serving.


grpcServer.Serve(lis)
Server (2) Frank Müller
// Connect the server.


conn, err := grpc.Dial("localhost:10000")


if err != nil {


log.Fatalf("failed to connect the server: %v", err)


}


defer conn.Close()


// Start the client.


client := calculator.NewCardClient(conn)


// Perform requests using the created client.


reply, err := client.AddItem(context.Background(), &pb.AddItemRequest{ ... })


...
Client Frank Müller
• Statische Datenformate


• Effiziente Serialisierung


• Streaming möglich


• Connections können beibehalten werden


• Umfangreicher Stack für Security und Credentials


• Problemloser Mix verschiedener Sprachen
Vorteile Frank Müller
• Nicht für alle Sprachen verfügbar


• Proto-Dateien sind eigene Artefakte (bei Mehrsprachigkeit eher
Vorteil)


• Extra Tools notwendig
Nachteile Frank Müller
Zusammenfassung
• RESTful APIs sind etabliert und flexibel


• Sie können in vielen Sprachen leicht implementiert werden


• Unabhängigkeit von Sprachen und Plattformen


• gRPC ist ein leistungsstarker Nachfolger


• Definition in Proto-Dateien erlaubt leichteren Austausch


• Generator nicht für alle Sprachen verfügbar
Zusammenfassung Frank Müller
Bildquellen


123RF


Pexels


iStockphoto


Eigene Fotos

More Related Content

Similar to DevOpsCon - Verteilte Entwicklung in Go

Prometheus Monitoring
Prometheus MonitoringPrometheus Monitoring
Prometheus Monitoringinovex GmbH
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoFrank Müller
 
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaCloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaQAware GmbH
 
OpenSocial und Apache Shindig
OpenSocial und Apache ShindigOpenSocial und Apache Shindig
OpenSocial und Apache ShindigMayflower GmbH
 
REST Problems
REST ProblemsREST Problems
REST Problemspredic8
 
Object-orientied way of using mysqli interface - Workshop
Object-orientied way of using mysqli interface - WorkshopObject-orientied way of using mysqli interface - Workshop
Object-orientied way of using mysqli interface - WorkshopWaldemar Dell
 
FM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas HirtFM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas HirtVerein FM Konferenz
 
Ist GraphQL das bessere REST
Ist GraphQL das bessere RESTIst GraphQL das bessere REST
Ist GraphQL das bessere RESTMartin Abraham
 
2021 OOP - Kubernetes Operatoren
2021   OOP - Kubernetes Operatoren2021   OOP - Kubernetes Operatoren
2021 OOP - Kubernetes OperatorenFrank Müller
 
HTML5 - presentation at W3C-Tag 2009
HTML5 - presentation at W3C-Tag 2009HTML5 - presentation at W3C-Tag 2009
HTML5 - presentation at W3C-Tag 2009Felix Sasaki
 
Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?QAware GmbH
 
Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Josef Adersberger
 
Grundlagen puppet
Grundlagen puppetGrundlagen puppet
Grundlagen puppetinovex GmbH
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in GoFrank Müller
 
Dokumentenorientiere Datenbanken am Beispiel CouchDB
Dokumentenorientiere Datenbanken am Beispiel CouchDBDokumentenorientiere Datenbanken am Beispiel CouchDB
Dokumentenorientiere Datenbanken am Beispiel CouchDBMario Müller
 
Dart (Teil II der Tour de Dart)
Dart (Teil II der Tour de Dart)Dart (Teil II der Tour de Dart)
Dart (Teil II der Tour de Dart)Nane Kratzke
 
Google Maps mit PHP und Ajax nutzen.
Google Maps mit PHP und Ajax nutzen.Google Maps mit PHP und Ajax nutzen.
Google Maps mit PHP und Ajax nutzen.frankstaude
 

Similar to DevOpsCon - Verteilte Entwicklung in Go (20)

Prometheus Monitoring
Prometheus MonitoringPrometheus Monitoring
Prometheus Monitoring
 
Go to the Cloud
Go to the CloudGo to the Cloud
Go to the Cloud
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google Go
 
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaCloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
 
Web Entwicklung mit PHP - Teil 1
Web Entwicklung mit PHP - Teil 1Web Entwicklung mit PHP - Teil 1
Web Entwicklung mit PHP - Teil 1
 
OpenSocial und Apache Shindig
OpenSocial und Apache ShindigOpenSocial und Apache Shindig
OpenSocial und Apache Shindig
 
REST Problems
REST ProblemsREST Problems
REST Problems
 
Object-orientied way of using mysqli interface - Workshop
Object-orientied way of using mysqli interface - WorkshopObject-orientied way of using mysqli interface - Workshop
Object-orientied way of using mysqli interface - Workshop
 
FM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas HirtFM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas Hirt
 
Ist GraphQL das bessere REST
Ist GraphQL das bessere RESTIst GraphQL das bessere REST
Ist GraphQL das bessere REST
 
2021 OOP - Kubernetes Operatoren
2021   OOP - Kubernetes Operatoren2021   OOP - Kubernetes Operatoren
2021 OOP - Kubernetes Operatoren
 
HTML5 - presentation at W3C-Tag 2009
HTML5 - presentation at W3C-Tag 2009HTML5 - presentation at W3C-Tag 2009
HTML5 - presentation at W3C-Tag 2009
 
Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?
 
Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?
 
Grundlagen puppet
Grundlagen puppetGrundlagen puppet
Grundlagen puppet
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
 
Einsteiger Workshop
Einsteiger WorkshopEinsteiger Workshop
Einsteiger Workshop
 
Dokumentenorientiere Datenbanken am Beispiel CouchDB
Dokumentenorientiere Datenbanken am Beispiel CouchDBDokumentenorientiere Datenbanken am Beispiel CouchDB
Dokumentenorientiere Datenbanken am Beispiel CouchDB
 
Dart (Teil II der Tour de Dart)
Dart (Teil II der Tour de Dart)Dart (Teil II der Tour de Dart)
Dart (Teil II der Tour de Dart)
 
Google Maps mit PHP und Ajax nutzen.
Google Maps mit PHP und Ajax nutzen.Google Maps mit PHP und Ajax nutzen.
Google Maps mit PHP und Ajax nutzen.
 

More from Frank Müller

JAX 2023 - Generics in Go
JAX 2023 - Generics in GoJAX 2023 - Generics in Go
JAX 2023 - Generics in GoFrank Müller
 
Let The Computer Do It
Let The Computer Do ItLet The Computer Do It
Let The Computer Do ItFrank Müller
 
Blockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale WährungenBlockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale WährungenFrank Müller
 
Cloud Provisioning mit Juju
Cloud Provisioning mit JujuCloud Provisioning mit Juju
Cloud Provisioning mit JujuFrank Müller
 
Juju - Scalable Software with Google Go
Juju - Scalable Software with Google GoJuju - Scalable Software with Google Go
Juju - Scalable Software with Google GoFrank Müller
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google GoFrank Müller
 
Clouds, leicht beherrschbar
Clouds, leicht beherrschbarClouds, leicht beherrschbar
Clouds, leicht beherrschbarFrank Müller
 
WTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten CloudWTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten CloudFrank Müller
 
Juju - Google Go in a scalable Environment
Juju - Google Go in a scalable EnvironmentJuju - Google Go in a scalable Environment
Juju - Google Go in a scalable EnvironmentFrank Müller
 
OOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source SoftwareOOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source SoftwareFrank Müller
 
Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of GoFrank Müller
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaFrank Müller
 
On Event-Driven Architecture
On Event-Driven ArchitectureOn Event-Driven Architecture
On Event-Driven ArchitectureFrank Müller
 
Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.Frank Müller
 
Agility And The Way To SOA
Agility And The Way To SOAAgility And The Way To SOA
Agility And The Way To SOAFrank Müller
 

More from Frank Müller (17)

JAX 2023 - Generics in Go
JAX 2023 - Generics in GoJAX 2023 - Generics in Go
JAX 2023 - Generics in Go
 
Let The Computer Do It
Let The Computer Do ItLet The Computer Do It
Let The Computer Do It
 
Concurrency with Go
Concurrency with GoConcurrency with Go
Concurrency with Go
 
Fun with functions
Fun with functionsFun with functions
Fun with functions
 
Blockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale WährungenBlockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale Währungen
 
Cloud Provisioning mit Juju
Cloud Provisioning mit JujuCloud Provisioning mit Juju
Cloud Provisioning mit Juju
 
Juju - Scalable Software with Google Go
Juju - Scalable Software with Google GoJuju - Scalable Software with Google Go
Juju - Scalable Software with Google Go
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
 
Clouds, leicht beherrschbar
Clouds, leicht beherrschbarClouds, leicht beherrschbar
Clouds, leicht beherrschbar
 
WTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten CloudWTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
 
Juju - Google Go in a scalable Environment
Juju - Google Go in a scalable EnvironmentJuju - Google Go in a scalable Environment
Juju - Google Go in a scalable Environment
 
OOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source SoftwareOOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source Software
 
Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of Go
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
 
On Event-Driven Architecture
On Event-Driven ArchitectureOn Event-Driven Architecture
On Event-Driven Architecture
 
Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.
 
Agility And The Way To SOA
Agility And The Way To SOAAgility And The Way To SOA
Agility And The Way To SOA
 

DevOpsCon - Verteilte Entwicklung in Go

  • 1. Verteilte Entwicklung in Go RESTful APIs und gRPC Frank Müller
  • 2. •Oldenburg, Deutschland •1965 geboren •Kubermatic •Team Lead Development •@themue Einführung Frank Müller
  • 4. • Laufzeitumgebung sind Clouds und Cluster • Komponenten sind Microservices • Aufteilung bringt Flexibilität und Skalierbarkeit • APIs auf Basis von REST oder gRPC bringen Sprachunabhängigkeit Runtime im Netz Frank Müller
  • 6. • HTTP Bibliothek ist genug • URL bezeichnet Typ und gegebenenfalls Ressource • HTTP Methode bestimmt Aktion • Create / Read / Update / Delete ist POST / GET / PUT / DELETE • Body enthält die Daten • Content Type ist in der Regel JSON Einfache Struktur Frank Müller
  • 7. POST /api/cards/12345/items Content-Type: application/json { "articleNo": "9876", "spec": { "size": "XL", "color": "red" }, "number": 2 } Beispiel Frank Müller
  • 8. • Package net/http enthält Server, Request und Response • Es definiert den Handler und implementiert ihn als ServeMux • Nicht hinreichend, aber leicht zu ergänzen • Ein eigenes Package httpx hilft ‣ Pfade abbilden ‣ Methoden abbilden Standardbibliothek genügt beinahe Frank Müller
  • 9. // NestedHandler allows to nest handler following the // pattern /handlerA/{entityID-A}/handlerB/{entityID-B}. type NestedHandler struct { resource string handler http.Handler nested map[string]http.Handler } func NewNestedHandler(resource string, handler http.Handler) *NestedHandler { return &NestedHandler{ resource: resource, handler: handler, nested: make(map[string]http.Handler), } } Pfade abbilden (1) Frank Müller
  • 10. // Nest nests another nested handler. func (h *NestedHandler) Nest(handler *NestedHandler) *NestedHandler { h.nested[handler.resource] = handler return handler } // NestHandler nests any handler as new nested handler. func (h *NestedHandler) NestHandler( resource string, handler http.Handler) *NestedHandler { nh := NewNestedHandler(resource, handler) h.nested[resource] = nh return nh } Pfade abbilden (2) Frank Müller
  • 11. func (h *NestedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check if own or one of the nested handler is addressed. eh, ok := h.analyzePath(r.URL.Path) if ok { eh.ServeHTTP(w, r) return } // Handler not found. http.NotFound(w, r) } Pfade abbilden (3) Frank Müller
  • 12. // CreateHandler care for create requests, aka POST. type CreateHandler interface { Create(w http.ResponseWriter, r *http.Request) } // ReadHandler care for read requests, aka GET. type ReadHandler interface { Read(w http.ResponseWriter, r *http.Request) } . . . Methoden abbilden (1) Frank Müller
  • 13. // MethodHandler maps requests to according methods. type MethodHandler struct { handler http.Handler } // NewMethodHandler wraps a handler for automatic method mapping. func NewMethodHandler(h http.Handler) *MethodHandler { return &MethodHandler{ handler: h, } } Methoden abbilden (2) Frank Müller
  • 14. // ServeHTTP implements http.Handler and cares for the mapping. func (h *MethodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPost: if ch, ok := h.handler.(CreateHandler); ok { ch.Create(w, r) return } case http.MethodGet: ... } // Fallback. h.handler.ServeHTTP(w, r) } Methoden abbilden (3) Frank Müller
  • 16. • Handler jeweils für Logik von Shopping Cards und Items • Wrapping durch MethodHandler • Kombination durch NestedHandler Beispiel Shopping API (1) Frank Müller
  • 17. type CardsHandler struct { ... } // Create to handle POST requests. func (h *CardsHandler) Create(w http.ResponseWriter, r *http.Request) { ... } // Read to handle GET requests. func (h *CardsHandler) Read(w http.ResponseWriter, r *http.Request) { ... } type ItemsHandler struct { ... } // Create to handle POST requests. func (h *ItemsHandler) Create(w http.ResponseWriter, r *http.Request) { ... } // Read to handle GET requests. func (h *ItemsHandler) Read(w http.ResponseWriter, r *http.Request) { ... } Beispiel Shopping API (2) Frank Müller
  • 18. // Little helper for convenience, wrapping with logging, // authentication/authorization, and method handling. wrap := func(h http.Handler) http.Handler { return httpx.NewLogHandler(httpx.NewAuthHandler(httpx.NewMethodHandler(h))) } // Wrap the handlers for business logic. ch := wrap(NewCardsHandler()) ih := wrap(NewItemsHandler()) // Nest the handlers for business logic of cards and their items. ncih := httpx.NewNestedHandler("cards", ch).Nest("items", ih) Beispiel Shopping API (3) Frank Müller
  • 19. // Use standard multiplexer for all handlers. mux := http.NewServeMux() mux.Handle("/cards/", ncih) // Configure and start server using the multiplexer. s := &http.Server{ Addr: ":8080", Handler: mux, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } log.Fatal(s.ListenAndServe()) Beispiel Shopping API (4) Frank Müller
  • 20. • Analyse des Pfads an einer Position für Resource Identifier • Analyse des Content Type • Analyse weiterer Header • Marshal und Unmarshal direkt in oder aus dem Body Weitere Helfer für das Package Frank Müller
  • 21. • Wenig Dependencies, wenig Komplexität, leichte Erweiterbarkeit • Wrapping ist praktisch für modulare Erweiterung ‣ Authentisierung und Autorisierung ‣ Logging • Testing der Geschäftslogik ist losgelöst von diesen Aspekten Vorteile Frank Müller
  • 22. • Eigenes Package erfordert Vorarbeit und eigene Wartung • Marshalling und Unmarshalling der Transportobjekte bringt manuelle Aufwände mit sich Nachteile Frank Müller
  • 24. •Remote Procedure Calls •Bei Google entwickelt •Nutzen in der Regel Protocol Buffers •Server bietet Dienste an •Clients nutzen sie Eigentlich nichts besonderes Frank Müller Go Service JS Client Java Client gRPC Server gRPC Stub gRPC Stub Proto Request Proto Request Proto Response Proto Responses
  • 25. • Protocol Buffers beschreiben Datenstrukturen ‣ sprachunabhängig ‣ plattformunabhängig ‣ erweiterbar • Serialisiert Daten für den Transport •Stubs werden für Zielsprache und -plattform generiert Grundlagen Frank Müller
  • 26. • Definition in Proto-Datei • Übertragung der Daten als Messages • Verschiedene Felder stehen zur Verfügung ‣ Verschiedene Integers, String, Bool, Floats, Slice of Bytes ‣ Optionales, OneOf, Enumerations, Wiederholungen ‣ Default Value und Schachtelungen Transport der Daten Frank Müller
  • 27. // Message to add one item to an existing card. message AddItemRequest { required string card_id = 1; required string article_no = 2; optional group spec = 3 { optional string size = 4; optional string color = 5; } required uint64 number = 6; } // Message to reply to the adding of an article. message AddItemReply { ... } Nachrichten Frank Müller
  • 28. // Service for the management of a shopping card. service Cards { // Create a new card. rpc NewCard () returns (NewCardReply) {} // Add an item. rpc AddItem (AddItemRequest) returns (AddItemReply) {} ... } Services Frank Müller
  • 29. Vorbereitung Frank Müller ## Installation der Plugins $ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 ## Pfad erweitern $ export PATH="$PATH:$(go env GOPATH)/bin" ## gRPC Code generieren $ protoc -I $SRCDIR --go_out $DSTDIR $SRCDIR/myshop.proto
  • 30. // AddItem handels the AddItem call. func (s *cardService) AddItem( ctx context.Context, in *pb.AddItemRequest) (*pb.AddItemReply, error) { // Use data of AddItemRequest in to add the item, e.g. card, err := s.loadCard(in.CardId) if err != nil { return nil, err } ... // Return the reply. return &pb.AddItemReply{ ... }, nil } Server (1) Frank Müller
  • 31. // Start listener and GRPC server. lis, err := net.Listen("tcp", ":10000") if err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer := grpc.NewServer() // Register card service. myshop.RegisterCardServer(grpcServer, &cardService{}) // Start serving. grpcServer.Serve(lis) Server (2) Frank Müller
  • 32. // Connect the server. conn, err := grpc.Dial("localhost:10000") if err != nil { log.Fatalf("failed to connect the server: %v", err) } defer conn.Close() 
 // Start the client. client := calculator.NewCardClient(conn) // Perform requests using the created client. reply, err := client.AddItem(context.Background(), &pb.AddItemRequest{ ... }) ... Client Frank Müller
  • 33. • Statische Datenformate • Effiziente Serialisierung • Streaming möglich • Connections können beibehalten werden • Umfangreicher Stack für Security und Credentials • Problemloser Mix verschiedener Sprachen Vorteile Frank Müller
  • 34. • Nicht für alle Sprachen verfügbar • Proto-Dateien sind eigene Artefakte (bei Mehrsprachigkeit eher Vorteil) • Extra Tools notwendig Nachteile Frank Müller
  • 36. • RESTful APIs sind etabliert und flexibel • Sie können in vielen Sprachen leicht implementiert werden • Unabhängigkeit von Sprachen und Plattformen • gRPC ist ein leistungsstarker Nachfolger • Definition in Proto-Dateien erlaubt leichteren Austausch • Generator nicht für alle Sprachen verfügbar Zusammenfassung Frank Müller