Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Microservices - are your frameworks ready?

Microservices - are your frameworks ready?

Slides for our talk at #microXchg, Berlin. More info available at https://www.innoq.com/en/talks/2015/02/microservices-jvm-applications-talk/

Alexander Heusingfeld

February 13, 2015
Tweet

More Decks by Alexander Heusingfeld

Other Decks in Technology

Transcript

  1. Challenges > distributed configuration > service registration & discovery >

    resilience > fast, automated deployment > metrics
  2. Dropwizard libraries > Jetty > Jersey > Metrics > Jackson

    > Guava > Logback > Hibernate Validator > Apache Http Client > JDBI > Liquibase > Freemarker & Mustache > Joda
  3. Spring Boot > convention over configuration approach > Java, Groovy

    or Scala > self-contained jar or war > tackles dependency-hell via pre-packaging
  4. Spring Cloud > umbrella project for cloud connectors > On

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

    top of Spring Boot > config server for distributed configuration > annotations for service-discovery & resilience
  6. Play - Typesafe Config > Config Library used by akka,

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

    play and other > HOCON - JSON Data Model + syntactic sugar > override via system property
  8. 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
  9. Spring Boot @ComponentScan
 @EnableAutoConfiguration
 public class OrderApp {
 
 public

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

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


    @EnableAutoConfiguration
 public class OrderApp {
 
 public static void main(String[] args) {
 SpringApplication.run(OrderApp.class, args);
 }
 }
  12. 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);
 }
 }
  13. 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);
 }
 }
  14. Dropwizard public Product resolveProduct(String url) { Product product = client.resource(url)

    .accept(MediaType.APPLICATION_JSON).get(Product.class); return product; }
  15. Service Service Discovery Client Service Registry 2. discover service instances

    3. call service instance Service Service 1. register service ("myself") & heartbeat
  16. Spring Cloud @ComponentScan
 @EnableAutoConfiguration
 @EnableDiscoveryClient
 public class OrdersApp {
 


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


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


    public static void main(String[] args) {
 SpringApplication.run(OrdersApp.class, args);
 }
 }
  19. 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.
  20. > Provides Command-oriented Integration of Services > Introduces Circuit Breaker,

    Bulkheads and Isolation > Decouples from Service-dependencies > Provides metrics-facility to protect from failures
  21. Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand<Product> { @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 } }
  22. Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand<Product> { @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 } }
  23. Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand<Product> { @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 } }
  24. Hystrix & Dropwizard public class CommandInDropwizard extends TenacityCommand<Product> { @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 } }
  25. Spring Cloud Hystrix @HystrixCommand(fallbackMethod = “fallbackProduct") private Pair<String, ResponseEntity<Product>> resolveProduct(String

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

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

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

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

    productUri) {
 final RestTemplate restTemplate = new RestTemplate();
 return new Pair(productUri, restTemplate.getForEntity(productUri, Product.class));
 } private Pair<String, ResponseEntity<Product>> fallbackProduct(String productUri) {
 final Product product = new Product(productUri, null, BigDecimal.ZERO);
 final ResponseEntity<Product> response = new ResponseEntity<Product>(product, PARTIAL_CONTENT); return new Pair(productUri, response);
 } method reference!
  30. 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() } }
  31. 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() } }
  32. 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() } }
  33. 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() } }
  34. 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() } }
  35. Dropwizard > “Metrics” Integrated with Dropwizard > @Timed on Resources

    > HTTP Client is already instrumented > JVM Data
  36. "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" }
  37. Dropwizard Metrics > Exposed over HTTP (as Json) > Exposed

    as jmx > Others available: stdout, csv, slf4j, ganglia, graphite
  38. 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
  39. { "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
  40. Modularize into independent, self-contained systems Separate micro and macro architectures

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

    Strike a balance between control and decentralization MicroServices aren’t micro! Summary
  42. 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
  43. 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