SlideShare ist ein Scribd-Unternehmen logo
1 von 68
Downloaden Sie, um offline zu lesen
Microservices in GO
Massimiliano Dessì @desmax74
ROME 24-25 MARCH 2017
2
Speaker
Massimiliano Dessì has more than 17
years of experience in programming, and
several years in cloud computing.
Manager of GDG Sardegna,
co-founder of Jug Sardegna,
Founder of SpringFramework IT UG,
Author of Spring 2.5 AOP.
He’s a proud father of three,
one girl and two boys.
He currently works for Red Hat.
3
Monolith vs Microservice
The architect’s dilemma
4
It depends...
“.. don't even consider microservices unless you have
a system that's too complex to manage as a monolith.”
“...is a microservice architecture a good choice for the
system you're working on ?”
https://martinfowler.com/bliki/MicroservicePremium.html
5 https://martinfowler.com/bliki/MicroservicePremium.html
6
After these important premises,
we will see the bad part of monolith
and
how microservices
can solve this problems
and how much cost the solution
NO free launch
7
Monolith in sci-f
Arthur C.Clarke 2001 : A space Odissey
8
A successful application growth
during the years
with new features
and
at some point in time,
it is simply too large for any developer to
fully understand.
Big ball of mud/Lasagna code
Software Monolith
9
Million LOC
Hundreds/thousands jar/libs
Codebase difficult to understand.
Each change makes the codebase
incrementally more complex, and more
difficult to understand
10
Large teams
on large monolitic codebase
lead to feature branches
and often
to a painful merges
11
12
Run the compilation
and
the entire suite test
tooks a significant
amount of time,
long time to diagnose and fix
the cause of a test failures
13
A monolithic app
force to use
a
single
technology stack,
used since
the start of the
project
WW2
14
http://martinfowler.com/articles/microservices.html
Microservices
15
Microservices
Service-oriented architecture
composed of
loosely coupled elements
that
have bounded contexts.
Adrian Cockcroft
Netflix
16
Functional Decomposition
https://www.nginx.com/blog/introduction-to-microservices/
17
Bound Context and Data Partition
https://www.nginx.com/blog/introduction-to-microservices/
18
Benefts of Microservices
A microservice architecture
provides benefts like:
Enabling growth at different rate
Deploy multiple instances when
needed
Scalability
19
Benefts of Microservices
Different
technology
stack for
different
services
Caren Hartley http://www.hartleycycles.com/
20
Benefts of Microservices
The teams are able to manage
every single microservice
Fast testing
Monitoring
Code ownership
21
Benefts of Microservices
Monitoring/health check
Rewriting with a different stack it’s easy
Circuit breaker (internal/external)
Bulkhead (internal/external)
22
Costs of Microservices
Coordination/Orchestration
Inter process communication
Discovery
Fallacies of distributed computing
Complexity of the entire system
23
Costs of Microservices
https://www.nginx.com/blog/building-microservices-inter-process-communication/
24
Costs of Microservices
Latency
API Gateway
Load Balancers
25
Load Balancer
https://www.nginx.com/blog/introduction-to-microservices/
External
Load balancer
26
API Gateway
https://www.nginx.com/blog/building-microservices-using-an-api-gateway/
27
Api Gateway
https://tyk.io/http://www.apiman.io https://getkong.org/
28
Costs of Microservices
Test with other services
Operational complexity
High level of automation
29
Errors with Microservices
Silver bullet/Golden Hammer
(human fault)
Wrong decomposition of
a monolith/Distributed monolith
Coupled services
30
Microservices and 12 factor app
Our microservices writed as a cloud
(private/public/hybrid)
native services
must obey the rules of
12 factor app
https://12factor.net/
31
Golang tools
● Rest - fasthttp
● gRPC
● RabbitMQ
● Context
● Env Config- Viper
● Load Test - Hey
● Load test - Vegeta
● Distributed Tracing - Zipkin
● Service discovery - Consul
● Service discovery – Kubernetes
● Load balancer – Kubernetes
● Health check - Kubernetes
32
REST HTTP
import (
log "github.com/Sirupsen/logrus"
"github.com/buaazp/fasthttprouter"
mid "org.desmax/gulch/middlewares"
…
)
func init(){
…..
}
func main() {
db := sys.StartDB(Conf)
defer db.Close()
/*Routes*/
router := fasthttprouter.New()
router.GET("/", mid.ConfigMidw(handlers.LoginHandler, Conf))
router.POST("/login", mid.DBMidw(mid.ConfigMidw(handlers.LoginHandler, Conf), db))
router.POST("/auth", mid.DBMidw(mid.ConfigMidw(handlers.AuthHandler, Conf), db))
router.GET("/healthz", mid.ConfigMidw(handlers.HealthHandler, Conf)
router.GET("/items", mid.ConfigMidw(handlers.ItemHandler, Conf)
...
/*Server*/
config.HttpServer(router, Conf) //HTTP
//config.HttpsServer(router, conf) //HTTPS
}
33
REST HTTP
func ItemsHandler(ctx *fasthttp.RequestCtx, params fasthttprouter.Params) { {
….
json, err := json.Marshal(MyStruct)
if err != nil {
//manage error
return
}
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetBody(json) //[]byte
}
34
gRPC (Google RPC)
1)
Download Protocol Buffer in your project
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get google.golang.org/grpc
Remote Procedure call using protocol buffer
Protocol Buffers, also referred as protobuf, is Google’s language-neutral, platform-
neutral, extensible mechanism for serializing structured data. Protocol Buffers are
smaller, faster, and simpler that provides high performance than other standards such
as XML and JSON.
35
gRPC (Google RPC)
syntax = "proto3";
package user;
service User {
rpc GetUsers(UserFilter) returns (stream UserRequest) {}
rpc CreateUser (UserRequest) returns (UserResponse) {}
}
message UserRequest {
int32 id = 1;
string name = 2;
string email = 3;
message Address {
string street = 1;
string city = 2;
string state = 3;
string zip = 4;
}
repeated Address addresses = 5;
}
message UserResponse {
int32 id = 1;
bool success = 2;
}
message UserFilter {
string keyword = 1;
}
2)
Define your proto3 file
called vault.proto
with service,
request and
response
36
gRPC (Google RPC)
3) Generate code
protoc -I <my_package>/user/user.proto –go_out=plugins=grpc:user
Output user.pb.go
4)Create gRPC Server
import (
...
"google.golang.org/grpc"
pb "github.com/desmax74/<prj_name>/grpc/user"
)
const (
port = ":50051"
)
type server struct {
savedUsers []*pb.UserRequest
}
37
gRPC (Google RPC)
func (s *server) CreateUser(ctx context.Context, in *pb.UserRequest)
(*pb.UserResponse, error) {
s.savedUsers = append(s.savedUsers, in)
return &pb.UserResponse{Id: in.Id, Success: true}, nil
}
func (s *server) GetUsers(filter *pb.UserFilter, stream pb.User_GetUserServer) error
{
for _, user := range users {
//search the user with the filter
….
//write the user in the stream
if err := stream.Send(user); err != nil {
return err
}
}
return nil
}
38
gRPC (Google RPC)
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("Error on listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterUserServer(s, &server{})
s.Serve(lis)
}
39
gRPC (Google RPC)
func createUser(client pb.UserClient, user *pb.UserRequest) {
resp, err := client.CreateUser(context.Background(), user)
if err != nil {
log.Printf("Error on create User: %v", err)
}
if resp.Success {
log.Printf("New User has created with id: %d", resp.Id)
} ...
40
gRPC (Google RPC)
func getUsers(client pb.UserClient, filter *pb.UserFilter) {
stream, err := client.GetUsers(context.Background(), filter)
if err != nil {
...
for {
users, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("%v.GetUsers(_) = _, %v", client, err)
}
log.Printf("User: %v", user)
}
}
41
gRPC (Google RPC)
Client code
func main() {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewUserClient(conn)
user := &pb.UserRequest{
Id: 17,
Name: "Speaker One",
Email: "spealer1@codemotion.it",
Phone: "+39-345-1234567",
….
createUser(client, user)
42
RabbitMQ
const (
MQHost = "127.0.0.1"
MQPort = ":5672"
)
type MyData struct {
Username string `json:"username"`
Message string `json:"message"`
}
func MQConnect() (*amqp.Connection, *amqp.Channel, error) {
url := "amqp://" + MQHost + MQPort
conn, err := amqp.Dial(url)
if err != nil {
return nil, nil, err
}
channel, err := conn.Channel()
if err != nil {
return nil, nil, err
}
if _, err := channel.QueueDeclare("myqueue", false, true, false,
false,nil)
https://github.com/streadway/amqp
43
RabbitMQ
err != nil {
return nil, nil, err
}
return conn, channel, nil
}
// Publish
err = channel.Publish(
"", // exchange
q.Name, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(body),
}
)
// Consume
msgs, err := ch.Consume(
q.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
https://github.com/streadway/amqp
44
Golang Context
import "context"
func WithValue(parent Context, key interface{}, val interface{}) Context
Like Java Thread Local
45
Golang Context
Func myBusinessHandler(){
var timeInMilliseconds time.Duration = 0
ctx := context.WithValue(context.Background(), "time",
&timeInMilliseconds)
myBusinessFuncWithTracking(ctx)
val := ctx.Value("time").(*time.Duration)
}
func myBusinessFuncWithTracking(ctx context.Context) {
defer func(s time.Time) {
val := ctx.Value("time").(*time.Duration)
*val = *val + time.Since(s)
}(time.Now())
//do other
}
46
Confguration from environment
Docker run command:
docker run -it desmax74/gdg -e PORT='8080' -e APPNAME='gdg'
-p 8080:8080 -e LOGSERVER='127.0.0.1:1902'
//plain without external libs
serverPort := os.Getenv(PORT)
if(serverPort == "") {serverPort = "8080"}
appName := os.Getenv(APPNAME)
logServer := os.Getenv(LOGSERVER)
47
Confguration from environment
AutomaticEnv()
BindEnv(string...) : error
SetEnvPrefix(string)
SetEnvReplacer(string...) *strings.Replacer
//Binding Env to Specific Keys
viper.BindEnv("port") // bind to ENV "PORT"
viper.BindEnv("name", USERNAME) // bind to ENV "USERNAME"
os.Setenv("PORT", "8080") // outside of the app
os.Setenv("USERNAME", "speaker") // outside app
port := viper.GetInt("port")) // 13
name := viper.GetString("name")) // "spf13"
//Automatic Env Binding
viper.SetEnvPrefix("foo") // Becomes "FOO_"
os.Setenv("FOO_PORT", "1313") // outside of the app
viper.AutomaticEnv()
port := viper.GetInt("port"))
https://github.com/spf13/viper
48
Load Test Setup
1)Run our docker image/K8s POD
2)Inspect image
3)Read the ip
49
Load Test Hey
Hey previously know as boom
$ hey -n 100 -c 10 -m GET http://172.17.0.2:8080/
All requests done.
Summary:
Total: 0.0068 secs
Slowest: 0.0026 secs
Fastest: 0.0002 secs
Average: 0.0005 secs
Requests/sec: 14772.2227
Total data:7500 bytes
Size/request: 75 bytes
Status code distribution:
[200] 100 responses
Response time histogram:
0.000 [1] |∎
0.000 [65] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
0.001 [16] |∎∎∎∎∎∎∎∎∎∎
0.001 [4] |∎∎
0.001 [2] |∎
0.001 [3] |∎∎
0.002 [5] |∎∎∎
0.002 [1] |∎
0.002 [0] |
0.002 [1] |∎
0.003 [2] |∎
Latency distribution:
10% in 0.0002 secs
25% in 0.0003 secs
50% in 0.0003 secs
75% in 0.0005 secs
90% in 0.0013 secs
95% in 0.0016 secs
99% in 0.0026 secs
https://github.com/rakyll/hey
50
Load Test Vegeta
echo "GET http://172.17.0.2:8080/" | ./vegeta attack -duration=10s | tee results.bin |
./vegeta report
Requests [total, rate] 500, 50.10
Duration [total, attack, wait] 9.98043696s, 9.979999794s, 437.166µs
Latencies [mean, 50, 95, 99, max] 481.501µs, 479.956µs, 564.821µs, 596.038µs, 1.211673ms
Bytes In [total, mean] 37500, 75.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
Error Set:
https://github.com/tsenart/vegeta
51
Load Test Vegeta
cat results.bin | ./vegeta report -reporter=plot > plot.html
52
Golang Distributed tracing
With microservices we need to correlate the calls
between services to track the flow.
We can use OpenZipkin, we add a Correlation ID
and propagate it between processes, then the
correlated logs can be used by ELK or Splunk
Correlation ID -> unifed view of business event
53
Distributed tracing Lingo
A Span is an individual operation
A Span contains timestamped events and tags.
A Trace is an end-to-end latency graph, composed
of spans.
54
Distributed tracing
Server Received: 09:20:14:100 Server Sent: 09:20:15:425
v v
+-------------------------------------+
| POST /data | 1325ms
+-------------------------------------+
| peer.ipv4 | 1.2.3.4 |
| http.request-id | xyz1-rf3 |
| http.content.length | 1 MB |
| http.url |...&upload |
Server Received is an event
POST /data is a span name
325ms is a span duration
http.request-id=xyz1-rf3 is a span tag
55
Zipkin Docker image
https://github.com/openzipkin/docker-zipkin
56
Golang Distributed tracing
if span := opentracing.SpanFromContext(req.Context());
span != nil {
// We are going to use this span in a clientrequest
ext.SpanKindRPCClient.Set(span)
// Add some standard OpenTracing tags
ext.HTTPMethod.Set(span, req.Method)
span.SetTag(zipkincore.HTTP_HOST, req.URL.Host)
span.SetTag(zipkincore.HTTP_PATH, req.URL.Path)
ext.HTTPUrl.Set(
span,
fmt.Sprintf("%s://%s%s",
req.URL.Scheme,
req.URL.Host,
req.URL.Path),
)
https://github.com/opentracing/opentracing-go
https://github.com/openzipkin/zipkin-go-opentracing/
57
Golang Distributed tracing
continue
// Add information on the peer service we're about to contact.
if host, portString, err := net.SplitHostPort(req.URL.Host);
err == nil {
ext.PeerHostname.Set(span, host)
if port, err := strconv.Atoi(portString);
err != nil {
ext.PeerPort.Set(span, uint16(port))
}
} else {
ext.PeerHostname.Set(span, req.URL.Host)
}
https://github.com/opentracing/opentracing-go
https://github.com/openzipkin/zipkin-go-opentracing/
58
Golang Distributed tracing
Continue
// Inject the Span context into the outgoing HTTP Request.
if err := tracer.Inject(
span.Context(),
opentracing.TextMap,
opentracing.HTTPHeadersCarrier(req.Header),
);
err != nil {
fmt.Printf("error encountered while trying to inject
span: %+v", err)
}
}
return req
}
https://github.com/opentracing/opentracing-go
https://github.com/openzipkin/zipkin-go-opentracing/
59
Service discovery with Consul
import consul "github.com/hashicorp/consul/api")
type Client interface {
Service(string, string) ([]string, error)
Register(string, int) error
DeRegister(string) error
}
type client struct {
consul *consul.Client
}
func (c *client) Register(name string, port int) error {
reg := &consul.AgentServiceRegistration{
ID: name,
Name: name,
Port: port,
}
return c.consul.Agent().ServiceRegister(reg)
} https://www.consul.io/
60
Service discovery with Consul
func (c *client) DeRegister(id string) error {
return c.consul.Agent().ServiceDeregister(id)
}
func (c *client) Service(service, tag string) ([]*ServiceEntry,
*QueryMeta, error) {
passingOnly := true
addrs, meta, err := c.consul.Health().Service(service, tag,
passingOnly, nil)
if len(addrs) == 0 && err == nil {
return nil, fmt.Errorf("service ( %s ) was not found",
service)
}
if err != nil {
return nil, err
}
return addrs, meta, nil
}
https://github.com/hashicorp/consul
61
Service discovery inside Kubernetes
//with Environment variables
backendHost := os.Getenv("BE_SRV_SERVICE_HOST")
backendPort := os.Getenv("BE_SRV_SERVICE_PORT")
backendRsp, backendErr := http.Get(fmt.Sprintf(
"http://%v:%v/",
backendHost,
BackendPort)
)
if backendErr == nil {
defer backendRsp.Body.Close()
}
62
Service discovery inside Kubernetes
//with DNS server
cname, rec, err := net.LookupSRV("be", "tcp",
"be-srv.default.svc.cluster.local")
if err != nil {
http.Error(resp, err.Error(),
http.StatusInternalServerError)
}
fmt.Fprintf(resp, "SRV CNAME: %vn", cname)
for i := range rec {
fmt.Fprintf(resp, "SRV Records: %v n", rec[i])
DNSbackendHost = rec[i].Target
DNSbackendPort = strconv.Itoa(int(rec[i].Port))
}
63
Kubernetes Load Balancer
https://www.nginx.com/blog/microservices-openshift-fabric-model-nginx-mra/
kubectl expose rc desmax --type=LoadBalancer --name desmax-http
$ kubectl get svc
NAME CLUSTER_IP EXTERNAL_IP PORT(S) AGE
Kubernetes 10.3.240.1 <none> 443/TCP 35m
Kubia-http 10.3.245.160 XXX.XXX.XXX.XXX 8080/TCP 1m
64
Health check
https://www.nginx.com/blog/microservices-openshift-fabric-model-nginx-mra/
65
Kubernetes Health check
livenessProbe:
# an http probe
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
timeoutSeconds: 1
router.GET("/healthz",
mid.ConfigMidw(handlers.HealthHandler, Conf)
)
In our microservice code
In kubernetes deployment
66
Resources
http://kubernetes.io/
https://www.openshift.org/
https://martinfowler.com/articles/microservices.html
https://martinfowler.com/bliki/MicroservicePremium.html
https://www.nginx.com/blog/introduction-to-microservices/
http://www.grpc.io/
https://github.com/grpc/grpc-go
https://www.manning.com/books/kubernetes-in-action
https://github.com/micro/go-micro
67
Q & A
68
Thanks and
have fun !
ROME 24-25 MARCH 2017
@desmax74
http://slideshare.net/desmax74
All pictures belong
to their respective authors

