SlideShare a Scribd company logo
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

More Related Content

What's hot (20)

PDF
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
brendandburns
 
PDF
Kubernetes: A Short Introduction (2019)
Megan O'Keefe
 
PPTX
When Docker Engine 1.12 features unleashes software architecture
Adrien Blind
 
PDF
containerd summit - Deep Dive into containerd
Docker, Inc.
 
PPTX
Continuous deployment of polyglot microservices: A practical approach
Juan Larriba
 
PDF
Platform Orchestration with Kubernetes and Docker
Julian Strobl
 
PPTX
containerd the universal container runtime
Docker, Inc.
 
PDF
Deep Dive into Kubernetes - Part 2
Imesh Gunaratne
 
PDF
Kubernetes - Starting with 1.2
William Stewart
 
PPTX
Introducing LinuxKit
Docker, Inc.
 
PDF
Kubernetes in Docker
Docker, Inc.
 
PDF
Kubernetes architecture
Janakiram MSV
 
PPTX
Learn kubernetes in 90 minutes
Larry Cai
 
PPTX
Containerd - core container runtime component
Docker, Inc.
 
PDF
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Michael O'Sullivan
 
PDF
Kubernetes - how to orchestrate containers
inovex GmbH
 
PDF
Docker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Ken Thompson
 
PDF
WSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2
 
PDF
Introduction to kubernetes
Raffaele Di Fazio
 
PDF
In-Cluster Continuous Testing Framework for Docker Containers
Neil Gehani
 
Containers, Clusters and Kubernetes - Brendan Burns - Defrag 2014
brendandburns
 
Kubernetes: A Short Introduction (2019)
Megan O'Keefe
 
When Docker Engine 1.12 features unleashes software architecture
Adrien Blind
 
containerd summit - Deep Dive into containerd
Docker, Inc.
 
Continuous deployment of polyglot microservices: A practical approach
Juan Larriba
 
Platform Orchestration with Kubernetes and Docker
Julian Strobl
 
containerd the universal container runtime
Docker, Inc.
 
Deep Dive into Kubernetes - Part 2
Imesh Gunaratne
 
Kubernetes - Starting with 1.2
William Stewart
 
Introducing LinuxKit
Docker, Inc.
 
Kubernetes in Docker
Docker, Inc.
 
Kubernetes architecture
Janakiram MSV
 
Learn kubernetes in 90 minutes
Larry Cai
 
Containerd - core container runtime component
Docker, Inc.
 
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Michael O'Sullivan
 
Kubernetes - how to orchestrate containers
inovex GmbH
 
Docker Meetup - Melbourne 2015 - Kubernetes Deep Dive
Ken Thompson
 
WSO2Con ASIA 2016: WSO2 Cloud Strategy Update
WSO2
 
Introduction to kubernetes
Raffaele Di Fazio
 
In-Cluster Continuous Testing Framework for Docker Containers
Neil Gehani
 

Viewers also liked (15)

PDF
Codemotion 2013 scalatra_play_spray
Massimiliano Dessì
 
ODP
Why we cannot ignore functional programming
Massimiliano Dessì
 
PDF
Scala Italy 2013 extended Scalatra vs Spring MVC
Massimiliano Dessì
 
PDF
Docker linuxday 2015
Massimiliano Dessì
 
PDF
NoEstimates @ miniIAD
Massimo Iacolare
 
PDF
How to Leverage Machine Learning (R, Hadoop, Spark, H2O) for Real Time Proces...
Codemotion
 
PDF
Vert.X like Node.js but polyglot and reactive on JVM
Massimiliano Dessì
 
PDF
認識那條鯨魚 Docker 初探
仲昀 王
 
PDF
Aeroprobing A.I. Drone with TX1
NVIDIA Taiwan
 
PDF
White paper IBM: Ripensare il Made in Italy nell’Era del digitale
Faq400 - la Community IBM i italiana
 
