Slide 1

Slide 1 text

Microservices Are your Frameworks ready? Martin Eigenbrodt | [email protected] Alexander Heusingfeld | [email protected]

Slide 2

Slide 2 text

Microservices?

Slide 3

Slide 3 text

Levels of Architecture

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Domain architecture

Slide 6

Slide 6 text

Macro (technical) architecture Domain architecture

Slide 7

Slide 7 text

JRuby C# Scala Groovy
 Java Clojure

Slide 8

Slide 8 text

RDBMS NoSQL K/V RDBMS RDBMS/DWH NoSQL
 DocDB

Slide 9

Slide 9 text

RDBMS NoSQL K/V RDBMS RDBMS/DWH NoSQL
 DocDB Micro architecture

Slide 10

Slide 10 text

Challenges

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Challenges

Slide 13

Slide 13 text

Challenges > many services to take care of

Slide 14

Slide 14 text

Challenges > many services to take care of > distributed system

Slide 15

Slide 15 text

Challenges > distributed configuration > service registration & discovery > resilience > fast, automated deployment > metrics

Slide 16

Slide 16 text

Macro- vs. Micro Architecture

Slide 17

Slide 17 text

Frameworks

Slide 18

Slide 18 text

Dropwizard

Slide 19

Slide 19 text

Dropwizard > Glue Code for well known libraries > Java

Slide 20

Slide 20 text

Dropwizard libraries

Slide 21

Slide 21 text

Dropwizard libraries > Jetty

Slide 22

Slide 22 text

Dropwizard libraries > Jetty > Jersey

Slide 23

Slide 23 text

Dropwizard libraries > Jetty > Jersey > Metrics

Slide 24

Slide 24 text

Dropwizard libraries > Jetty > Jersey > Metrics > Jackson > Guava > Logback > Hibernate Validator > Apache Http Client > JDBI > Liquibase > Freemarker & Mustache > Joda

Slide 25

Slide 25 text

Spring Boot and Spring Cloud

Slide 26

Slide 26 text

Spring Boot

Slide 27

Slide 27 text

Spring Boot > convention over configuration approach

Slide 28

Slide 28 text

Spring Boot > convention over configuration approach > Java, Groovy or Scala

Slide 29

Slide 29 text

Spring Boot > convention over configuration approach > Java, Groovy or Scala > self-contained jar or war

Slide 30

Slide 30 text

Spring Boot > convention over configuration approach > Java, Groovy or Scala > self-contained jar or war > tackles dependency-hell via pre-packaging

Slide 31

Slide 31 text

Spring Cloud

Slide 32

Slide 32 text

Spring Cloud > umbrella project for cloud connectors

Slide 33

Slide 33 text

Spring Cloud > umbrella project for cloud connectors > On top of Spring Boot

Slide 34

Slide 34 text

Spring Cloud > umbrella project for cloud connectors > On top of Spring Boot > config server for distributed configuration

Slide 35

Slide 35 text

Spring Cloud > umbrella project for cloud connectors > On top of Spring Boot > config server for distributed configuration > annotations for service-discovery & resilience

Slide 36

Slide 36 text

Play 2

Slide 37

Slide 37 text

Play 2 > Java or Scala > based on Akka > strong async support

Slide 38

Slide 38 text

Configuration

Slide 39

Slide 39 text

Play - Typesafe Config

Slide 40

Slide 40 text

Play - Typesafe Config > Config Library used by akka, play and other

Slide 41

Slide 41 text

Play - Typesafe Config > Config Library used by akka, play and other > HOCON - JSON Data Model + syntactic sugar

Slide 42

Slide 42 text

Play - Typesafe Config > Config Library used by akka, play and other > HOCON - JSON Data Model + syntactic sugar > override via system property

Slide 43

Slide 43 text

Play - Typesafe Config > Config Library used by akka, play and other > HOCON - JSON Data Model + syntactic sugar > override via system property > rich merge and include possibilities

Slide 44

Slide 44 text

Spring Boot @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }

Slide 45

Slide 45 text

Spring Boot @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }

Slide 46

Slide 46 text

Spring Boot > HTTP resource “/autoconfig” shows all properties @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }

Slide 47

Slide 47 text

Spring Boot > HTTP resource “/autoconfig” shows all properties > overwrite via application.properties or CLI parameter @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }

Slide 48

Slide 48 text

Spring Boot > HTTP resource “/autoconfig” shows all properties > overwrite via application.properties or CLI parameter > configuration in git? -> Check spring-cloud configserver @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }

Slide 49

Slide 49 text

Http Client

Slide 50

Slide 50 text

Dropwizard public Product resolveProduct(String url) { Product product = client.resource(url) .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; }

Slide 51

Slide 51 text

