Building a microservices architecture means making a lot of decisions, about tools, about frameworks. In this talk I share the decisions that we made at Measurence during our journey for building a microservices architecture based on Scala technologies.
We're going to talk about Spray, Akka, Swagger, Sbt, Docker, Jenkins, Mesos and Marathon.
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) {
…
}
15. API DOCS = SWAGGER
@ApiModel(description = "Result of the sum")
case class SumApiResponse(
@(ApiModelProperty @field)(value = "The sum of a and b")
result: Int
)
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")
}
}