PDF
以深度學習加速語音及影像辨識應用發展
NVIDIA Taiwan
 
PDF
PIKASEN Clasificadora con lector óptico
Origenes con Identidad y Calidad HONDURIGEN
 
PDF
Pronunciamiento apo 25 03 2017
megaradioexpress
 
PDF
Impact Hub_Abidjan - Columbia Ci3
Kathy Liu, MPA CIPP
 
PPTX
Next Money Fintech Finals Hong Kong: January 19, 2017
Jim Marous
 
Codemotion 2013 scalatra_play_spray
Massimiliano Dessì
 
Why we cannot ignore functional programming
Massimiliano Dessì
 
Scala Italy 2013 extended Scalatra vs Spring MVC
Massimiliano Dessì
 
Docker linuxday 2015
Massimiliano Dessì
 
NoEstimates @ miniIAD
Massimo Iacolare
 
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
Massimiliano Dessì
 
認識那條鯨魚 Docker 初探
仲昀 王
 
Aeroprobing A.I. Drone with TX1
NVIDIA Taiwan
 
White paper IBM: Ripensare il Made in Italy nell’Era del digitale
Faq400 - la Community IBM i italiana
 
以深度學習加速語音及影像辨識應用發展
NVIDIA Taiwan
 
PIKASEN Clasificadora con lector óptico
Origenes con Identidad y Calidad HONDURIGEN
 
Pronunciamiento apo 25 03 2017
megaradioexpress
 
Impact Hub_Abidjan - Columbia Ci3
Kathy Liu, MPA CIPP
 
Next Money Fintech Finals Hong Kong: January 19, 2017
Jim Marous
 
Ad

Similar to Microservices in Go_Dessi_Massimiliano_Codemotion_2017_Rome (20)

PDF
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Codemotion
 
PDF
AngularJS in large applications - AE NV
AE - architects for business and ict
 
PPTX
Cloud nativemicroservices jax-london2020
Emily Jiang
 
PPTX
Cloud nativemicroservices jax-london2020
Emily Jiang
 
PPTX
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
Emily Jiang
 
PDF
How to write clean & testable code without losing your mind
Andreas Czakaj
 
PDF
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
Editor IJCTER
 
PDF
Metarhia: Node.js Macht Frei
Timur Shemsedinov
 
PPT
Synapse india dotnet development web approch
Synapseindiappsdevelopment
 
PDF
Do you know what your drupal is doing? Observe it!
Luca Lusso
 
PPT
Synapse india reviews sharing chapter 23 – asp.net-part2
Synapseindiappsdevelopment
 
PDF
Scaling frontend applications with micro-frontends Presentation.pdf
KatamaRajuBandigari1
 
PDF
Docker meetup - PaaS interoperability
Ludovic Piot
 
PDF
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Nikolaos Georgantas
 
PPTX
ql.io at NodePDX
Subbu Allamaraju
 
ZIP
OneTeam Media Server
Mickaël Rémond
 
PPTX
MongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB
 
PDF
Building Event-Driven (Micro) Services with Apache Kafka
Guido Schmutz
 
PPTX
eProsima RPC over DDS - Connext Conf London October 2015
Jaime Martin Losa
 
Microservices in GO - Massimiliano Dessì - Codemotion Rome 2017
Codemotion
 
AngularJS in large applications - AE NV
AE - architects for business and ict
 
Cloud nativemicroservices jax-london2020
Emily Jiang
 
Cloud nativemicroservices jax-london2020
Emily Jiang
 
MicroProfile, Docker, Kubernetes, Istio and Open Shift lab @dev nexus
Emily Jiang
 
How to write clean & testable code without losing your mind
Andreas Czakaj
 
PRIVATE CLOUD SERVER IMPLEMENTATIONS FOR DATA STORAGE
Editor IJCTER
 
Metarhia: Node.js Macht Frei
Timur Shemsedinov
 
Synapse india dotnet development web approch
Synapseindiappsdevelopment
 
