Deploying Swift

With Docker and Kubernetes
Swift Cloud Workshop 3

February 23rd, 2018
Chris Bailey

(@Chris__Bailey)
: Key Technologies
: Key Technologies
Container
: Key Technologies
Container Orchestration
: Key Technologies
Container Orchestration
Package and Deploy
: Key Technologies
Container Orchestration
MonitoringPackage and Deploy
: Key Technologies
Container Orchestration
Monitoring Fault TolerancePackage and Deploy
Building Swift
Microservices
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import LoggerAPI
import CloudEnvironment
import KituraContracts
import Health
public let projectPath = ConfigurationManager.BasePath.project.path
public let health = Health()
public class App {
let router = Router()
let cloudEnv = CloudEnv()
public init() throws {
}
func postInit() throws {
initializeMetrics(app: self)
initializeHealthRoutes(app: self)
}
public func run() throws {
try postInit()
Kitura.addHTTPServer(onPort: cloudEnv.port, with: router)
Kitura.run()
}
}
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
FROM ibmcom/swift-ubuntu-runtime:4.0
# We can replace this port with what the user wants
EXPOSE 8080
# Install system level packages
# RUN apt-get update && apt-get dist-upgrade -y
# Add utils files
ADD https://raw.githubusercontent.com/IBM-Swift/swift-ubuntu-
docker/master/utils/run-utils.sh /swift-utils/run-utils.sh
ADD https://raw.githubusercontent.com/IBM-Swift/swift-ubuntu-
docker/master/utils/common-utils.sh /swift-utils/common-utils.sh
RUN chmod -R 555 /swift-utils
# Bundle application source & binaries
COPY . /swift-project
# Command to start Swift application
CMD [ "sh", "-c", "cd /swift-project && .build-ubuntu/release/
helium" ]
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
Dockerfile
Dockerfile-tools
$ docker build -t <your username>/swift-app .

$ docker build -t <your username>/swift-app .

$ docker run -p 49160:8080 -d <your username>/swift-app
$ docker build -t <your username>/swift-app .

$ docker run -p 49160:8080 -d <your username>/swift-app
$ docker build -t <your username>/swift-app .

$ docker run -p 49160:8080 -d <your username>/swift-app
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
apiVersion: v1
description: A Helm chart for Kubernetes
name: swift-app
version: 1.0.0
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: “{{ .Chart.Name }}-deployment"
labels:
chart: “{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}’
spec:
replicas: “{{ .Values.replicaCount }}”
revisionHistoryLimit: “{{ .Values.revisionHistoryLimit }}”
template:
metadata:
labels:
app: “{{ .Chart.Name }}-selector"
version: "current"
spec:
containers:
- name: “{{ .Chart.Name }}”
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /health
port: {{ .Values.service.servicePort }}
initialDelaySeconds:
{{.Values.livenessProbe.initialDelaySeconds}}
periodSeconds: {{ .Values.livenessProbe.periodSeconds}}
resources:
requests:
cpu: "{{ .Values.image.resources.requests.cpu }}"
memory: "{{ .Values.image.resources.requests.memory }}"
env:
- name: PORT
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: "{{ .Chart.Name }}-hpa-policy"
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1beta1
kind: Deployment
name: "{{ .Chart.Name }}-deployment"
minReplicas: {{ .Values.hpa.minReplicas }}
maxReplicas: {{ .Values.hpa.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization:
{{.Values.hpa.metrics.cpu.targetAverageUtilization}}
- type: Resource
resource:
name: memory
targetAverageUtilization:
{{.Values.hpa.metrics.memory.targetAverageUtilization}}
{{ end }}
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/scrape: 'true'
name: "{{ .Chart.Name }}-service"
labels:
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+"
"_" }}"
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.servicePort }}
selector:
app: "{{ .Chart.Name }}-selector"
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
HELM CHARTS
replicaCount: 1
revisionHistoryLimit: 1
image:
repository: registry.ng.bluemix.net/replace-namespace/swift-app
tag: v1.0.0
pullPolicy: Always
resources:
requests:
cpu: 200m
memory: 300Mi
livenessProbe:
initialDelaySeconds: 3000
periodSeconds: 1000
service:
name: Node
type: NodePort
servicePort: 8080
hpa:
enabled: false
minReplicas: 1
maxReplicas: 2
metrics:
cpu:
targetAverageUtilization: 70
memory:
targetAverageUtilization: 70
services:
base:
enabled: false
replicaCount: 1
image:
tag : v0.9.9
weight: 100
prometheus:
enabled: false
$ helm package ./chart/swift-app
$ helm package ./chart/swift-app
$ helm install ./swift-app-1.0.0.tgz
$ helm package ./chart/swift-app
$ helm install ./swift-app-1.0.0.tgz
$ helm package ./chart/swift-app
$ helm install ./swift-app-1.0.0.tgz
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
Jenkinsfile
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Dockerfile
Dockerfile-tools
.dockerignore
chart/swift-app/Chart.yaml
chart/swift-app/templates/deployment.yaml
chart/swift-app/templates/hpa.yaml
chart/swift-app/templates/service.yaml
chart/swift-app/values.yaml
Jenkinsfile
#!groovy
@Library('MicroserviceBuilder') _
microserviceBuilderPipeline {
image = ‘swift-app’
}
Integrating with

