SlideShare a Scribd company logo
1 of 46
Download to read offline
A BLUEPRINT FOR
SCALA
MICROSERVICES
FEDERICO FEROLDI
CTO / MEASURENCE.COM
@CLOUDIFY
OUR GOAL
Empower developers with tools
and process to own a service
from development to production.
Monolithic (1990s) SOA (2000s) Microservices (2010s)
RATIONALE
Small team: time is scarce
Heavy use of open source
Automate al the things
Sane standards, easy override
MAIN TOPICS
Minimum Viable Service
Deployment & Discovery
Best practices
MINIMUM VIABLE SERVICE
Business Logic
REST API
Configuration
Health / Monitoring
Releasing / Versioning
Packaging
BUSINESS LOGIC = AKKA ACTORS
Sum

Service
HTTP
API
SumOp
SumRes
“ask” pattern
BUSINESS LOGIC = AKKA ACTORS
object SumService {
def props = Props(classOf[SumService])
!
case class SumOp(a: Int, b: Int)
case class SumRes(result: Int)
}
!
class SumService extends Actor {
import SumService._
!
def receive: Receive = {
case SumOp(a, b) => sender() ! SumRes(a + b)
}
}
REST API = SPRAY.IO
Sum

Service
SPRAY
API
SumOp
SumRes
GET /v1/sum
JSON
REST API = SPRAY.IO
case class SumApiResponse(result: Int)
!
object SumProtocol extends DefaultJsonProtocol {
implicit val sumApiResponseFormat = jsonFormat1(SumApiResponse)
}
!
class SumHttpServiceV1(services: Services) {
import SumProtocol._
!
def route = path("v1" / "sum") {
get {
parameters('a.as[Int], 'b.as[Int]) { (a, b) =>
def future = (services.sumService ? SumOp(a, b)).mapTo[SumRes]
onSuccess(future) { response =>
complete(SumApiResponse(response.result))
}
}
}
}
}
API DOCS = SWAGGER
SPRAY-
SWAGGER
GET /
HTML/JSON
docs
API DOCS = SWAGGER
@Api(value = “/v1/sum", description = "Sum numbers.")
class SumHttpServiceV1(services: Services) {
…
}
API DOCS = SWAGGER
!
@ApiOperation(value = "Returns the sum”, httpMethod = “GET")
!
@ApiImplicitParams(Array(
new ApiImplicitParam(
name="a", required=true, dataType="integer", paramType=“query"
),
new ApiImplicitParam(
name="b", required=true, dataType="integer", paramType=“query"
)
))
!
@ApiResponses(Array(
new ApiResponse(
code=200, message="The sum", response=classOf[SumApiResponse]
)
))
!
def route = path("v1" / "sum") { … }
API DOCS = SWAGGER
@ApiModel(description = "Result of the sum")
case class SumApiResponse(
@(ApiModelProperty @field)(value = "The sum of a and b")
result: Int
)
REST API = SPRAY.IO + SWAGGER
CONFIG = TYPESAFE CONFIG
application.conf
development.conf
testing.conf staging.conf
production.conf
CONFIG = TYPESAFE CONFIG
akka.loglevel = "INFO"
!
metrics.carbon = "graphite.local:2003"
!
acme {
environment = "production"
!
svc-calculator {
hostname = “0.0.0.0”
port = "9999"
}
}
application.conf
CONFIG = TYPESAFE CONFIG
include "application"
production.conf
CONFIG = TYPESAFE CONFIG
include "application"

!
akka.loglevel = "DEBUG"
metrics.carbon = "localhost:2003"
!
acme {
environment = "development"
!
svc-calculator {
hostname = "127.0.0.1"
}
}
development.conf
CONFIG = TYPESAFE CONFIG
val config = ConfigFactory.defaultApplication()
$ sbt -Dconfig.resource=development.conf run
Loads application.conf by default
Loads development.conf
CONFIG = TYPESAFE CONFIG
{
mysql_username=${MYSQL_USERNAME}
mysql_password=${MYSQL_PASSWORD}
}
PRO-TIP

Don’t store passwords with source code!
Instead make use ENV vars substitution and
keep passwords in a safe place.
HEALTH = SPRAY + HAPROXY
SPRAY
GET /ping
Load
Balancer
Are you ok?
HEALTH = SPRAY + HAPROXY
def route = get {
path("ping") {
complete("pong")
}
}
PERFMON = METRICS + GRAPHITE
CODAHALE
METRICS
data points
GRAPHITE
CARBON
PERF.MON. = METRICS + GRAPHITE
object MetricsInstrumentation {
val metricRegistry = new MetricRegistry()
}
!
trait Instrumented extends InstrumentedBuilder {
val metricRegistry = MetricsInstrumentation.metricRegistry
}
!
class Actor extends Actor with Instrumented {
val meter = metrics.meter("requests")
!
def receive: Receive = {
!
case Request =>
meter.mark()
!
}
}
PERFMON = METRICS + GRAPHITE
RELEASING = SBT-RELEASE
SNAPSHOT/RELEASE artifacts
Semantic versioning
version.sbt + Git tags
publishing of artifacts
100% customizable process
interactive OR automated
PACKAGING = ASSEMBLY + DOCKER
JVM
SERVICE
(fat jar)
HTTP Requests
METRICS
“Immutable” container
Other Svc HTTP Reqs
PACKAGING = SBT-ASSEMBLY + SBT-DOCKER
docker <<= (docker dependsOn assembly)
!
dockerfile in docker := {
val artifact = (outputPath in assembly).value
val artifactTargetPath = s"/app/${artifact.name}"
new Dockerfile {
from(“acme/javabase")
expose(9999)
add(artifact, artifactTargetPath)
entryPoint("java", "-jar", artifactTargetPath)
}
}
!
imageNames in docker := Seq(
ImageName(
namespace = Some(organization.value),
repository = name.value,
tag = Some("v" + version.value)
)
)
MINIMUM VIABLE SERVICE
Business Logic = Akka
REST API = Spray + Swagger
Configuration = Typesafe Config
Health / Monitoring = Metrics
Packaging = Assembly & Docker
DEPLOYMENT & DISCOVERY
Continuous Integration
Deployment
Service Discovery
CI/DEPLOY = JENKINS + SBT + ANSIBLE
Git repo
Jenkins Jobs + sbt
Test Release Dockerize Deploy
Commit
Staging / Production
Ansible
HOSTING = MESOS/MARATHON
{
"id": "/svc-calculator",
"container": {
"type": "DOCKER",
"docker": {
"image": "docker.com/svc-calculator:1.0.0",
"network": "BRIDGE",
"portMappings": [{
"containerPort": 9999, "protocol": "tcp"
}]
}
},
"env": {"JAVA_ARGS": “-Dconfig.resource=production"},
"cpus": 1,
"mem": 1024,
"instances": 2
}
HOSTING = MESOS/MARATHON
HOSTING = MESOS/MARATHON
Dynamic port mapping
DISCOVERY = ?
mesos1
/svc-calculator /svc-calculator
mesos2
/web-app
mesos3
HOST:PORT?
DISCOVERY = BAMBOO + HAPROXY
mesos1
/svc-calculator /svc-calculator
mesos2
/web-app
mesos3
BAMBOO +
HAPROXY
BAMBOO +
HAPROXY
BAMBOO +
HAPROXY
MARATHON
http://localhost/svc-calculator
:80
:30001:30002
DEPLOYMENT & DISCOVERY
CI = Jenkins + sbt
Deploy = Ansible + Marathon
Discovery = Bamboo + HAProxy
FINAL TIPS
DRY + keep team aligned
Zero friction on new services
DRY: CUSTOM SBT PLUGIN
package com.acme.sbt.plugin
import sbt._
import Keys._
object AcmePlugin extends AutoPlugin {
lazy val acmeBuildSettings = Seq(
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-feature",
"-Xlint",
"-Ywarn-dead-code",
"-target:jvm-1.7"
)
)
} AcmePlugin.scala
FINAL TIP: CUSTOM SBT PLUGIN
import com.acme.sbt.plugin.AcmePlugin._
!
Seq(acmeBuildSettings:_*)
!
// custom project settings
build.sbt
ZERO FRICTION: GITER8 TEMPLATES
% g8 file://g8-svc-spray/ --name=svc-calculator 
-—servicePort=9999
!
Template applied in ./svc-calculator
!
% ls svc-calculator
build.sbt project src version.sbt
Recap
Thank you!

More Related Content

What's hot

RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP Framework
Bo-Yi Wu
 

What's hot (20)

Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17
 
PHP 8.1 - What's new and changed
PHP 8.1 - What's new and changedPHP 8.1 - What's new and changed
PHP 8.1 - What's new and changed
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
 
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
 
Refactoring
RefactoringRefactoring
Refactoring
 
Refactoring
RefactoringRefactoring
Refactoring
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWT
 
How Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran MizrahiHow Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran Mizrahi
 
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiReactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz Khambati
 
Second Level Cache in JPA Explained
Second Level Cache in JPA ExplainedSecond Level Cache in JPA Explained
Second Level Cache in JPA Explained
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
 
Moderne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellModerne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodell
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#Typed? Dynamic? Both! Cross-platform DSLs in C#
Typed? Dynamic? Both! Cross-platform DSLs in C#
 
RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP Framework
 
Arrays &amp; functions in php
Arrays &amp; functions in phpArrays &amp; functions in php
Arrays &amp; functions in php
 
Dlr
DlrDlr
Dlr
 

Similar to A Blueprint for Scala Microservices

Similar to A Blueprint for Scala Microservices (20)

Let's play with adf 3.0
Let's play with adf 3.0Let's play with adf 3.0
Let's play with adf 3.0
 
Diseño y Desarrollo de APIs
Diseño y Desarrollo de APIsDiseño y Desarrollo de APIs
Diseño y Desarrollo de APIs
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase Server
 
Node Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-ServicesNode Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-Services
 
Full Stack Scala
Full Stack ScalaFull Stack Scala
Full Stack Scala
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiectures
 
Serverless in-action
Serverless in-actionServerless in-action
Serverless in-action
 
Continuous Integration and Deployment Best Practices on AWS
Continuous Integration and Deployment Best Practices on AWSContinuous Integration and Deployment Best Practices on AWS
Continuous Integration and Deployment Best Practices on AWS
 
Arquitecturas de microservicios - Medianet Software
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet Software
 
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
 
Scala & sling
Scala & slingScala & sling
Scala & sling
 
Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)Prompt engineering for iOS developers (How LLMs and GenAI work)
Prompt engineering for iOS developers (How LLMs and GenAI work)
 
Cutting Edge Data Processing with PHP & XQuery
Cutting Edge Data Processing with PHP & XQueryCutting Edge Data Processing with PHP & XQuery
Cutting Edge Data Processing with PHP & XQuery
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Play framework
Play frameworkPlay framework
Play framework
 
Cloud2Car - Force.com and the Internet of Things
Cloud2Car - Force.com and the Internet of ThingsCloud2Car - Force.com and the Internet of Things
Cloud2Car - Force.com and the Internet of Things
 
Analytics Metrics delivery and ML Feature visualization: Evolution of Data Pl...
Analytics Metrics delivery and ML Feature visualization: Evolution of Data Pl...Analytics Metrics delivery and ML Feature visualization: Evolution of Data Pl...
Analytics Metrics delivery and ML Feature visualization: Evolution of Data Pl...
 

More from Federico Feroldi

Design and development of an Online Social Network crawler
Design and development of an Online Social Network crawlerDesign and development of an Online Social Network crawler
Design and development of an Online Social Network crawler
Federico Feroldi
 
Scaling web application in the Cloud
Scaling web application in the CloudScaling web application in the Cloud
Scaling web application in the Cloud
Federico Feroldi
 

More from Federico Feroldi (12)

Project IO - TS-Conf 2019
Project IO - TS-Conf 2019Project IO - TS-Conf 2019
Project IO - TS-Conf 2019
 
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
 
From 1 to infinity: how to scale your tech organization, build a great cultur...
From 1 to infinity: how to scale your tech organization, build a great cultur...From 1 to infinity: how to scale your tech organization, build a great cultur...
From 1 to infinity: how to scale your tech organization, build a great cultur...
 
From Startup to Exit in 18 months
From Startup to Exit in 18 monthsFrom Startup to Exit in 18 months
From Startup to Exit in 18 months
 
Design and development of an Online Social Network crawler
Design and development of an Online Social Network crawlerDesign and development of an Online Social Network crawler
Design and development of an Online Social Network crawler
 
Scaling web application in the Cloud
Scaling web application in the CloudScaling web application in the Cloud
Scaling web application in the Cloud
 
Innovate, optimize and profit with cloud computing
Innovate, optimize and profit with cloud computingInnovate, optimize and profit with cloud computing
Innovate, optimize and profit with cloud computing
 
Crawling the web for fun and profit
Crawling the web for fun and profitCrawling the web for fun and profit
Crawling the web for fun and profit
 
Cloudify your applications with Amazon Web Services
Cloudify your applications with Amazon Web ServicesCloudify your applications with Amazon Web Services
Cloudify your applications with Amazon Web Services
 
the Picmix experiment
the Picmix experimentthe Picmix experiment
the Picmix experiment
 
Cloudify - Scalability On Demand
Cloudify - Scalability On DemandCloudify - Scalability On Demand
Cloudify - Scalability On Demand
 
Federico Feroldi Php In Yahoo
Federico Feroldi Php In YahooFederico Feroldi Php In Yahoo
Federico Feroldi Php In Yahoo
 

Recently uploaded

Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Recently uploaded (20)

Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 

A Blueprint for Scala Microservices

  • 1. A BLUEPRINT FOR SCALA MICROSERVICES FEDERICO FEROLDI CTO / MEASURENCE.COM @CLOUDIFY
  • 2. OUR GOAL Empower developers with tools and process to own a service from development to production.
  • 3. Monolithic (1990s) SOA (2000s) Microservices (2010s)
  • 4. RATIONALE Small team: time is scarce Heavy use of open source Automate al the things Sane standards, easy override
  • 5.
  • 6. MAIN TOPICS Minimum Viable Service Deployment & Discovery Best practices
  • 7. MINIMUM VIABLE SERVICE Business Logic REST API Configuration Health / Monitoring Releasing / Versioning Packaging
  • 8. BUSINESS LOGIC = AKKA ACTORS Sum
 Service HTTP API SumOp SumRes “ask” pattern
  • 9. BUSINESS LOGIC = AKKA ACTORS object SumService { def props = Props(classOf[SumService]) ! case class SumOp(a: Int, b: Int) case class SumRes(result: Int) } ! class SumService extends Actor { import SumService._ ! def receive: Receive = { case SumOp(a, b) => sender() ! SumRes(a + b) } }
  • 10. REST API = SPRAY.IO Sum
 Service SPRAY API SumOp SumRes GET /v1/sum JSON
  • 11. REST API = SPRAY.IO case class SumApiResponse(result: Int) ! object SumProtocol extends DefaultJsonProtocol { implicit val sumApiResponseFormat = jsonFormat1(SumApiResponse) } ! class SumHttpServiceV1(services: Services) { import SumProtocol._ ! def route = path("v1" / "sum") { get { parameters('a.as[Int], 'b.as[Int]) { (a, b) => def future = (services.sumService ? SumOp(a, b)).mapTo[SumRes] onSuccess(future) { response => complete(SumApiResponse(response.result)) } } } } }
  • 12. API DOCS = SWAGGER SPRAY- SWAGGER GET / HTML/JSON docs
  • 13. API DOCS = SWAGGER @Api(value = “/v1/sum", description = "Sum numbers.") class SumHttpServiceV1(services: Services) { … }
  • 14. API DOCS = SWAGGER ! @ApiOperation(value = "Returns the sum”, httpMethod = “GET") ! @ApiImplicitParams(Array( new ApiImplicitParam( name="a", required=true, dataType="integer", paramType=“query" ), new ApiImplicitParam( name="b", required=true, dataType="integer", paramType=“query" ) )) ! @ApiResponses(Array( new ApiResponse( code=200, message="The sum", response=classOf[SumApiResponse] ) )) ! def route = path("v1" / "sum") { … }
  • 15. API DOCS = SWAGGER @ApiModel(description = "Result of the sum") case class SumApiResponse( @(ApiModelProperty @field)(value = "The sum of a and b") result: Int )
  • 16. REST API = SPRAY.IO + SWAGGER
  • 17. CONFIG = TYPESAFE CONFIG application.conf development.conf testing.conf staging.conf production.conf
  • 18. CONFIG = TYPESAFE CONFIG akka.loglevel = "INFO" ! metrics.carbon = "graphite.local:2003" ! acme { environment = "production" ! svc-calculator { hostname = “0.0.0.0” port = "9999" } } application.conf
  • 19. CONFIG = TYPESAFE CONFIG include "application" production.conf
  • 20. CONFIG = TYPESAFE CONFIG include "application"
 ! akka.loglevel = "DEBUG" metrics.carbon = "localhost:2003" ! acme { environment = "development" ! svc-calculator { hostname = "127.0.0.1" } } development.conf
  • 21. CONFIG = TYPESAFE CONFIG val config = ConfigFactory.defaultApplication() $ sbt -Dconfig.resource=development.conf run Loads application.conf by default Loads development.conf
  • 22. CONFIG = TYPESAFE CONFIG { mysql_username=${MYSQL_USERNAME} mysql_password=${MYSQL_PASSWORD} } PRO-TIP
 Don’t store passwords with source code! Instead make use ENV vars substitution and keep passwords in a safe place.
  • 23. HEALTH = SPRAY + HAPROXY SPRAY GET /ping Load Balancer Are you ok?
  • 24. HEALTH = SPRAY + HAPROXY def route = get { path("ping") { complete("pong") } }
  • 25. PERFMON = METRICS + GRAPHITE CODAHALE METRICS data points GRAPHITE CARBON
  • 26. PERF.MON. = METRICS + GRAPHITE object MetricsInstrumentation { val metricRegistry = new MetricRegistry() } ! trait Instrumented extends InstrumentedBuilder { val metricRegistry = MetricsInstrumentation.metricRegistry } ! class Actor extends Actor with Instrumented { val meter = metrics.meter("requests") ! def receive: Receive = { ! case Request => meter.mark() ! } }
  • 27. PERFMON = METRICS + GRAPHITE
  • 28. RELEASING = SBT-RELEASE SNAPSHOT/RELEASE artifacts Semantic versioning version.sbt + Git tags publishing of artifacts 100% customizable process interactive OR automated
  • 29. PACKAGING = ASSEMBLY + DOCKER JVM SERVICE (fat jar) HTTP Requests METRICS “Immutable” container Other Svc HTTP Reqs
  • 30. PACKAGING = SBT-ASSEMBLY + SBT-DOCKER docker <<= (docker dependsOn assembly) ! dockerfile in docker := { val artifact = (outputPath in assembly).value val artifactTargetPath = s"/app/${artifact.name}" new Dockerfile { from(“acme/javabase") expose(9999) add(artifact, artifactTargetPath) entryPoint("java", "-jar", artifactTargetPath) } } ! imageNames in docker := Seq( ImageName( namespace = Some(organization.value), repository = name.value, tag = Some("v" + version.value) ) )
  • 31. MINIMUM VIABLE SERVICE Business Logic = Akka REST API = Spray + Swagger Configuration = Typesafe Config Health / Monitoring = Metrics Packaging = Assembly & Docker
  • 32. DEPLOYMENT & DISCOVERY Continuous Integration Deployment Service Discovery
  • 33. CI/DEPLOY = JENKINS + SBT + ANSIBLE Git repo Jenkins Jobs + sbt Test Release Dockerize Deploy Commit Staging / Production Ansible
  • 35. { "id": "/svc-calculator", "container": { "type": "DOCKER", "docker": { "image": "docker.com/svc-calculator:1.0.0", "network": "BRIDGE", "portMappings": [{ "containerPort": 9999, "protocol": "tcp" }] } }, "env": {"JAVA_ARGS": “-Dconfig.resource=production"}, "cpus": 1, "mem": 1024, "instances": 2 } HOSTING = MESOS/MARATHON
  • 37. DISCOVERY = ? mesos1 /svc-calculator /svc-calculator mesos2 /web-app mesos3 HOST:PORT?
  • 38. DISCOVERY = BAMBOO + HAPROXY mesos1 /svc-calculator /svc-calculator mesos2 /web-app mesos3 BAMBOO + HAPROXY BAMBOO + HAPROXY BAMBOO + HAPROXY MARATHON http://localhost/svc-calculator :80 :30001:30002
  • 39. DEPLOYMENT & DISCOVERY CI = Jenkins + sbt Deploy = Ansible + Marathon Discovery = Bamboo + HAProxy
  • 40. FINAL TIPS DRY + keep team aligned Zero friction on new services
  • 41. DRY: CUSTOM SBT PLUGIN package com.acme.sbt.plugin import sbt._ import Keys._ object AcmePlugin extends AutoPlugin { lazy val acmeBuildSettings = Seq( scalacOptions ++= Seq( "-unchecked", "-deprecation", "-feature", "-Xlint", "-Ywarn-dead-code", "-target:jvm-1.7" ) ) } AcmePlugin.scala
  • 42. FINAL TIP: CUSTOM SBT PLUGIN import com.acme.sbt.plugin.AcmePlugin._ ! Seq(acmeBuildSettings:_*) ! // custom project settings build.sbt
  • 43. ZERO FRICTION: GITER8 TEMPLATES % g8 file://g8-svc-spray/ --name=svc-calculator -—servicePort=9999 ! Template applied in ./svc-calculator ! % ls svc-calculator build.sbt project src version.sbt
  • 44. Recap
  • 45.