Weitere ähnliche Inhalte

Was ist angesagt?

Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014brendandburns
 
Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)Megan O'Keefe
 
When Docker Engine 1.12 features unleashes software architecture
When Docker Engine 1.12 features unleashes software architectureWhen Docker Engine 1.12 features unleashes software architecture
When Docker Engine 1.12 features unleashes software architecture Adrien Blind
 
containerd summit - Deep Dive into containerd
containerd summit - Deep Dive into containerdcontainerd summit - Deep Dive into containerd
containerd summit - Deep Dive into containerdDocker, Inc.
 
Continuous deployment of polyglot microservices: A practical approach
Continuous deployment of polyglot microservices: A practical approachContinuous deployment of polyglot microservices: A practical approach
Continuous deployment of polyglot microservices: A practical approachJuan Larriba
 
Platform Orchestration with Kubernetes and Docker
Platform Orchestration with Kubernetes and DockerPlatform Orchestration with Kubernetes and Docker
Platform Orchestration with Kubernetes and DockerJulian Strobl
 
containerd the universal container runtime
containerd the universal container runtimecontainerd the universal container runtime
containerd the universal container runtimeDocker, Inc.
 
Deep Dive into Kubernetes - Part 2
Deep Dive into Kubernetes - Part 2Deep Dive into Kubernetes - Part 2
Deep Dive into Kubernetes - Part 2Imesh Gunaratne
 