Kubernetes
• Checks status of service
• Requires /health endpoint providing data

• Restarts service if not 200 OK
• Restarts service if no response

Microservice Health: Liveness Probes
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import LoggerAPI
import CloudEnvironment
import KituraContracts
import Health
public let projectPath = ConfigurationManager.BasePath.project.path
public let health = Health()
public class App {
let router = Router()
let cloudEnv = CloudEnv()
public init() throws {
}
func postInit() throws {
initializeMetrics(app: self)
initializeHealthRoutes(app: self)
}
public func run() throws {
try postInit()
Kitura.addHTTPServer(onPort: cloudEnv.port, with: router)
Kitura.run()
}
}
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import LoggerAPI
func initializeHealthRoutes(app: App) {
app.router.get("/health") { request, response, _ in
let result = health.status.toSimpleDictionary()
if health.status.state == .UP {
try response.send(json: result).end()
} else {
try response.status(.serviceUnavailable).send(json:
result).end()
}
}
}
• Provides “fault tolerance” to an application

• Enables handling of failed downstream services
• Prevents repeated calls to failed services
• Provides alternative fallback function

• Integrates with monitoring
Microservice Resilience: Hystrix and CircuitBreaker
• Provides “fault tolerance” to an application

• Enables handling of failed downstream services
• Prevents repeated calls to failed services
• Provides alternative fallback function

• Integrates with monitoring
Microservice Resilience: Hystrix and CircuitBreaker
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
breaker = CircuitBreaker(
name: "breaker",

timeout: 10000,
maxFailures: 3,
rollingWindow: 60000,
command: myCommand,
fallback: myFallback)
func myFallback(err: BreakerError, msg: String) {
Log.verbose("Error: (error)")
Log.verbose("Message: (msg)")
}
func myCommand(invocation: Invocation<(String), String>) {



}
breaker.run(commandArgs: , fallbackArgs:)
CircuitBreaker
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
breaker = CircuitBreaker(
name: "breaker",

timeout: 10000,
maxFailures: 3,
rollingWindow: 60000,
command: myCommand,
fallback: myFallback)
func myFallback(err: BreakerError, msg: String) {
Log.verbose("Error: (error)")
Log.verbose("Message: (msg)")
}
func myCommand(invocation: Invocation<(String), String>) {



}
breaker.run(commandArgs: , fallbackArgs:)
CircuitBreaker
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
breaker = CircuitBreaker(
name: "breaker",

timeout: 10000,
maxFailures: 3,
rollingWindow: 60000,
command: myCommand,
fallback: myFallback)
func myFallback(err: BreakerError, msg: String) {
Log.verbose("Error: (error)")
Log.verbose("Message: (msg)")
}
func myCommand(invocation: Invocation<(String), String>) {



}
breaker.run(commandArgs: , fallbackArgs:)
CircuitBreaker
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
breaker = CircuitBreaker(
name: "breaker",

timeout: 10000,
maxFailures: 3,
rollingWindow: 60000,
command: myCommand,
fallback: myFallback)
func myFallback(err: BreakerError, msg: String) {
Log.verbose("Error: (error)")
Log.verbose("Message: (msg)")
}
func myCommand(invocation: Invocation<(String), String>) {



}
breaker.run(commandArgs: , fallbackArgs:)
CircuitBreaker
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
let circuitParameters = CircuitParameters(
timeout: 2000,
maxFailures: 2,
fallback: myFallback)
let request = RestRequest(method: .get, url: "/hello")
request.circuitParameters = circuitParameters
SwiftyRequest
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
let circuitParameters = CircuitParameters(
timeout: 2000,
maxFailures: 2,
fallback: myFallback)
let request = RestRequest(method: .get, url: "/hello")
request.circuitParameters = circuitParameters
SwiftyRequest
• Collects data from each enabled service