Spring Boot public Product resolveProduct(String url) { return restTemplate.getForEntity(url, Product.class);
 }

Slide 52

Slide 52 text

WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }.recover { case e => List() } Play

Slide 53

Slide 53 text

Service Discovery

Slide 54

Slide 54 text

Service Service Discovery Client Service Registry 2. discover service instances 3. call service instance Service Service 1. register service ("myself") & heartbeat

Slide 55

Slide 55 text

Spring Cloud @ComponentScan
 @EnableAutoConfiguration
 @EnableDiscoveryClient
 public class OrdersApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrdersApp.class, args);
 }
 }

Slide 56

Slide 56 text

Spring Cloud @ComponentScan
 @EnableAutoConfiguration
 @EnableDiscoveryClient
 public class OrdersApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrdersApp.class, args);
 }
 }

Slide 57

Slide 57 text

Spring Cloud @ComponentScan
 @EnableAutoConfiguration
 @EnableDiscoveryClient
 public class OrdersApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrdersApp.class, args);
 }
 }

Slide 58

Slide 58 text

Service Discovery with Sidecar Sidecar Client Service Registry Sidecar Service 2. register service ("myself") & heartbeat 4. discover service instances 5. call service instance 1. health check 3.

Slide 59

Slide 59 text

Resilience

Slide 60

Slide 60 text

Resilience > isolate Failure > apply graceful degradation > be responsive in case of failure

Slide 61

Slide 61 text

Request service http://en.wikipedia.org/wiki/Circuit_breaker closed

Slide 62

Slide 62 text

Request service http://en.wikipedia.org/wiki/Circuit_breaker closed Request service open

Slide 63

Slide 63 text

Request service http://en.wikipedia.org/wiki/Circuit_breaker closed Request service open Request service half- open

Slide 64

Slide 64 text

> Provides Command-oriented Integration of Services > Introduces Circuit Breaker, Bulkheads and Isolation > Decouples from Service-dependencies > Provides metrics-facility to protect from failures

Slide 65

Slide 65 text

Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand { @Override protected Product run() throws Exception { Product product = client.resource(url) .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; } protected Product getFallback() { return FALLBACK_PRODUCT } }

Slide 66

Slide 66 text

Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand { @Override protected Product run() throws Exception { Product product = client.resource(url) .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; } protected Product getFallback() { return FALLBACK_PRODUCT } }

Slide 67

Slide 67 text

Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand { @Override protected Product run() throws Exception { Product product = client.resource(url) .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; } protected Product getFallback() { return FALLBACK_PRODUCT } }

Slide 68

Slide 68 text

Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand { @Override protected Product run() throws Exception { Product product = client.resource(url) .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; } protected Product getFallback() { return FALLBACK_PRODUCT } }

Slide 69

Slide 69 text

ResolveProductCommand command = new ResolveProductCommand(client, url); Product product = command.execute(); Hystrix & Dropwizard

Slide 70