Do you know what your drupal is doing? Observe it!
Luca Lusso
 
Synapse india reviews sharing chapter 23 – asp.net-part2
Synapseindiappsdevelopment
 
Scaling frontend applications with micro-frontends Presentation.pdf
KatamaRajuBandigari1
 
Docker meetup - PaaS interoperability
Ludovic Piot
 
Mobile IoT Middleware Interoperability & QoS Analysis - Eclipse IoT Day Paris...
Nikolaos Georgantas
 
ql.io at NodePDX
Subbu Allamaraju
 
OneTeam Media Server
Mickaël Rémond
 
MongoDB.local Atlanta: Introduction to Serverless MongoDB
MongoDB
 
Building Event-Driven (Micro) Services with Apache Kafka
Guido Schmutz
 
eProsima RPC over DDS - Connext Conf London October 2015
Jaime Martin Losa
 
Ad

More from Massimiliano Dessì (20)

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

Recently uploaded (20)

PDF
Introduction to Apache Iceberg™ & Tableflow
Alluxio, Inc.
 
PPTX
From spreadsheets and delays to real-time control
SatishKumar2651
 
PDF
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
 
PDF
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
 
PDF
IDM Crack with Internet Download Manager 6.42 Build 31 2025?
utfefguu
 
PPTX
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
 
PPTX
Build a Custom Agent for Agentic Testing.pptx
klpathrudu
 
PDF
10 Salesforce Consulting Companies in Sydney.pdf
DianApps Technologies
 
PPTX
How Odoo ERP Enhances Operational Visibility Across Your Organization.pptx
pintadoxavier667
 
PPTX
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
 
PPTX
API DOCUMENTATION | API INTEGRATION PLATFORM
philipnathen82
 
PDF
Message Level Status (MLS): The Instant Feedback Mechanism for UAE e-Invoicin...
Prachi Desai
 
PPTX
Odoo Migration Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
 
PDF
ERP Consulting Services and Solutions by Contetra Pvt Ltd
jayjani123
 
PPTX
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
 
PDF
Optimizing Tiered Storage for Low-Latency Real-Time Analytics at AI Scale
Alluxio, Inc.
 
PPTX
Smart Doctor Appointment Booking option in odoo.pptx
AxisTechnolabs
 
PDF
Australian Enterprises Need Project Service Automation
Navision India
 
PDF
Salesforce Experience Cloud Consultant.pdf
VALiNTRY360
 
PPTX
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 
Introduction to Apache Iceberg™ & Tableflow
Alluxio, Inc.
 
From spreadsheets and delays to real-time control
SatishKumar2651
 
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
 
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
 
IDM Crack with Internet Download Manager 6.42 Build 31 2025?
utfefguu
 
BB FlashBack Pro 5.61.0.4843 With Crack Free Download
cracked shares
 
Build a Custom Agent for Agentic Testing.pptx
klpathrudu
 
10 Salesforce Consulting Companies in Sydney.pdf
DianApps Technologies
 
How Odoo ERP Enhances Operational Visibility Across Your Organization.pptx
pintadoxavier667
 
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
 
API DOCUMENTATION | API INTEGRATION PLATFORM
philipnathen82
 
Message Level Status (MLS): The Instant Feedback Mechanism for UAE e-Invoicin...
Prachi Desai
 
Odoo Migration Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
 
ERP Consulting Services and Solutions by Contetra Pvt Ltd
jayjani123
 
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
 
Optimizing Tiered Storage for Low-Latency Real-Time Analytics at AI Scale
Alluxio, Inc.
 
Smart Doctor Appointment Booking option in odoo.pptx
AxisTechnolabs
 
Australian Enterprises Need Project Service Automation
Navision India
 
Salesforce Experience Cloud Consultant.pdf
VALiNTRY360
 
Foundations of Marketo Engage - Powering Campaigns with Marketo Personalization
bbedford2
 

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: "[email protected]", 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