• Requires /metrics endpoint providing data

• Provides storage and correlation capabilities
• Provide customisable dashboard

• Integrates with Graphana, Graphite, etc
Microservice Metrics: Prometheus
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift

Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import LoggerAPI
import CloudEnvironment
import KituraContracts
import Health
public let projectPath = ConfigurationManager.BasePath.project.path
public let health = Health()
public class App {
let router = Router()
let cloudEnv = CloudEnv()
public init() throws {
}
func postInit() throws {
initializeMetrics(app: self)
initializeHealthRoutes(app: self)
}
public func run() throws {
try postInit()
Kitura.addHTTPServer(onPort: cloudEnv.port, with: router)
Kitura.run()
}
}
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift
Sources/Applicaton/Metrics.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import SwiftMetrics
import SwiftMetricsDash
import SwiftMetricsPrometheus
import LoggerAPI
var swiftMetrics: SwiftMetrics?
var swiftMetricsDash: SwiftMetricsDash?
var swiftMetricsPrometheus: SwiftMetricsPrometheus?
func initializeMetrics(router: Router) {
do {
let metrics = try SwiftMetrics()
let dashboard = try SwiftMetricsDash(swiftMetricsInstance:
metrics, endpoint: router)
let prometheus = try
SwiftMetricsPrometheus(swiftMetricsInstance:
metrics, endpoint: router)
swiftMetrics = metrics
swiftMetricsDash = dashboard
swiftMetricsPrometheus = prometheus
Log.info("Initialized metrics.")
} catch {
Log.warning("Failed to initialize metrics: (error)")
}
}
• ‘SwiftMetricsDash’ provides self-hosted monitoring

• Inbound and Outbound request performance
• Resource monitoring
• ++ Dispatch queue monitoring