Kubernetes - Starting with 1.2
Kubernetes  - Starting with 1.2Kubernetes  - Starting with 1.2
Kubernetes - Starting with 1.2William Stewart
 
Introducing LinuxKit
Introducing LinuxKitIntroducing LinuxKit
Introducing LinuxKitDocker, Inc.
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in DockerDocker, Inc.
 
Kubernetes architecture
Kubernetes architectureKubernetes architecture
Kubernetes architectureJanakiram MSV
 
Learn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLearn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLarry Cai
 
Containerd - core container runtime component
Containerd - core container runtime component Containerd - core container runtime component
Containerd - core container runtime component Docker, Inc.
 
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration PlatformKubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration PlatformMichael O'Sullivan
 
Kubernetes - how to orchestrate containers
Kubernetes - how to orchestrate containersKubernetes - how to orchestrate containers
Kubernetes - how to orchestrate containersinovex GmbH
 
Docker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Docker Meetup - Melbourne 2015 - Kubernetes Deep DiveDocker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Docker Meetup - Melbourne 2015 - Kubernetes Deep DiveKen Thompson
 
WSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2Con ASIA 2016: WSO2 Cloud Strategy UpdateWSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2Con ASIA 2016: WSO2 Cloud Strategy UpdateWSO2
 