Slide 70 text

Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair> resolveProduct(String productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity response = new ResponseEntity(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 }

Slide 71

Slide 71 text

Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair> resolveProduct(String productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity response = new ResponseEntity(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 } auto-wrapped with command!

Slide 72

Slide 72 text

Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair> resolveProduct(String productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity response = new ResponseEntity(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 }

Slide 73

Slide 73 text

Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair> resolveProduct(String productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity response = new ResponseEntity(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 }

Slide 74

Slide 74 text

Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair> resolveProduct(String productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity response = new ResponseEntity(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 } method reference!

Slide 75

Slide 75 text

Play - Circuit Breaker val apiUrl = "..." val breaker = CircuitBreaker(Akka.system().scheduler, maxFailures = 5, callTimeout = 2.seconds, resetTimeout = 1.minute) def getBestseller : Future[List[Bestseller]] = { breaker.withCircuitBreaker( WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }).recover { case e => List() } }

Slide 76

Slide 76 text

Play - Circuit Breaker val apiUrl = "..." val breaker = CircuitBreaker(Akka.system().scheduler, maxFailures = 5, callTimeout = 2.seconds, resetTimeout = 1.minute) def getBestseller : Future[List[Bestseller]] = { breaker.withCircuitBreaker( WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }).recover { case e => List() } }

Slide 77

Slide 77 text

Play - Circuit Breaker val apiUrl = "..." val breaker = CircuitBreaker(Akka.system().scheduler, maxFailures = 5, callTimeout = 2.seconds, resetTimeout = 1.minute) def getBestseller : Future[List[Bestseller]] = { breaker.withCircuitBreaker( WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }).recover { case e => List() } }

Slide 78

Slide 78 text

Play - Circuit Breaker val apiUrl = "..." val breaker = CircuitBreaker(Akka.system().scheduler, maxFailures = 5, callTimeout = 2.seconds, resetTimeout = 1.minute) def getBestseller : Future[List[Bestseller]] = { breaker.withCircuitBreaker( WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }).recover { case e => List() } }

Slide 79

Slide 79 text

Play - Circuit Breaker val apiUrl = "..." val breaker = CircuitBreaker(Akka.system().scheduler, maxFailures = 5, callTimeout = 2.seconds, resetTimeout = 1.minute) def getBestseller : Future[List[Bestseller]] = { breaker.withCircuitBreaker( WS.url(apiUrl).get.map { response => response.json.as[List[Bestseller]] }).recover { case e => List() } }

Slide 80

Slide 80 text

Deployment

Slide 81

Slide 81 text

Spring Boot - Packaging ./gradlew build ./gradlew distZip

Slide 82

Slide 82 text

Spring Boot - Packaging ./gradlew build ./gradlew distZip executable JAR

Slide 83

Slide 83 text

Spring Boot - Packaging ./gradlew build ./gradlew distZip ZIP + shell-script executable JAR

Slide 84

Slide 84 text

Play - Packaging sbt dist sbt debian:packageBin sbt rpm:packageBin

Slide 85

Slide 85 text

Metrics

Slide 86

Slide 86 text

Dropwizard > “Metrics” Integrated with Dropwizard > @Timed on Resources > HTTP Client is already instrumented > JVM Data

Slide 87

Slide 87 text

"org.apache.http.client.HttpClient.cart.get-requests": { "count": 11, "max": 0.062107, "mean": 0.013355909090909092, "min": 0.005750000000000001, "p50": 0.009454, "p75": 0.010427, "p95": 0.062107, "p98": 0.062107, "p99": 0.062107, "p999": 0.062107, "stddev": 0.016285873488729705, "m15_rate": 0, "m1_rate": 0, "m5_rate": 0, "mean_rate": 2.9714422786532126, "duration_units": "seconds", "rate_units": "calls/second" } "cart.resources.ShoppingCartResource.shoppingCart": { "count": 22, "max": 0.136162, "mean": 0.01208109090909091, "min": 0.00093, "p50": 0.008174500000000001, "p75": 0.011782250000000001, "p95": 0.11783499999999976, "p98": 0.136162, "p99": 0.136162, "p999": 0.136162, "stddev": 0.02813530239821426, "m15_rate": 1.8524577712890011, "m1_rate": 0.18057796798879996, "m5_rate": 1.315746847992022, "mean_rate": 0.133050618509084, "duration_units": "seconds", "rate_units": "calls/second" }

Slide 88

Slide 88 text

Dropwizard Metrics > Exposed over HTTP (as Json) > Exposed as jmx > Others available: stdout, csv, slf4j, ganglia, graphite

Slide 89

Slide 89 text

Spring Boot Metrics > Prepackaged Spring Boot starter module > enables HTTP resources for metrics > configurable via application.properties http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready

Slide 90

Slide 90 text

{ "counter.checkouts.withproducts.3": 4, ... } counterService.increment("checkouts.withproducts." + productUris.size());
 GET /metrics HTTP/1.1 Using a counter metric in your Java code… …will display it in the /metrics JSON Spring Boot Metrics

Slide 91

Slide 91 text

Summary

Slide 92

Slide 92 text

Modularize into independent, self-contained systems Summary

Slide 93

Slide 93 text

Modularize into independent, self-contained systems Separate micro and macro architectures Summary

Slide 94

Slide 94 text

Modularize into independent, self-contained systems Separate micro and macro architectures Strike a balance between control and decentralization Summary

Slide 95

Slide 95 text

Modularize into independent, self-contained systems Separate micro and macro architectures Strike a balance between control and decentralization MicroServices aren’t micro! Summary

Slide 96

Slide 96 text

Modularize into independent, self-contained systems Separate micro and macro architectures Strike a balance between control and decentralization MicroServices aren’t micro! frameworks can’t solve all your problems Summary

Slide 97

Slide 97 text

Martin Eigenbrodt | @eigenbrodtm [email protected] Alexander Heusingfeld | @goldstift [email protected] innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am Rhein Germany Phone: +49 2173 3366-0 innoQ Schweiz GmbH Gewerbestr. 11 CH-6330 Cham Switzerland Phone: +41 41 743 0116 www.innoq.com Ohlauer Straße 43 10999 Berlin Germany Phone: +49 2173 3366-0 Robert-Bosch-Straße 7 64293 Darmstadt Germany Phone: +49 2173 3366-0 Radlkoferstraße 2 D-81373 München Germany Telefon +49 (0) 89 741185-270 Thank you! Questions? Comments? https://www.innoq.com/en/talks/2015/02/microservices-jvm-applications-talk