• ++ profiling and flame graphs
Deep Analysis: ‘SwiftMetricsDash’
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift
Sources/Applicaton/Metrics.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import SwiftMetrics
import SwiftMetricsDash
import SwiftMetricsPrometheus
import LoggerAPI
var swiftMetrics: SwiftMetrics?
var swiftMetricsDash: SwiftMetricsDash?
var swiftMetricsPrometheus: SwiftMetricsPrometheus?
func initializeMetrics(router: Router) {
do {
let metrics = try SwiftMetrics()
let dashboard = try SwiftMetricsDash(swiftMetricsInstance:
metrics, endpoint: router)
let prometheus = try
SwiftMetricsPrometheus(swiftMetricsInstance:
metrics, endpoint: router)
swiftMetrics = metrics
swiftMetricsDash = dashboard
swiftMetricsPrometheus = prometheus
Log.info("Initialized metrics.")
} catch {
Log.warning("Failed to initialize metrics: (error)")
}
}
func add(_ a: Int,
to b: Int) -> Void
{
print(a + b)
}
let a = ”5”
let b = 3
Sources/*
Sources/Application/Application.swift
Sources/Application/Routes/Health.swift
Sources/Applicaton/Metrics.swift
Tests/*
Package.swift
README.md
.gitignore
Kitura
import Kitura
import SwiftMetrics
import SwiftMetricsDash
import SwiftMetricsPrometheus
import LoggerAPI
var swiftMetrics: SwiftMetrics?
var swiftMetricsDash: SwiftMetricsDash?
var swiftMetricsPrometheus: SwiftMetricsPrometheus?
func initializeMetrics(router: Router) {
do {
let metrics = try SwiftMetrics()
let dashboard = try SwiftMetricsDash(swiftMetricsInstance:
metrics, endpoint: router)
let prometheus = try
SwiftMetricsPrometheus(swiftMetricsInstance:
metrics, endpoint: router)
swiftMetrics = metrics
swiftMetricsDash = dashboard
swiftMetricsPrometheus = prometheus
Log.info("Initialized metrics.")
} catch {
Log.warning("Failed to initialize metrics: (error)")
}
}
‘SwiftMetricsDash’
$ kitura init$ kitura init
DEMO
Common
Microservices Approach
Config Fault Tolerance Health Check Health Metrics JWT Propagation
externalize configuration
to improve portability
build robust behavior to
cope with unexpected
failures
common format to
determine service
availability
common REST
endpoints for monitoring
service health
interoperable
authentication and role-
based access control
Config Fault Tolerance Health Check Health Metrics JWT Propagation
externalize configuration
to improve portability
build robust behavior to
cope with unexpected
failures
common format to
determine service
availability
common REST
endpoints for monitoring
service health
interoperable
authentication and role-
based access control
CloudEnvironment CircuitBreaker Health SwiftMetricsPrometheus Swift-JWT
Config Fault Tolerance Health Check Health Metrics JWT Propagation
externalize configuration
to improve portability
build robust behavior to
cope with unexpected
failures
common format to
determine service
availability
common REST
endpoints for monitoring
service health
interoperable
authentication and role-
based access control
CloudEnvironment CircuitBreaker Health SwiftMetricsPrometheus Swift-JWT
ibm-cloud-env hystrix-js /health appmetrics-prometheus jsonwebtoken
59
IBM Foundation
Support for Runtimes
generator-nodeserver
appmetrics monitoring
generator-swiftserver
swiftmetrics monitoringjavametrics monitoring
IBM Support for Runtimes
Enterprise Support: Runtimes
60
LoopBack
IBM Foundation
Support for Runtimes
generator-nodeserver
appmetrics monitoring
generator-swiftserver
swiftmetrics monitoringjavametrics monitoring
IBM Support for Runtimes
IBM Advanced
Support for Runtime
Frameworks
Enterprise Support: Frameworks
61
LoopBack
IBM Foundation
Support for Runtimes
IBM Advanced
Support for Runtime
Frameworks
generator-nodeserver
appmetrics monitoring
generator-swiftserver
swiftmetrics monitoringjavametrics monitoring
IBM Support for Runtimes
Enterprise Support: Module Ecosystems
What’s Missing?
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
PUBLIC NETWORK CLOUD NETWORK
CATALOG
ORDER
INVENTORY
USER
MySQL
MongoDB
SPARK
ELASTICSEARCH
BACKEND FOR

FRONTEND
MICROSERVICES SERVICES
LOAD

BALANCER
BROWSER
TIME
BROWSER
LOAD BALANCER
TIME
BROWSER
LOAD BALANCER
WEB BFF
TIME
BROWSER
LOAD BALANCER
WEB BFF
ORDER SERVICE
TIME
BROWSER
LOAD BALANCER
WEB BFF
ORDER SERVICE
MongoDB
TIME
BROWSER
LOAD BALANCER
WEB BFF
ORDER SERVICE
MongoDB
INVENTORY SERVICE
TIME
MySQL
BROWSER
LOAD BALANCER
WEB BFF
ORDER SERVICE
MongoDB
INVENTORY SERVICE
TIME
MySQL
BROWSER
LOAD BALANCER
WEB BFF
ORDER SERVICE
MongoDB
INVENTORY SERVICE
MongoDB
TIME
• Collects data from each enabled service

• Propagates correlation ID using HTTP headers

• Provides sampling, tracing, and debug capabilities
• Collects microsecond timestamps

• Correlates data in Zipkin server
• Presents data in Zipkin dashboard
Request Tracking: OpenTracing and Zipkin
Questions?

Swift Cloud Workshop - Swift Microservices

  • 1.
    Deploying Swift
 With Dockerand Kubernetes Swift Cloud Workshop 3
 February 23rd, 2018 Chris Bailey
 (@Chris__Bailey)
  • 2.
  • 3.
  • 4.
  • 5.
    : Key Technologies ContainerOrchestration Package and Deploy
  • 6.
    : Key Technologies ContainerOrchestration MonitoringPackage and Deploy
  • 7.
    : Key Technologies ContainerOrchestration Monitoring Fault TolerancePackage and Deploy
  • 8.
  • 9.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Kitura
  • 10.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Kitura import Kitura import LoggerAPI import CloudEnvironment import KituraContracts import Health public let projectPath = ConfigurationManager.BasePath.project.path public let health = Health() public class App { let router = Router() let cloudEnv = CloudEnv() public init() throws { } func postInit() throws { initializeMetrics(app: self) initializeHealthRoutes(app: self) } public func run() throws { try postInit() Kitura.addHTTPServer(onPort: cloudEnv.port, with: router) Kitura.run() } }
  • 11.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore
  • 12.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore FROM ibmcom/swift-ubuntu-runtime:4.0 # We can replace this port with what the user wants EXPOSE 8080 # Install system level packages # RUN apt-get update && apt-get dist-upgrade -y # Add utils files ADD https://raw.githubusercontent.com/IBM-Swift/swift-ubuntu- docker/master/utils/run-utils.sh /swift-utils/run-utils.sh ADD https://raw.githubusercontent.com/IBM-Swift/swift-ubuntu- docker/master/utils/common-utils.sh /swift-utils/common-utils.sh RUN chmod -R 555 /swift-utils # Bundle application source & binaries COPY . /swift-project # Command to start Swift application CMD [ "sh", "-c", "cd /swift-project && .build-ubuntu/release/ helium" ]
  • 13.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore Dockerfile Dockerfile-tools
  • 14.
    $ docker build-t <your username>/swift-app .

  • 15.
    $ docker build-t <your username>/swift-app .
 $ docker run -p 49160:8080 -d <your username>/swift-app
  • 16.
    $ docker build-t <your username>/swift-app .
 $ docker run -p 49160:8080 -d <your username>/swift-app
  • 17.
    $ docker build-t <your username>/swift-app .
 $ docker run -p 49160:8080 -d <your username>/swift-app
  • 18.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS
  • 19.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS apiVersion: v1 description: A Helm chart for Kubernetes name: swift-app version: 1.0.0
  • 20.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS apiVersion: extensions/v1beta1 kind: Deployment metadata: name: “{{ .Chart.Name }}-deployment" labels: chart: “{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}’ spec: replicas: “{{ .Values.replicaCount }}” revisionHistoryLimit: “{{ .Values.revisionHistoryLimit }}” template: metadata: labels: app: “{{ .Chart.Name }}-selector" version: "current" spec: containers: - name: “{{ .Chart.Name }}” image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: Always livenessProbe: httpGet: path: /health port: {{ .Values.service.servicePort }} initialDelaySeconds: {{.Values.livenessProbe.initialDelaySeconds}} periodSeconds: {{ .Values.livenessProbe.periodSeconds}} resources: requests: cpu: "{{ .Values.image.resources.requests.cpu }}" memory: "{{ .Values.image.resources.requests.memory }}" env: - name: PORT
  • 21.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: "{{ .Chart.Name }}-hpa-policy" namespace: default spec: scaleTargetRef: apiVersion: apps/v1beta1 kind: Deployment name: "{{ .Chart.Name }}-deployment" minReplicas: {{ .Values.hpa.minReplicas }} maxReplicas: {{ .Values.hpa.maxReplicas }} metrics: - type: Resource resource: name: cpu targetAverageUtilization: {{.Values.hpa.metrics.cpu.targetAverageUtilization}} - type: Resource resource: name: memory targetAverageUtilization: {{.Values.hpa.metrics.memory.targetAverageUtilization}} {{ end }}
  • 22.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS apiVersion: v1 kind: Service metadata: annotations: prometheus.io/scrape: 'true' name: "{{ .Chart.Name }}-service" labels: chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" spec: type: {{ .Values.service.type }} ports: - name: http port: {{ .Values.service.servicePort }} selector: app: "{{ .Chart.Name }}-selector"
  • 23.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml HELM CHARTS replicaCount: 1 revisionHistoryLimit: 1 image: repository: registry.ng.bluemix.net/replace-namespace/swift-app tag: v1.0.0 pullPolicy: Always resources: requests: cpu: 200m memory: 300Mi livenessProbe: initialDelaySeconds: 3000 periodSeconds: 1000 service: name: Node type: NodePort servicePort: 8080 hpa: enabled: false minReplicas: 1 maxReplicas: 2 metrics: cpu: targetAverageUtilization: 70 memory: targetAverageUtilization: 70 services: base: enabled: false replicaCount: 1 image: tag : v0.9.9 weight: 100 prometheus: enabled: false
  • 24.
    $ helm package./chart/swift-app
  • 25.
    $ helm package./chart/swift-app $ helm install ./swift-app-1.0.0.tgz
  • 26.
    $ helm package./chart/swift-app $ helm install ./swift-app-1.0.0.tgz
  • 27.
    $ helm package./chart/swift-app $ helm install ./swift-app-1.0.0.tgz
  • 28.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml Jenkinsfile
  • 29.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Dockerfile Dockerfile-tools .dockerignore chart/swift-app/Chart.yaml chart/swift-app/templates/deployment.yaml chart/swift-app/templates/hpa.yaml chart/swift-app/templates/service.yaml chart/swift-app/values.yaml Jenkinsfile #!groovy @Library('MicroserviceBuilder') _ microserviceBuilderPipeline { image = ‘swift-app’ }
  • 30.
  • 31.
    • Checks statusof service • Requires /health endpoint providing data
 • Restarts service if not 200 OK • Restarts service if no response
 Microservice Health: Liveness Probes
  • 32.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Kitura
  • 33.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Kitura import Kitura import LoggerAPI import CloudEnvironment import KituraContracts import Health public let projectPath = ConfigurationManager.BasePath.project.path public let health = Health() public class App { let router = Router() let cloudEnv = CloudEnv() public init() throws { } func postInit() throws { initializeMetrics(app: self) initializeHealthRoutes(app: self) } public func run() throws { try postInit() Kitura.addHTTPServer(onPort: cloudEnv.port, with: router) Kitura.run() } }
  • 34.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift Tests/* Package.swift README.md .gitignore Kitura import LoggerAPI func initializeHealthRoutes(app: App) { app.router.get("/health") { request, response, _ in let result = health.status.toSimpleDictionary() if health.status.state == .UP { try response.send(json: result).end() } else { try response.status(.serviceUnavailable).send(json: result).end() } } }
  • 35.
    • Provides “faulttolerance” to an application
 • Enables handling of failed downstream services • Prevents repeated calls to failed services • Provides alternative fallback function
 • Integrates with monitoring Microservice Resilience: Hystrix and CircuitBreaker
  • 36.
    • Provides “faulttolerance” to an application
 • Enables handling of failed downstream services • Prevents repeated calls to failed services • Provides alternative fallback function
 • Integrates with monitoring Microservice Resilience: Hystrix and CircuitBreaker
  • 37.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura breaker = CircuitBreaker( name: "breaker",
 timeout: 10000, maxFailures: 3, rollingWindow: 60000, command: myCommand, fallback: myFallback) func myFallback(err: BreakerError, msg: String) { Log.verbose("Error: (error)") Log.verbose("Message: (msg)") } func myCommand(invocation: Invocation<(String), String>) {
 
 } breaker.run(commandArgs: , fallbackArgs:) CircuitBreaker
  • 38.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura breaker = CircuitBreaker( name: "breaker",
 timeout: 10000, maxFailures: 3, rollingWindow: 60000, command: myCommand, fallback: myFallback) func myFallback(err: BreakerError, msg: String) { Log.verbose("Error: (error)") Log.verbose("Message: (msg)") } func myCommand(invocation: Invocation<(String), String>) {
 
 } breaker.run(commandArgs: , fallbackArgs:) CircuitBreaker
  • 39.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura breaker = CircuitBreaker( name: "breaker",
 timeout: 10000, maxFailures: 3, rollingWindow: 60000, command: myCommand, fallback: myFallback) func myFallback(err: BreakerError, msg: String) { Log.verbose("Error: (error)") Log.verbose("Message: (msg)") } func myCommand(invocation: Invocation<(String), String>) {
 
 } breaker.run(commandArgs: , fallbackArgs:) CircuitBreaker
  • 40.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura breaker = CircuitBreaker( name: "breaker",
 timeout: 10000, maxFailures: 3, rollingWindow: 60000, command: myCommand, fallback: myFallback) func myFallback(err: BreakerError, msg: String) { Log.verbose("Error: (error)") Log.verbose("Message: (msg)") } func myCommand(invocation: Invocation<(String), String>) {
 
 } breaker.run(commandArgs: , fallbackArgs:) CircuitBreaker
  • 41.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura let circuitParameters = CircuitParameters( timeout: 2000, maxFailures: 2, fallback: myFallback) let request = RestRequest(method: .get, url: "/hello") request.circuitParameters = circuitParameters SwiftyRequest
  • 42.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura let circuitParameters = CircuitParameters( timeout: 2000, maxFailures: 2, fallback: myFallback) let request = RestRequest(method: .get, url: "/hello") request.circuitParameters = circuitParameters SwiftyRequest
  • 43.
    • Collects datafrom each enabled service
 • Requires /metrics endpoint providing data
 • Provides storage and correlation capabilities • Provide customisable dashboard
 • Integrates with Graphana, Graphite, etc Microservice Metrics: Prometheus
  • 44.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Tests/* Package.swift README.md .gitignore Kitura
  • 45.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift
 Tests/* Package.swift README.md .gitignore Kitura import Kitura import LoggerAPI import CloudEnvironment import KituraContracts import Health public let projectPath = ConfigurationManager.BasePath.project.path public let health = Health() public class App { let router = Router() let cloudEnv = CloudEnv() public init() throws { } func postInit() throws { initializeMetrics(app: self) initializeHealthRoutes(app: self) } public func run() throws { try postInit() Kitura.addHTTPServer(onPort: cloudEnv.port, with: router) Kitura.run() } }
  • 46.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift Sources/Applicaton/Metrics.swift Tests/* Package.swift README.md .gitignore Kitura import Kitura import SwiftMetrics import SwiftMetricsDash import SwiftMetricsPrometheus import LoggerAPI var swiftMetrics: SwiftMetrics? var swiftMetricsDash: SwiftMetricsDash? var swiftMetricsPrometheus: SwiftMetricsPrometheus? func initializeMetrics(router: Router) { do { let metrics = try SwiftMetrics() let dashboard = try SwiftMetricsDash(swiftMetricsInstance: metrics, endpoint: router) let prometheus = try SwiftMetricsPrometheus(swiftMetricsInstance: metrics, endpoint: router) swiftMetrics = metrics swiftMetricsDash = dashboard swiftMetricsPrometheus = prometheus Log.info("Initialized metrics.") } catch { Log.warning("Failed to initialize metrics: (error)") } }
  • 49.
    • ‘SwiftMetricsDash’ providesself-hosted monitoring
 • Inbound and Outbound request performance • Resource monitoring • ++ Dispatch queue monitoring
 • ++ profiling and flame graphs Deep Analysis: ‘SwiftMetricsDash’
  • 50.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift Sources/Applicaton/Metrics.swift Tests/* Package.swift README.md .gitignore Kitura import Kitura import SwiftMetrics import SwiftMetricsDash import SwiftMetricsPrometheus import LoggerAPI var swiftMetrics: SwiftMetrics? var swiftMetricsDash: SwiftMetricsDash? var swiftMetricsPrometheus: SwiftMetricsPrometheus? func initializeMetrics(router: Router) { do { let metrics = try SwiftMetrics() let dashboard = try SwiftMetricsDash(swiftMetricsInstance: metrics, endpoint: router) let prometheus = try SwiftMetricsPrometheus(swiftMetricsInstance: metrics, endpoint: router) swiftMetrics = metrics swiftMetricsDash = dashboard swiftMetricsPrometheus = prometheus Log.info("Initialized metrics.") } catch { Log.warning("Failed to initialize metrics: (error)") } }
  • 51.
    func add(_ a:Int, to b: Int) -> Void { print(a + b) } let a = ”5” let b = 3 Sources/* Sources/Application/Application.swift Sources/Application/Routes/Health.swift Sources/Applicaton/Metrics.swift Tests/* Package.swift README.md .gitignore Kitura import Kitura import SwiftMetrics import SwiftMetricsDash import SwiftMetricsPrometheus import LoggerAPI var swiftMetrics: SwiftMetrics? var swiftMetricsDash: SwiftMetricsDash? var swiftMetricsPrometheus: SwiftMetricsPrometheus? func initializeMetrics(router: Router) { do { let metrics = try SwiftMetrics() let dashboard = try SwiftMetricsDash(swiftMetricsInstance: metrics, endpoint: router) let prometheus = try SwiftMetricsPrometheus(swiftMetricsInstance: metrics, endpoint: router) swiftMetrics = metrics swiftMetricsDash = dashboard swiftMetricsPrometheus = prometheus Log.info("Initialized metrics.") } catch { Log.warning("Failed to initialize metrics: (error)") } }
  • 52.
  • 53.
    $ kitura init$kitura init
  • 54.
  • 55.
  • 56.
    Config Fault ToleranceHealth Check Health Metrics JWT Propagation externalize configuration to improve portability build robust behavior to cope with unexpected failures common format to determine service availability common REST endpoints for monitoring service health interoperable authentication and role- based access control
  • 57.
    Config Fault ToleranceHealth Check Health Metrics JWT Propagation externalize configuration to improve portability build robust behavior to cope with unexpected failures common format to determine service availability common REST endpoints for monitoring service health interoperable authentication and role- based access control CloudEnvironment CircuitBreaker Health SwiftMetricsPrometheus Swift-JWT
  • 58.
    Config Fault ToleranceHealth Check Health Metrics JWT Propagation externalize configuration to improve portability build robust behavior to cope with unexpected failures common format to determine service availability common REST endpoints for monitoring service health interoperable authentication and role- based access control CloudEnvironment CircuitBreaker Health SwiftMetricsPrometheus Swift-JWT ibm-cloud-env hystrix-js /health appmetrics-prometheus jsonwebtoken
  • 59.
    59 IBM Foundation Support forRuntimes generator-nodeserver appmetrics monitoring generator-swiftserver swiftmetrics monitoringjavametrics monitoring IBM Support for Runtimes Enterprise Support: Runtimes
  • 60.
    60 LoopBack IBM Foundation Support forRuntimes generator-nodeserver appmetrics monitoring generator-swiftserver swiftmetrics monitoringjavametrics monitoring IBM Support for Runtimes IBM Advanced Support for Runtime Frameworks Enterprise Support: Frameworks
  • 61.
    61 LoopBack IBM Foundation Support forRuntimes IBM Advanced Support for Runtime Frameworks generator-nodeserver appmetrics monitoring generator-swiftserver swiftmetrics monitoringjavametrics monitoring IBM Support for Runtimes Enterprise Support: Module Ecosystems
  • 62.
  • 63.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 64.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 65.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 66.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 67.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 68.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 69.
    PUBLIC NETWORK CLOUDNETWORK CATALOG ORDER INVENTORY USER MySQL MongoDB SPARK ELASTICSEARCH BACKEND FOR
 FRONTEND MICROSERVICES SERVICES LOAD
 BALANCER
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
    BROWSER LOAD BALANCER WEB BFF ORDERSERVICE MongoDB INVENTORY SERVICE TIME
  • 76.
    MySQL BROWSER LOAD BALANCER WEB BFF ORDERSERVICE MongoDB INVENTORY SERVICE TIME
  • 77.
    MySQL BROWSER LOAD BALANCER WEB BFF ORDERSERVICE MongoDB INVENTORY SERVICE MongoDB TIME
  • 78.
    • Collects datafrom each enabled service
 • Propagates correlation ID using HTTP headers
 • Provides sampling, tracing, and debug capabilities • Collects microsecond timestamps
 • Correlates data in Zipkin server • Presents data in Zipkin dashboard Request Tracking: OpenTracing and Zipkin
  • 80.