In-Cluster Continuous Testing Framework for Docker Containers
In-Cluster Continuous Testing Framework for Docker ContainersIn-Cluster Continuous Testing Framework for Docker Containers
In-Cluster Continuous Testing Framework for Docker ContainersNeil Gehani
 

Was ist angesagt? (20)

Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
 
Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)
 
When Docker Engine 1.12 features unleashes software architecture
When Docker Engine 1.12 features unleashes software architectureWhen Docker Engine 1.12 features unleashes software architecture
When Docker Engine 1.12 features unleashes software architecture
 
containerd summit - Deep Dive into containerd
containerd summit - Deep Dive into containerdcontainerd summit - Deep Dive into containerd
containerd summit - Deep Dive into containerd
 
Continuous deployment of polyglot microservices: A practical approach
Continuous deployment of polyglot microservices: A practical approachContinuous deployment of polyglot microservices: A practical approach
Continuous deployment of polyglot microservices: A practical approach
 
Platform Orchestration with Kubernetes and Docker
Platform Orchestration with Kubernetes and DockerPlatform Orchestration with Kubernetes and Docker
Platform Orchestration with Kubernetes and Docker
 
containerd the universal container runtime
containerd the universal container runtimecontainerd the universal container runtime
containerd the universal container runtime
 
Deep Dive into Kubernetes - Part 2
Deep Dive into Kubernetes - Part 2Deep Dive into Kubernetes - Part 2
Deep Dive into Kubernetes - Part 2
 
Kubernetes - Starting with 1.2
Kubernetes  - Starting with 1.2Kubernetes  - Starting with 1.2
Kubernetes - Starting with 1.2
 
Introducing LinuxKit
Introducing LinuxKitIntroducing LinuxKit
Introducing LinuxKit
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in Docker
 
Kubernetes architecture
Kubernetes architectureKubernetes architecture
Kubernetes architecture
 
Learn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLearn kubernetes in 90 minutes
Learn kubernetes in 90 minutes
 
Containerd - core container runtime component
Containerd - core container runtime component Containerd - core container runtime component
Containerd - core container runtime component
 
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration PlatformKubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
 
Kubernetes - how to orchestrate containers
Kubernetes - how to orchestrate containersKubernetes - how to orchestrate containers
Kubernetes - how to orchestrate containers
 
Docker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Docker Meetup - Melbourne 2015 - Kubernetes Deep DiveDocker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Docker Meetup - Melbourne 2015 - Kubernetes Deep Dive
 
WSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2Con ASIA 2016: WSO2 Cloud Strategy UpdateWSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2Con ASIA 2016: WSO2 Cloud Strategy Update
 
Introduction to kubernetes
Introduction to kubernetesIntroduction to kubernetes
Introduction to kubernetes
 
In-Cluster Continuous Testing Framework for Docker Containers
In-Cluster Continuous Testing Framework for Docker ContainersIn-Cluster Continuous Testing Framework for Docker Containers
In-Cluster Continuous Testing Framework for Docker Containers
 

Andere mochten auch

Codemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_sprayCodemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_sprayMassimiliano Dessì
 
Why we cannot ignore functional programming
Why we cannot ignore functional programmingWhy we cannot ignore functional programming
Why we cannot ignore functional programmingMassimiliano Dessì
 
Scala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVCScala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVCMassimiliano Dessì
 
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...Codemotion
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMMassimiliano Dessì
 
認識那條鯨魚 Docker 初探
認識那條鯨魚   Docker 初探認識那條鯨魚   Docker 初探
認識那條鯨魚 Docker 初探仲昀 王
 
Aeroprobing A.I. Drone with TX1
Aeroprobing A.I. Drone with TX1Aeroprobing A.I. Drone with TX1
Aeroprobing A.I. Drone with TX1NVIDIA Taiwan
 
White paper IBM: Ripensare il Made in Italy nell’Era del digitale
White paper IBM: Ripensare il Made in Italy nell’Era del digitaleWhite paper IBM: Ripensare il Made in Italy nell’Era del digitale
White paper IBM: Ripensare il Made in Italy nell’Era del digitaleFaq400 - la Community IBM i italiana
 
以深度學習加速語音及影像辨識應用發展
以深度學習加速語音及影像辨識應用發展以深度學習加速語音及影像辨識應用發展
以深度學習加速語音及影像辨識應用發展NVIDIA Taiwan
 
Pronunciamiento apo 25 03 2017
Pronunciamiento apo 25 03 2017Pronunciamiento apo 25 03 2017
Pronunciamiento apo 25 03 2017megaradioexpress
 
Impact Hub_Abidjan - Columbia Ci3
Impact Hub_Abidjan - Columbia Ci3Impact Hub_Abidjan - Columbia Ci3
Impact Hub_Abidjan - Columbia Ci3Kathy Liu, MPA CIPP
 
Next Money Fintech Finals Hong Kong: January 19, 2017
Next Money Fintech Finals Hong Kong: January 19, 2017Next Money Fintech Finals Hong Kong: January 19, 2017
Next Money Fintech Finals Hong Kong: January 19, 2017Jim Marous
 

Andere mochten auch (15)

Codemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_sprayCodemotion 2013 scalatra_play_spray
Codemotion 2013 scalatra_play_spray
 
Why we cannot ignore functional programming
Why we cannot ignore functional programmingWhy we cannot ignore functional programming
Why we cannot ignore functional programming
 
Scala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVCScala Italy 2013 extended Scalatra vs Spring MVC
Scala Italy 2013 extended Scalatra vs Spring MVC
 
Docker linuxday 2015
Docker linuxday 2015Docker linuxday 2015
Docker linuxday 2015
 
NoEstimates @ miniIAD
NoEstimates @ miniIADNoEstimates @ miniIAD
NoEstimates @ miniIAD
 
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVM
 
認識那條鯨魚 Docker 初探
認識那條鯨魚   Docker 初探認識那條鯨魚   Docker 初探
認識那條鯨魚 Docker 初探
 
Aeroprobing A.I. Drone with TX1
Aeroprobing A.I. Drone with TX1Aeroprobing A.I. Drone with TX1
Aeroprobing A.I. Drone with TX1
 
White paper IBM: Ripensare il Made in Italy nell’Era del digitale
White paper IBM: Ripensare il Made in Italy nell’Era del digitaleWhite paper IBM: Ripensare il Made in Italy nell’Era del digitale
White paper IBM: Ripensare il Made in Italy nell’Era del digitale
 
以深度學習加速語音及影像辨識應用發展
以深度學習加速語音及影像辨識應用發展以深度學習加速語音及影像辨識應用發展
以深度學習加速語音及影像辨識應用發展
 
PIKASEN Clasificadora con lector óptico
PIKASEN Clasificadora con lector ópticoPIKASEN Clasificadora con lector óptico
PIKASEN Clasificadora con lector óptico
 
Pronunciamiento apo 25 03 2017
Pronunciamiento apo 25 03 2017Pronunciamiento apo 25 03 2017
Pronunciamiento apo 25 03 2017
 
Impact Hub_Abidjan - Columbia Ci3
Impact Hub_Abidjan - Columbia Ci3Impact Hub_Abidjan - Columbia Ci3
Impact Hub_Abidjan - Columbia Ci3
 
Next Money Fintech Finals Hong Kong: January 19, 2017
Next Money Fintech Finals Hong Kong: January 19, 2017Next Money Fintech Finals Hong Kong: January 19, 2017
Next Money Fintech Finals Hong Kong: January 19, 2017
 

Ähnlich wie Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome

Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017Codemotion
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020Emily Jiang
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020Emily Jiang
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusEmily Jiang
 
How to write clean & testable code without losing your mind
How to write clean & testable code without losing your mindHow to write clean & testable code without losing your mind
How to write clean & testable code without losing your mindAndreas Czakaj
 
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGEPRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGEEditor IJCTER
 
Metarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiMetarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiTimur Shemsedinov
 
Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Luca Lusso
 
Synapse india reviews sharing chapter 23 – asp.net-part2
Synapse india reviews sharing  chapter 23 – asp.net-part2Synapse india reviews sharing  chapter 23 – asp.net-part2
Synapse india reviews sharing chapter 23 – asp.net-part2Synapseindiappsdevelopment
 
Scaling frontend applications with micro-frontends Presentation.pdf
Scaling frontend applications with micro-frontends Presentation.pdfScaling frontend applications with micro-frontends Presentation.pdf
Scaling frontend applications with micro-frontends Presentation.pdfKatamaRajuBandigari1
 
Docker meetup - PaaS interoperability
Docker meetup - PaaS interoperabilityDocker meetup - PaaS interoperability
Docker meetup - PaaS interoperabilityLudovic Piot
 
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...Nikolaos Georgantas
 
MongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB.local Atlanta: Introduction to Serverless MongoDBMongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB.local Atlanta: Introduction to Serverless MongoDBMongoDB
 
Building Event-Driven (Micro) Services with Apache Kafka
Building Event-Driven (Micro) Services with Apache KafkaBuilding Event-Driven (Micro) Services with Apache Kafka
Building Event-Driven (Micro) Services with Apache KafkaGuido Schmutz
 
eProsima RPC over DDS - Connext Conf London October 2015
eProsima RPC over DDS - Connext Conf London October 2015 eProsima RPC over DDS - Connext Conf London October 2015
eProsima RPC over DDS - Connext Conf London October 2015 Jaime Martin Losa
 

Ähnlich wie Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome (20)

Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
 
AngularJS in large applications - AE NV
AngularJS in large applications - AE NVAngularJS in large applications - AE NV
AngularJS in large applications - AE NV
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
 
Cloud nativemicroservices jax-london2020
Cloud nativemicroservices   jax-london2020Cloud nativemicroservices   jax-london2020
Cloud nativemicroservices jax-london2020
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexusMicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
 
How to write clean & testable code without losing your mind
How to write clean & testable code without losing your mindHow to write clean & testable code without losing your mind
How to write clean & testable code without losing your mind
 
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGEPRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
 
Metarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiMetarhia: Node.js Macht Frei
Metarhia: Node.js Macht Frei
 
Synapse india dotnet development web approch
Synapse india dotnet development web approchSynapse india dotnet development web approch
Synapse india dotnet development web approch
 
Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!
 
Synapse india reviews sharing chapter 23 – asp.net-part2
Synapse india reviews sharing  chapter 23 – asp.net-part2Synapse india reviews sharing  chapter 23 – asp.net-part2
Synapse india reviews sharing chapter 23 – asp.net-part2
 
Scaling frontend applications with micro-frontends Presentation.pdf
Scaling frontend applications with micro-frontends Presentation.pdfScaling frontend applications with micro-frontends Presentation.pdf
Scaling frontend applications with micro-frontends Presentation.pdf
 
Docker meetup - PaaS interoperability
Docker meetup - PaaS interoperabilityDocker meetup - PaaS interoperability
Docker meetup - PaaS interoperability
 
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
 
GCF
GCFGCF
GCF
 
ql.io at NodePDX
ql.io at NodePDXql.io at NodePDX
ql.io at NodePDX
 
OneTeam Media Server
OneTeam Media ServerOneTeam Media Server
OneTeam Media Server
 
MongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB.local Atlanta: Introduction to Serverless MongoDBMongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB.local Atlanta: Introduction to Serverless MongoDB
 
Building Event-Driven (Micro) Services with Apache Kafka
Building Event-Driven (Micro) Services with Apache KafkaBuilding Event-Driven (Micro) Services with Apache Kafka
Building Event-Driven (Micro) Services with Apache Kafka
 
eProsima RPC over DDS - Connext Conf London October 2015
eProsima RPC over DDS - Connext Conf London October 2015 eProsima RPC over DDS - Connext Conf London October 2015
eProsima RPC over DDS - Connext Conf London October 2015
 

Mehr von Massimiliano Dessì

When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...Massimiliano Dessì
 
Web Marketing Training 2014 Community Online
Web Marketing Training 2014 Community OnlineWeb Marketing Training 2014 Community Online
Web Marketing Training 2014 Community OnlineMassimiliano Dessì
 
Three languages in thirty minutes
Three languages in thirty minutesThree languages in thirty minutes
Three languages in thirty minutesMassimiliano Dessì
 
Jaxitalia09 Spring Best Practices
Jaxitalia09 Spring Best PracticesJaxitalia09 Spring Best Practices
Jaxitalia09 Spring Best PracticesMassimiliano Dessì
 
MongoDB Scala Roma SpringFramework Meeting2009
MongoDB Scala Roma SpringFramework Meeting2009MongoDB Scala Roma SpringFramework Meeting2009
MongoDB Scala Roma SpringFramework Meeting2009Massimiliano Dessì
 
Scala Programming Linux Day 2009
Scala Programming Linux Day 2009Scala Programming Linux Day 2009
Scala Programming Linux Day 2009Massimiliano Dessì
 
MongoDB SpringFramework Meeting september 2009
MongoDB SpringFramework Meeting september 2009MongoDB SpringFramework Meeting september 2009
MongoDB SpringFramework Meeting september 2009Massimiliano Dessì
 
The hidden gems of Spring Security
The hidden gems of Spring SecurityThe hidden gems of Spring Security
The hidden gems of Spring SecurityMassimiliano Dessì
 
Aspect Oriented Programming and MVC with Spring Framework
Aspect Oriented Programming and MVC with Spring FrameworkAspect Oriented Programming and MVC with Spring Framework
Aspect Oriented Programming and MVC with Spring FrameworkMassimiliano Dessì
 
Real Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday JobReal Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday JobMassimiliano Dessì
 

Mehr von Massimiliano Dessì (20)

Code One 2018 maven
Code One 2018   mavenCode One 2018   maven
Code One 2018 maven
 
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
When Old Meets New: Turning Maven into a High Scalable, Resource Efficient, C...
 
Hacking Maven Linux day 2017
Hacking Maven Linux day 2017Hacking Maven Linux day 2017
Hacking Maven Linux day 2017
 
Web Marketing Training 2014 Community Online
Web Marketing Training 2014 Community OnlineWeb Marketing Training 2014 Community Online
Web Marketing Training 2014 Community Online
 
Scala linux day 2012
Scala linux day 2012 Scala linux day 2012
Scala linux day 2012
 
Three languages in thirty minutes
Three languages in thirty minutesThree languages in thirty minutes
Three languages in thirty minutes
 
MongoDB dessi-codemotion
MongoDB dessi-codemotionMongoDB dessi-codemotion
MongoDB dessi-codemotion
 
MongoDB Webtech conference 2010
MongoDB Webtech conference 2010MongoDB Webtech conference 2010
MongoDB Webtech conference 2010
 
RESTEasy
RESTEasyRESTEasy
RESTEasy
 
Spring Roo Internals Javaday IV
Spring Roo Internals Javaday IVSpring Roo Internals Javaday IV
Spring Roo Internals Javaday IV
 
Spring Roo JaxItalia09
Spring Roo JaxItalia09Spring Roo JaxItalia09
Spring Roo JaxItalia09
 
Jaxitalia09 Spring Best Practices
Jaxitalia09 Spring Best PracticesJaxitalia09 Spring Best Practices
Jaxitalia09 Spring Best Practices
 
Spring3.0 JaxItalia09
Spring3.0 JaxItalia09Spring3.0 JaxItalia09
Spring3.0 JaxItalia09
 
MongoDB Scala Roma SpringFramework Meeting2009
MongoDB Scala Roma SpringFramework Meeting2009MongoDB Scala Roma SpringFramework Meeting2009
MongoDB Scala Roma SpringFramework Meeting2009
 
Scala Programming Linux Day 2009
Scala Programming Linux Day 2009Scala Programming Linux Day 2009
Scala Programming Linux Day 2009
 
MongoDB SpringFramework Meeting september 2009
MongoDB SpringFramework Meeting september 2009MongoDB SpringFramework Meeting september 2009
MongoDB SpringFramework Meeting september 2009
 
The hidden gems of Spring Security
The hidden gems of Spring SecurityThe hidden gems of Spring Security
The hidden gems of Spring Security
 
Spring @Aspect e @Controller
Spring @Aspect e @Controller Spring @Aspect e @Controller
Spring @Aspect e @Controller
 
Aspect Oriented Programming and MVC with Spring Framework
Aspect Oriented Programming and MVC with Spring FrameworkAspect Oriented Programming and MVC with Spring Framework
Aspect Oriented Programming and MVC with Spring Framework
 
Real Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday JobReal Spring Aop Recipes For Your Everyday Job
Real Spring Aop Recipes For Your Everyday Job
 

Kürzlich hochgeladen

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 

Kürzlich hochgeladen (20)

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 

Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome

  • 1. Microservices in GO Massimiliano Dessì @desmax74 ROME 24-25 MARCH 2017
  • 2. 2 Speaker Massimiliano Dessì has more than 17 years of experience in programming, and several years in cloud computing. Manager of GDG Sardegna, co-founder of Jug Sardegna, Founder of SpringFramework IT UG, Author of Spring 2.5 AOP. He’s a proud father of three, one girl and two boys. He currently works for Red Hat.
  • 3. 3 Monolith vs Microservice The architect’s dilemma
  • 4. 4 It depends... “.. don't even consider microservices unless you have a system that's too complex to manage as a monolith.” “...is a microservice architecture a good choice for the system you're working on ?” https://martinfowler.com/bliki/MicroservicePremium.html
  • 6. 6 After these important premises, we will see the bad part of monolith and how microservices can solve this problems and how much cost the solution NO free launch
  • 7. 7 Monolith in sci-f Arthur C.Clarke 2001 : A space Odissey
  • 8. 8 A successful application growth during the years with new features and at some point in time, it is simply too large for any developer to fully understand. Big ball of mud/Lasagna code Software Monolith
  • 9. 9 Million LOC Hundreds/thousands jar/libs Codebase difficult to understand. Each change makes the codebase incrementally more complex, and more difficult to understand
  • 10. 10 Large teams on large monolitic codebase lead to feature branches and often to a painful merges
  • 11. 11
  • 12. 12 Run the compilation and the entire suite test tooks a significant amount of time, long time to diagnose and fix the cause of a test failures
  • 13. 13 A monolithic app force to use a single technology stack, used since the start of the project WW2
  • 15. 15 Microservices Service-oriented architecture composed of loosely coupled elements that have bounded contexts. Adrian Cockcroft Netflix
  • 17. 17 Bound Context and Data Partition https://www.nginx.com/blog/introduction-to-microservices/
  • 18. 18 Benefts of Microservices A microservice architecture provides benefts like: Enabling growth at different rate Deploy multiple instances when needed Scalability
  • 19. 19 Benefts of Microservices Different technology stack for different services Caren Hartley http://www.hartleycycles.com/
  • 20. 20 Benefts of Microservices The teams are able to manage every single microservice Fast testing Monitoring Code ownership
  • 21. 21 Benefts of Microservices Monitoring/health check Rewriting with a different stack it’s easy Circuit breaker (internal/external) Bulkhead (internal/external)
  • 22. 22 Costs of Microservices Coordination/Orchestration Inter process communication Discovery Fallacies of distributed computing Complexity of the entire system
  • 24. 24 Costs of Microservices Latency API Gateway Load Balancers
  • 28. 28 Costs of Microservices Test with other services Operational complexity High level of automation
  • 29. 29 Errors with Microservices Silver bullet/Golden Hammer (human fault) Wrong decomposition of a monolith/Distributed monolith Coupled services
  • 30. 30 Microservices and 12 factor app Our microservices writed as a cloud (private/public/hybrid) native services must obey the rules of 12 factor app https://12factor.net/
  • 31. 31 Golang tools ● Rest - fasthttp ● gRPC ● RabbitMQ ● Context ● Env Config- Viper ● Load Test - Hey ● Load test - Vegeta ● Distributed Tracing - Zipkin ● Service discovery - Consul ● Service discovery – Kubernetes ● Load balancer – Kubernetes ● Health check - Kubernetes
  • 32. 32 REST HTTP import ( log "github.com/Sirupsen/logrus" "github.com/buaazp/fasthttprouter" mid "org.desmax/gulch/middlewares" … ) func init(){ ….. } func main() { db := sys.StartDB(Conf) defer db.Close() /*Routes*/ router := fasthttprouter.New() router.GET("/", mid.ConfigMidw(handlers.LoginHandler, Conf)) router.POST("/login", mid.DBMidw(mid.ConfigMidw(handlers.LoginHandler, Conf), db)) router.POST("/auth", mid.DBMidw(mid.ConfigMidw(handlers.AuthHandler, Conf), db)) router.GET("/healthz", mid.ConfigMidw(handlers.HealthHandler, Conf) router.GET("/items", mid.ConfigMidw(handlers.ItemHandler, Conf) ... /*Server*/ config.HttpServer(router, Conf) //HTTP //config.HttpsServer(router, conf) //HTTPS }
  • 33. 33 REST HTTP func ItemsHandler(ctx *fasthttp.RequestCtx, params fasthttprouter.Params) { { …. json, err := json.Marshal(MyStruct) if err != nil { //manage error return } ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetBody(json) //[]byte }
  • 34. 34 gRPC (Google RPC) 1) Download Protocol Buffer in your project go get -u github.com/golang/protobuf/{proto,protoc-gen-go} go get google.golang.org/grpc Remote Procedure call using protocol buffer Protocol Buffers, also referred as protobuf, is Google’s language-neutral, platform- neutral, extensible mechanism for serializing structured data. Protocol Buffers are smaller, faster, and simpler that provides high performance than other standards such as XML and JSON.
  • 35. 35 gRPC (Google RPC) syntax = "proto3"; package user; service User { rpc GetUsers(UserFilter) returns (stream UserRequest) {} rpc CreateUser (UserRequest) returns (UserResponse) {} } message UserRequest { int32 id = 1; string name = 2; string email = 3; message Address { string street = 1; string city = 2; string state = 3; string zip = 4; } repeated Address addresses = 5; } message UserResponse { int32 id = 1; bool success = 2; } message UserFilter { string keyword = 1; } 2) Define your proto3 file called vault.proto with service, request and response
  • 36. 36 gRPC (Google RPC) 3) Generate code protoc -I <my_package>/user/user.proto –go_out=plugins=grpc:user Output user.pb.go 4)Create gRPC Server import ( ... "google.golang.org/grpc" pb "github.com/desmax74/<prj_name>/grpc/user" ) const ( port = ":50051" ) type server struct { savedUsers []*pb.UserRequest }
  • 37. 37 gRPC (Google RPC) func (s *server) CreateUser(ctx context.Context, in *pb.UserRequest) (*pb.UserResponse, error) { s.savedUsers = append(s.savedUsers, in) return &pb.UserResponse{Id: in.Id, Success: true}, nil } func (s *server) GetUsers(filter *pb.UserFilter, stream pb.User_GetUserServer) error { for _, user := range users { //search the user with the filter …. //write the user in the stream if err := stream.Send(user); err != nil { return err } } return nil }
  • 38. 38 gRPC (Google RPC) func main() { lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("Error on listen: %v", err) } s := grpc.NewServer() pb.RegisterUserServer(s, &server{}) s.Serve(lis) }
  • 39. 39 gRPC (Google RPC) func createUser(client pb.UserClient, user *pb.UserRequest) { resp, err := client.CreateUser(context.Background(), user) if err != nil { log.Printf("Error on create User: %v", err) } if resp.Success { log.Printf("New User has created with id: %d", resp.Id) } ...
  • 40. 40 gRPC (Google RPC) func getUsers(client pb.UserClient, filter *pb.UserFilter) { stream, err := client.GetUsers(context.Background(), filter) if err != nil { ... for { users, err := stream.Recv() if err == io.EOF { break } if err != nil { log.Fatalf("%v.GetUsers(_) = _, %v", client, err) } log.Printf("User: %v", user) } }
  • 41. 41 gRPC (Google RPC) Client code func main() { conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() client := pb.NewUserClient(conn) user := &pb.UserRequest{ Id: 17, Name: "Speaker One", Email: "spealer1@codemotion.it", Phone: "+39-345-1234567", …. createUser(client, user)
  • 42. 42 RabbitMQ const ( MQHost = "127.0.0.1" MQPort = ":5672" ) type MyData struct { Username string `json:"username"` Message string `json:"message"` } func MQConnect() (*amqp.Connection, *amqp.Channel, error) { url := "amqp://" + MQHost + MQPort conn, err := amqp.Dial(url) if err != nil { return nil, nil, err } channel, err := conn.Channel() if err != nil { return nil, nil, err } if _, err := channel.QueueDeclare("myqueue", false, true, false, false,nil) https://github.com/streadway/amqp
  • 43. 43 RabbitMQ err != nil { return nil, nil, err } return conn, channel, nil } // Publish err = channel.Publish( "", // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing{ ContentType: "text/plain", Body: []byte(body), } ) // Consume msgs, err := ch.Consume( q.Name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) https://github.com/streadway/amqp
  • 44. 44 Golang Context import "context" func WithValue(parent Context, key interface{}, val interface{}) Context Like Java Thread Local
  • 45. 45 Golang Context Func myBusinessHandler(){ var timeInMilliseconds time.Duration = 0 ctx := context.WithValue(context.Background(), "time", &timeInMilliseconds) myBusinessFuncWithTracking(ctx) val := ctx.Value("time").(*time.Duration) } func myBusinessFuncWithTracking(ctx context.Context) { defer func(s time.Time) { val := ctx.Value("time").(*time.Duration) *val = *val + time.Since(s) }(time.Now()) //do other }
  • 46. 46 Confguration from environment Docker run command: docker run -it desmax74/gdg -e PORT='8080' -e APPNAME='gdg' -p 8080:8080 -e LOGSERVER='127.0.0.1:1902' //plain without external libs serverPort := os.Getenv(PORT) if(serverPort == "") {serverPort = "8080"} appName := os.Getenv(APPNAME) logServer := os.Getenv(LOGSERVER)
  • 47. 47 Confguration from environment AutomaticEnv() BindEnv(string...) : error SetEnvPrefix(string) SetEnvReplacer(string...) *strings.Replacer //Binding Env to Specific Keys viper.BindEnv("port") // bind to ENV "PORT" viper.BindEnv("name", USERNAME) // bind to ENV "USERNAME" os.Setenv("PORT", "8080") // outside of the app os.Setenv("USERNAME", "speaker") // outside app port := viper.GetInt("port")) // 13 name := viper.GetString("name")) // "spf13" //Automatic Env Binding viper.SetEnvPrefix("foo") // Becomes "FOO_" os.Setenv("FOO_PORT", "1313") // outside of the app viper.AutomaticEnv() port := viper.GetInt("port")) https://github.com/spf13/viper
  • 48. 48 Load Test Setup 1)Run our docker image/K8s POD 2)Inspect image 3)Read the ip
  • 49. 49 Load Test Hey Hey previously know as boom $ hey -n 100 -c 10 -m GET http://172.17.0.2:8080/ All requests done. Summary: Total: 0.0068 secs Slowest: 0.0026 secs Fastest: 0.0002 secs Average: 0.0005 secs Requests/sec: 14772.2227 Total data:7500 bytes Size/request: 75 bytes Status code distribution: [200] 100 responses Response time histogram: 0.000 [1] |∎ 0.000 [65] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 0.001 [16] |∎∎∎∎∎∎∎∎∎∎ 0.001 [4] |∎∎ 0.001 [2] |∎ 0.001 [3] |∎∎ 0.002 [5] |∎∎∎ 0.002 [1] |∎ 0.002 [0] | 0.002 [1] |∎ 0.003 [2] |∎ Latency distribution: 10% in 0.0002 secs 25% in 0.0003 secs 50% in 0.0003 secs 75% in 0.0005 secs 90% in 0.0013 secs 95% in 0.0016 secs 99% in 0.0026 secs https://github.com/rakyll/hey
  • 50. 50 Load Test Vegeta echo "GET http://172.17.0.2:8080/" | ./vegeta attack -duration=10s | tee results.bin | ./vegeta report Requests [total, rate] 500, 50.10 Duration [total, attack, wait] 9.98043696s, 9.979999794s, 437.166µs Latencies [mean, 50, 95, 99, max] 481.501µs, 479.956µs, 564.821µs, 596.038µs, 1.211673ms Bytes In [total, mean] 37500, 75.00 Bytes Out [total, mean] 0, 0.00 Success [ratio] 100.00% Status Codes [code:count] 200:500 Error Set: https://github.com/tsenart/vegeta
  • 51. 51 Load Test Vegeta cat results.bin | ./vegeta report -reporter=plot > plot.html
  • 52. 52 Golang Distributed tracing With microservices we need to correlate the calls between services to track the flow. We can use OpenZipkin, we add a Correlation ID and propagate it between processes, then the correlated logs can be used by ELK or Splunk Correlation ID -> unifed view of business event
  • 53. 53 Distributed tracing Lingo A Span is an individual operation A Span contains timestamped events and tags. A Trace is an end-to-end latency graph, composed of spans.
  • 54. 54 Distributed tracing Server Received: 09:20:14:100 Server Sent: 09:20:15:425 v v +-------------------------------------+ | POST /data | 1325ms +-------------------------------------+ | peer.ipv4 | 1.2.3.4 | | http.request-id | xyz1-rf3 | | http.content.length | 1 MB | | http.url |...&upload | Server Received is an event POST /data is a span name 325ms is a span duration http.request-id=xyz1-rf3 is a span tag
  • 56. 56 Golang Distributed tracing if span := opentracing.SpanFromContext(req.Context()); span != nil { // We are going to use this span in a clientrequest ext.SpanKindRPCClient.Set(span) // Add some standard OpenTracing tags ext.HTTPMethod.Set(span, req.Method) span.SetTag(zipkincore.HTTP_HOST, req.URL.Host) span.SetTag(zipkincore.HTTP_PATH, req.URL.Path) ext.HTTPUrl.Set( span, fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.URL.Host, req.URL.Path), ) https://github.com/opentracing/opentracing-go https://github.com/openzipkin/zipkin-go-opentracing/
  • 57. 57 Golang Distributed tracing continue // Add information on the peer service we're about to contact. if host, portString, err := net.SplitHostPort(req.URL.Host); err == nil { ext.PeerHostname.Set(span, host) if port, err := strconv.Atoi(portString); err != nil { ext.PeerPort.Set(span, uint16(port)) } } else { ext.PeerHostname.Set(span, req.URL.Host) } https://github.com/opentracing/opentracing-go https://github.com/openzipkin/zipkin-go-opentracing/
  • 58. 58 Golang Distributed tracing Continue // Inject the Span context into the outgoing HTTP Request. if err := tracer.Inject( span.Context(), opentracing.TextMap, opentracing.HTTPHeadersCarrier(req.Header), ); err != nil { fmt.Printf("error encountered while trying to inject span: %+v", err) } } return req } https://github.com/opentracing/opentracing-go https://github.com/openzipkin/zipkin-go-opentracing/
  • 59. 59 Service discovery with Consul import consul "github.com/hashicorp/consul/api") type Client interface { Service(string, string) ([]string, error) Register(string, int) error DeRegister(string) error } type client struct { consul *consul.Client } func (c *client) Register(name string, port int) error { reg := &consul.AgentServiceRegistration{ ID: name, Name: name, Port: port, } return c.consul.Agent().ServiceRegister(reg) } https://www.consul.io/
  • 60. 60 Service discovery with Consul func (c *client) DeRegister(id string) error { return c.consul.Agent().ServiceDeregister(id) } func (c *client) Service(service, tag string) ([]*ServiceEntry, *QueryMeta, error) { passingOnly := true addrs, meta, err := c.consul.Health().Service(service, tag, passingOnly, nil) if len(addrs) == 0 && err == nil { return nil, fmt.Errorf("service ( %s ) was not found", service) } if err != nil { return nil, err } return addrs, meta, nil } https://github.com/hashicorp/consul
  • 61. 61 Service discovery inside Kubernetes //with Environment variables backendHost := os.Getenv("BE_SRV_SERVICE_HOST") backendPort := os.Getenv("BE_SRV_SERVICE_PORT") backendRsp, backendErr := http.Get(fmt.Sprintf( "http://%v:%v/", backendHost, BackendPort) ) if backendErr == nil { defer backendRsp.Body.Close() }
  • 62. 62 Service discovery inside Kubernetes //with DNS server cname, rec, err := net.LookupSRV("be", "tcp", "be-srv.default.svc.cluster.local") if err != nil { http.Error(resp, err.Error(), http.StatusInternalServerError) } fmt.Fprintf(resp, "SRV CNAME: %vn", cname) for i := range rec { fmt.Fprintf(resp, "SRV Records: %v n", rec[i]) DNSbackendHost = rec[i].Target DNSbackendPort = strconv.Itoa(int(rec[i].Port)) }
  • 63. 63 Kubernetes Load Balancer https://www.nginx.com/blog/microservices-openshift-fabric-model-nginx-mra/ kubectl expose rc desmax --type=LoadBalancer --name desmax-http $ kubectl get svc NAME CLUSTER_IP EXTERNAL_IP PORT(S) AGE Kubernetes 10.3.240.1 <none> 443/TCP 35m Kubia-http 10.3.245.160 XXX.XXX.XXX.XXX 8080/TCP 1m
  • 65. 65 Kubernetes Health check livenessProbe: # an http probe httpGet: path: /healthz port: 8080 initialDelaySeconds: 15 timeoutSeconds: 1 router.GET("/healthz", mid.ConfigMidw(handlers.HealthHandler, Conf) ) In our microservice code In kubernetes deployment
  • 68. 68 Thanks and have fun ! ROME 24-25 MARCH 2017 @desmax74 http://slideshare.net/desmax74 All pictures belong to their respective authors