Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Baking a Microservice PI(e)

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 188 Anzeige

Baking a Microservice PI(e)

Herunterladen, um offline zu lesen

Imagine you have several microservices exposing REST APIs. Imagine now that these microservices are spread all over and need to talk to each other. Imagine that you have a nice user interface interacting with these APIs where you can authenticate. And now, imagine that all this runs smoothly.

In this Deep Dive session, Roberto and Antonio will build, step by step, a full microservice architecture (using Java and different frameworks). This session will answer these questions:

How to build, document and deploy several microservices spread on different nodes (we use a Raspberry PI cluster because the Cloud is too expensive)
How to make those microservices talk to each other (Consul for registry and discovery)
How to scale up, down, and deal with network failures (Ribbon and Zuul to the rescue)
How to deal with high traffic (Hystrix, here you come)
How to monitor this distributed system (Dropwizard metrics with the ELK stack)
How to centralize configuration
How to authenticate and manage authorization with JWT (Tribestream Access Gateway)
How to have a centralized nice looking entry point (with Angular)

Imagine you have several microservices exposing REST APIs. Imagine now that these microservices are spread all over and need to talk to each other. Imagine that you have a nice user interface interacting with these APIs where you can authenticate. And now, imagine that all this runs smoothly.

In this Deep Dive session, Roberto and Antonio will build, step by step, a full microservice architecture (using Java and different frameworks). This session will answer these questions:

How to build, document and deploy several microservices spread on different nodes (we use a Raspberry PI cluster because the Cloud is too expensive)
How to make those microservices talk to each other (Consul for registry and discovery)
How to scale up, down, and deal with network failures (Ribbon and Zuul to the rescue)
How to deal with high traffic (Hystrix, here you come)
How to monitor this distributed system (Dropwizard metrics with the ELK stack)
How to centralize configuration
How to authenticate and manage authorization with JWT (Tribestream Access Gateway)
How to have a centralized nice looking entry point (with Angular)

Anzeige
Anzeige

Weitere Verwandte Inhalte

Ähnlich wie Baking a Microservice PI(e) (20)

Weitere von Roberto Cortez (15)

Anzeige

Aktuellste (20)

Baking a Microservice PI(e)

  1. 1. BAKING ABAKING A MICROSERVICE PI(E)MICROSERVICE PI(E) Antonio Goncalves and Roberto Cortez 1
  2. 2. INTRODUCTIONINTRODUCTION Welcome to Devoxx UK Hope it’s not too early…  … and that you are ready for a 3h session Thank you for joining us 2 . 1
  3. 3. ROBERTO CORTEZROBERTO CORTEZ
  4. 4. 2 . 2
  5. 5. ANTONIO GONCALVESANTONIO GONCALVES
  6. 6. 2 . 3
  7. 7. LISTEN TO OUR STORYLISTEN TO OUR STORY This talk is about our journey…  … through a Microservices architecture We’ll progressively build a MS architecture Going from problem, to solu on…  … to problem, to solu on…  … to problem And end‐up building a (basic) distributed applica on 2 . 4
  8. 8. ANYTIMEANYTIME
  9. 9. 2 . 5
  10. 10. DEMODEMO 2 . 6
  11. 11. ARCHITECTUREARCHITECTURE Microservices Monitoring Configura on Discovery Mechanism Load Balancing Circuit Breaker Gateway Security 2 . 7
  12. 12. HARDWAREHARDWARE Local machine 12 Raspberry PIs 6 Servers (Orange + Red) 2 Infrastructure (Purple) 4 Clients (Black) 1 Router 3 Switches Allows us to plug/unplug 2 . 8
  13. 13. SOFTWARESOFTWARE Java / Angular (TypeScript) Micro Profile TomEE / Wildfly Swarm NGinx / ELK Ne lix OSS Consul Tribestream Access Gateway 2 . 9
  14. 14. INFRASTRUCTUREINFRASTRUCTURE HypriotOS Ansible Docker Docker compose 2 . 10
  15. 15. DATABASEDATABASE Well…  … H2 in‐memory 2 . 11
  16. 16. THAT’S WHAT WE WILL BE BUILDINGTHAT’S WHAT WE WILL BE BUILDING DURING THESE 3 HOURSDURING THESE 3 HOURS 2 . 12
  17. 17. MICRO SERVICESMICRO SERVICES Have you heard about Microservices ? Who uses with Microservices ? Who plays with Microservices ? Who likes Microservices ? Who suffers with Microservices ? Do you know how big is a "micro" ? 3 . 1
  18. 18. WHAT DO PEOPLE MEAN BY MICROWHAT DO PEOPLE MEAN BY MICRO SERVICES ?SERVICES ? 3 . 2
  19. 19. PROMISE, WE WON’T TALK ABOUT PIZZAS !PROMISE, WE WON’T TALK ABOUT PIZZAS ! 3 . 3
  20. 20. SO, WHY MICROSERVICES ?SO, WHY MICROSERVICES ? Business focused (bounded context) Deliver new features quicker Smaller, more agile teams Scale services independently Address unpredictable loads Cloud 3 . 4
  21. 21. LET’S START SIMPLELET’S START SIMPLE We have one Number API Microservice We have one Angular client We use 2 PIs How do we deploy and make this run? 4 . 1
  22. 22. ARCHITECTUREARCHITECTURE 4 . 2
  23. 23. SEVERAL WAYS TO DEVELOPSEVERAL WAYS TO DEVELOP MICROSERVICESMICROSERVICES Dropwizard Lagom Vert.x Spring Boot MicroProfile 4 . 3
  24. 24. WHAT IS MICROPROFILE?WHAT IS MICROPROFILE? Comes from Java EE (Jakarta EE) JAX‐RS + CDI + JSON‐P Extensions Configura on Security Health Check Fault tolerance Metrics 4 . 4
  25. 25. NUMBER APINUMBER API JAX‐RS Endpoint Generates random numbers Just an HTTP GET on: /numbers/book Port 8084 Exposes a Swagger contract 4 . 5
  26. 26. NUMBER APINUMBER API @Path("numbers") @Produces(MediaType.TEXT_PLAIN) public class NumberResource { @GET @Path("book") public Response generateBookNumber() { log.info("Generating a book number"); return Response.ok("BK-" + Math.random()).build(); } } 4 . 6
  27. 27. RUNNING ON WILDFLY SWARMRUNNING ON WILDFLY SWARM Comes from Wildfly (RedHat) Open source Modular Small frac ons Executable Jar Now known as Thorntail 4 . 7
  28. 28. ANGULAR APPANGULAR APP Angular Bootstrap (because we are bad web designers) Port 8080 Invokes the number-api through HTTP Thanks to the Open API contract 4 . 8
  29. 29. OPEN APIOPEN API 4 . 9
  30. 30. OPEN APIOPEN API Open API Specifica on API documenta on What do you call? What are the parameters? What are the status code? Contract wri en in JSon (or Yaml) Swagger is one implementa on 4 . 10
  31. 31. SWAGGER ANNOTATIONSSWAGGER ANNOTATIONS @Path("numbers") @Produces(MediaType.TEXT_PLAIN) @Api(value = "numbers", description = "Generating all sorts of num public class NumberResource { @GET @Path("book") @ApiOperation(value = "Generates a book number.", response = public Response generateBookNumber() { log.info("Generating a book number"); return Response.ok("BK-" + Math.random()).build(); } } 4 . 11
  32. 32. SWAGGER CONTRACTSWAGGER CONTRACT { "swagger" : "2.0", "info" : { "description" : "Generates all sorts of numbers", "version" : "01", "title" : "Numbers API" }, "host" : "localhost:8084", "basePath" : "/number-api/api", "tags" : [ { "name" : "numbers", "description" : "Generating all sorts of numbers." } ], "schemes" : [ "http", "https" ], "paths" : { "/numbers/book" : { 4 . 12
  33. 33. SWAGGER ECOSYSTEMSWAGGER ECOSYSTEM 4 . 13
  34. 34. SWAGGER CODE GENSWAGGER CODE GEN Generates code from a Swagger contract Client stubs Several languages Including TypeScript for Angular $ swagger-codegen generate -i swagger.json -l typescript-angular2 -o src/app/shared 4 . 14
  35. 35. THE GENERATED TYPESCRIPT SERVICETHE GENERATED TYPESCRIPT SERVICE @Injectable() export class NumbersApi { protected basePath = 'http://localhost:8084/number-api/api'; public generateBookNumber(extraHttpRequestParams?: any): Obse return this.generateBookNumberWithHttpInfo(extraHttpReque .map((response: Response) => { if (response.status === 204) { return undefined; } else { return response.text() || ""; } }); } 4 . 15
  36. 36. CORSCORS Cross‐Origin Resource Sharing Specifica on ( ) Access across domain‐boundaries Number API and Angular app on different machines h ps://www.w3.org/TR/cors/ 4 . 16
  37. 37. SOLVING CORSSOLVING CORS Network configura on JAX‐RS ContainerResponseFilter Servlet Filter 4 . 17
  38. 38. CORS SERVLET FILTERCORS SERVLET FILTER @WebFilter(filterName = "corsFilter") public class CORSFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse HttpServletResponse resp = (HttpServletResponse) response resp.addHeader("Access-Control-Allow-Origin", "*"); resp.addHeader("Access-Control-Allow-Headers", "origin, c resp.addHeader("Access-Control-Allow-Credentials", "true" resp.addHeader("Access-Control-Allow-Methods", "GET, POST resp.addHeader("Access-Control-Max-Age", "1209600"); resp.addHeader("Access-Control-Expose-Headers", "origin, chain.doFilter(request, response); } } 4 . 18
  39. 39. CORS SERVLET FILTERCORS SERVLET FILTER <filter> <filter-name>CorsFilter</filter-name> <filter-class>org.bakingpie.commons.web.CORSFilter</filter-cl </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> 4 . 19
  40. 40. DEMO (LOCAL)DEMO (LOCAL) 4 . 20
  41. 41. DEPLOYDEPLOY We have a bunch of Raspberry PIs Running HypriotOS We package everything with Docker Use a Local Docker registry Push Docker images to the PIs with Ansible We could have used Docker Swarm too. 4 . 21
  42. 42. RASPBERRYRASPBERRY Raspberry v3 Use HypriotOS Minimal Debian‐based opera ng systems Op mized to run Docker on Raspberry PIs 4 . 22
  43. 43. DOCKERDOCKER Everything is packaged with Docker Number API Angular app Using Maven Fabric8 Plugin 4 . 23
  44. 44. DOCKER REGISTRYDOCKER REGISTRY We don’t use Docker Hub Too slow Use a Local Docker Registry Speed up deployment Running on port 5000 4 . 24
  45. 45. BUILDING DOCKER IMAGES WITH MAVENBUILDING DOCKER IMAGES WITH MAVEN $ mvn clean install docker:build docker:push 4 . 25
  46. 46. DOCKER REGISTRYDOCKER REGISTRY h p://docker‐registry:5000/v2/_catalog 4 . 26
  47. 47. ANSIBLEANSIBLE Automate tasks Ping all PIs Deploy docker images on all PIs Playbook List of tasks to do 4 . 27
  48. 48. PLAYBOOK FOR OUR SERVICEPLAYBOOK FOR OUR SERVICE --- - hosts: services strategy: free gather_facts: no remote_user: pirate become: yes become_method: sudo tasks: - name: Deploy Number API docker_container: name: number-api image: docker-registry:5000/baking/number-api:rpi state: started restart: yes pull: true 4 . 28
  49. 49. PINGING ALL THE PISPINGING ALL THE PIS $ ansible -i ansible/hosts -m ping all 4 . 29
  50. 50. DEPLOYING ON THE PISDEPLOYING ON THE PIS $ ansible-playbook ansible/deploy.yaml -i ansible/hosts 4 . 30
  51. 51. DEMO (PIS)DEMO (PIS) 4 . 31
  52. 52. WHAT’S NEXT ?WHAT’S NEXT ? Adding more Microservices Communica ng together 4 . 32
  53. 53. INVOKING MICRO-SERVICESINVOKING MICRO-SERVICES We have one Number API Microservice We need one Book API Microservice Book API invokes Number API We have one Angular client We use 3 PIs How do we deploy and make this run? 5 . 1
  54. 54. ARCHITECTUREARCHITECTURE 5 . 2
  55. 55. INVOKE MICROSERVICESINVOKE MICROSERVICES Microservices need to talk to each other Synchronously / Asynchronously REST / Messaging / Reac ve We’ll use only HTTP 5 . 3
  56. 56. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM By hand Apache HTTP Client JAX‐RS Client API Ne lix Feign 5 . 4
  57. 57. WHAT IS FEIGN?WHAT IS FEIGN? Feign is a Java to HTTP client Inspired by Retrofit, JAXRS‐2.0, and WebSocket Reducing the complexity of HTTP APIs calls Jersey or CXF Clients for REST or SOAP services 5 . 5
  58. 58. BOOK APIBOOK API JAX‐RS Endpoint CRUD opera ons on Book Book JPA en ty HTTP GET/POST/PUT/DELETE on: /books Port 8081 5 . 6
  59. 59. BOOK APIBOOK API @Path("books") @Api(value = "books", description = "Operations for Books.") public class BookResource { @Inject private NumbersApi numbersApi; @Inject private BookRepository bookRepository; @GET @Path("/{id : d+}") public Response findById(@PathParam("id") final Long id) { log.info("Getting the book " + id); return ofNullable(bookRepository.findById(id)) map(Response::ok) 5 . 7
  60. 60. RUNNING ON TOMEERUNNING ON TOMEE TomEE = Tomcat + Java EE Comes from Apache Open source Supported by Tomitribe Executable Fat‐Jar 5 . 8
  61. 61. NUMBER API SWAGGER CONTRACTNUMBER API SWAGGER CONTRACT { "swagger" : "2.0", "info" : { "description" : "Generates all sorts of numbers", "version" : "02", "title" : "Numbers API" }, "host" : "localhost:8084", "basePath" : "/number-api/api", "tags" : [ { "name" : "numbers", "description" : "Generating all sorts of numbers." } ], "schemes" : [ "http", "https" ], "paths" : { "/numbers/book" : { 5 . 9
  62. 62. SWAGGER CODE GEN FEIGN CLIENT STUBSWAGGER CODE GEN FEIGN CLIENT STUB $ swagger-codegen generate -i swagger.json -l java --library feig 5 . 10
  63. 63. THE GENERATED JAVA INTERFACETHE GENERATED JAVA INTERFACE @Generated(value = "io.swagger.codegen.languages.JavaClientCodege public interface NumbersApi extends ApiClient.Api { @RequestLine("GET /numbers/book") @Headers({"Content-Type: text/plain", "Accept: text/plain"}) String generateBookNumber(); } 5 . 11
  64. 64. THE GENERATED JAVA FEIGN CLIENTTHE GENERATED JAVA FEIGN CLIENT public class ApiClient { private String basePath = "http://localhost:8084/number-api/ap public NumbersApi buildNumberApiClient() { return Feign.builder() .logger(new Slf4jLogger(NumbersApi.class)) .logLevel(Logger.Level.FULL) .target(NumbersApi.class, basePath); } } 5 . 12
  65. 65. PRODUCING THE FEIGN CLIENTPRODUCING THE FEIGN CLIENT @ApplicationScoped public class NumbersApiProducer { @Produces @RequestScoped public NumbersApi createNumbersApi() { return new ApiClient().buildNumberApiClient(); } } 5 . 13
  66. 66. INVOKING THE NUMBER API WITH FEIGNINVOKING THE NUMBER API WITH FEIGN CLIENTCLIENT @Path("books") @Api(value = "books", description = "Operations for Books.") public class BookResource { @Inject private NumbersApi numbersApi; public Response create(@ApiParam(value = "Book to be created" String isbn = numbersApi.generateBookNumber(); book.setIsbn(isbn); 5 . 14
  67. 67. DEMO (LOCAL)DEMO (LOCAL) 5 . 15
  68. 68. DEMO (PIS)DEMO (PIS) 5 . 16
  69. 69. WHAT’S NEXT ?WHAT’S NEXT ? Monitoring our architecture Figure out what’s wrong 5 . 17
  70. 70. MONITORINGMONITORING We have several Microservices Running on several PIs Something goes wrong How do we monitor them? 6 . 1
  71. 71. ARCHITECTUREARCHITECTURE
  72. 72. 6 . 2
  73. 73. CENTRAL MONITORINGCENTRAL MONITORING Centralize logs Easier to vizualize Several nodes logging to a single place Allows to quickly see failures 6 . 3
  74. 74. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM Home made log aggrega on Syslog Fluentd Splunk Flume Logma c.io ELK 6 . 4
  75. 75. LOGSTASHLOGSTASH Centralize, Transform & Stash Your Data Data processing pipeline Ingests data from a mul tude of sources From Wildfly Swarm and TomEE logs Push to Elas csearch 6 . 5
  76. 76. ELASTICSEARCHELASTICSEARCH Search and analy cs engine Centrally stores the data From Logstash or other sources So you can search out logs Or any other informa on 6 . 6
  77. 77. KIBANAKIBANA Lets you visualize Elas csearch data Shape your data Interac ve visualiza ons 6 . 7
  78. 78. GELFGELF Graylog Extended Log Format Log format avoids classic plain syslog Docker log driver 6 . 8
  79. 79. LOGSTASH.CONFLOGSTASH.CONF input { gelf { } } filter { multiline { pattern => '^s' what => 'previous' stream_identity => "%{host}.%{container_id}" } } output { elasticsearch { 6 . 9
  80. 80. GELF ON DOCKER-COMPOSEGELF ON DOCKER-COMPOSE version: '2' services: angular-app: image: baking/angular:default container_name: angular ports: - 8080:80 depends_on: - book-api - number-api book-api: image: baking/book-api:default container_name: book-api ports: - 8081:8081 logging: 6 . 10
  81. 81. DEMODEMO
  82. 82. 6 . 11
  83. 83. WHAT’S NEXT ?WHAT’S NEXT ? Fixing IP addresses Adding configura on 6 . 12
  84. 84. CONFIGURINGCONFIGURING Book API has hard coded Number API address We have several environments (local, docker‐ compose, PIs) We need to configure the correct Hosts 7 . 1
  85. 85. ARCHITECTUREARCHITECTURE
  86. 86. 7 . 2
  87. 87. CODE CONFIGURATIONCODE CONFIGURATION Configure parts of the applica on Business configura on VAT rate Currency Technical configura on Different environment IP addresses / port numbers Timeout 7 . 3
  88. 88. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM Environment variable Property files XML, JSon, Yaml Database JNDI in Java EE Spring Config MicroProfile Configura on 7 . 4
  89. 89. MICROPROFILE CONFIGURATIONMICROPROFILE CONFIGURATION Config loca ons are called ConfigSources Same property defined in mul ple ConfigSources Some data sources may change dynamically Without the need to restart the applica on 7 . 5
  90. 90. BOOK API INVOKING NUMBER APIBOOK API INVOKING NUMBER API public class ApiClient { public interface Api { } private String baseHost = "http://localhost:8084"; private String basePath = "/number-api/api"; public NumbersApi buildNumberApiClient() { final Config config = ConfigProvider.getConfig(); config.getOptionalValue("NUMBER_API_HOST", String.class) .ifPresent(host -> baseHost = host); return Feign.builder() .logger(new Slf4jLogger(NumbersApi.class)) .logLevel(Logger.Level.FULL) target(NumbersApi class baseHost + basePath); 7 . 6
  91. 91. DOCKER-COMPOSE ENV VARIABLEDOCKER-COMPOSE ENV VARIABLE - name: Deploy Book API docker_container: name: book-api image: docker-registry:5000/baking/book-api:rpi state: started restart: yes pull: true ports: - "8081:8081" env: NUMBER_API_HOST: http://pi-grom-server-01:8084 7 . 7
  92. 92. DEMODEMO
  93. 93. 7 . 8
  94. 94. WHAT’S NEXT ?WHAT’S NEXT ? Moving our services around Adding a Registry 7 . 9
  95. 95. REGISTRINGREGISTRING We have two Microservices Book API and Number API Can be deployed on any PI How do they look for each other? 8 . 1
  96. 96. ARCHITECTUREARCHITECTURE
  97. 97. 8 . 2
  98. 98. SERVICE REGISTRATION AND DISCOVERYSERVICE REGISTRATION AND DISCOVERY Think of it as DNS resolu on A service registers with a name Another service looks for it by name Several instances of the same service 8 . 3
  99. 99. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM JNDI Apache Zookeeper Ne lix Eureka HashiCorp Consul 8 . 4
  100. 100. WHAT IS CONSUL?WHAT IS CONSUL? Solu on to connect and configure applica ons Distributed, highly available, and data center aware Dynamic Service Discovery Run me Configura on 8 . 5
  101. 101. REGISTER WITH CONSULREGISTER WITH CONSUL Consul consul = Consul.builder().withUrl(consulHost + ":" + consu agentClient = consul.agentClient(); final ImmutableRegistration registration = ImmutableRegistration.b .id("number-api") .name(NUMBER_API_NAME) .address(numberApiHost) .port(numberApiPort) .check(http(numberApiHost + ":" + numberApiPort + "/numb .build(); agentClient.register(registration); 8 . 6
  102. 102. HEALTH CHECKHEALTH CHECK @GET @Path("health") @ApiOperation(value = "Health of this REST endpoint", response = public Response health() { log.info("Alive and Kicking !!!"); return Response.ok().build(); } 8 . 7
  103. 103. DISCOVER WITH CONSULDISCOVER WITH CONSUL final Consul consul = Consul.builder().withUrl(consulHost + ":" + final HealthClient healthClient = consul.healthClient(); final List<ServiceHealth> nodes = healthClient.getHealthyServiceI final Service service = nodes.iterator().next().getService(); final String baseHost = service.getAddress() + ":" + service.getP return Feign.builder() .logger(new Slf4jLogger(NumbersApi.class)) .logLevel(Logger.Level.FULL) .target(NumbersApi.class, baseHost + basePath); 8 . 8
  104. 104. CONSUL UICONSUL UI
  105. 105. 8 . 9
  106. 106. DEMODEMO
  107. 107. 8 . 10
  108. 108. WHAT’S NEXT ?WHAT’S NEXT ? Handling failures Adding a Circuit Breaker 8 . 11
  109. 109. BREAK TIMEBREAK TIME
  110. 110. 9
  111. 111. CIRCUIT BREAKERCIRCUIT BREAKER We have two Microservices Book API calls Number API But Number API can fail How does Book API handle this failure? 10 . 1
  112. 112. ARCHITECTUREARCHITECTURE
  113. 113. 10 . 2
  114. 114. CIRCUIT BREAKERCIRCUIT BREAKER Services some mes collaborate when handling requests When invoked synchronously, there is always the possibility of being unavailable (or high latency) The failure of one service can poten ally cascade to others Client should invoke a remote service via a proxy If consecu ve failures, the circuit breaks 10 . 3
  115. 115. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM Build your own (CDI) JRugged MicroProfile Fault‐Tolerance Ne lix Hystrix 10 . 4
  116. 116. WHAT IS HYSTRIX?WHAT IS HYSTRIX?
  117. 117. Ne lix implementa on of Circuit Breaker Construct a HystrixCommand represents the request you are making Execute the HystrixCommand Is the Circuit Open? Yes: Hystrix will not execute the command and fallsback No: proceeds Integrates with Feign using Feign Hystrix 10 . 5
  118. 118. NUMBER API FAILINGNUMBER API FAILING @GET @Path("book") @ApiOperation(value = "Generates a book number.", response = Stri public Response generateBookNumber() throws InterruptedException final Config config = ConfigProvider.getConfig(); config.getOptionalValue("NUMBER_API_FAKE_TIMEOUT", Integer.cl log.info("Waiting for " + numberApiFakeTimeout + " seconds"); TimeUnit.SECONDS.sleep(numberApiFakeTimeout); return Response.ok("BK-" + Math.random()).build(); } 10 . 6
  119. 119. BOOK API FALLING BACKBOOK API FALLING BACK public NumbersApi buildNumberApiClient() { // Get host from Consul // This instance will be invoked if there are errors of any k NumbersApi fallback = () -> { return "FALLBACK ISBN"; }; return HystrixFeign.builder() .logger(new Slf4jLogger(NumbersApi.class)) .logLevel(Logger.Level.FULL) .target(NumbersApi.class, baseHost + basePath, fallba } 10 . 7
  120. 120. DEMODEMO
  121. 121. 10 . 8
  122. 122. WHAT’S NEXT ?WHAT’S NEXT ? Scaling the architecture Adding a Load Balancer 10 . 9
  123. 123. SCALINGSCALING We need to scale our Microservices Several Number API’s All registered in Consul Deployed on several PIs Which instance to choose from? 11 . 1
  124. 124. ARCHITECTUREARCHITECTURE 11 . 2
  125. 125. CLIENT-SIDE LOAD BALANCINGCLIENT-SIDE LOAD BALANCING Several instances of same service registered The client gets all the registered instances Then choose from among these instances Following certain criterias Capacity, round‐robin, cloud‐provider availability‐ zone awareness, mul ‐tenancy 11 . 3
  126. 126. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM Amazon Elas c Load Balancing (ELB) Apache H pd Nginx Ne lix Ribbon 11 . 4
  127. 127. WHAT IS RIBBON?WHAT IS RIBBON? Ne lix implementa on of Client‐Side Load Balancing Fault tolerant Mul ple protocols (HTTP, TCP, UDP) support Synchronous, asynchronous and reac ve model Caching and batching Integrates with Feign using Feing Ribbon 11 . 5
  128. 128. REGISTER SEVERAL NUMBER APIS INREGISTER SEVERAL NUMBER APIS IN CONSULCONSUL final ImmutableRegistration registration = ImmutableRegistration.builder() .id(UUID.randomUUID().toString()) .name(NUMBER_API_NAME) .address(numberApiHost) .port(numberApiPort) .check(http(numberApiHost + ":" + numberA .build(); agentClient.register(registration); 11 . 6
  129. 129. BOOK API REGISTERS THE RIBBON LOAD-BOOK API REGISTERS THE RIBBON LOAD- BALANCERBALANCER private void registerLoadBalancer(final Consul consul) { try { final DefaultClientConfigImpl clientConfig = getClientCon clientConfig.set(NFLoadBalancerClassName, "com.netflix.lo clientConfig.set(NFLoadBalancerRuleClassName, "com.netflix clientConfig.set(ServerListRefreshInterval, 10000); final DynamicServerListLoadBalancer dynamicServerListLoad (DynamicServerListLoadBalancer) registerNamedLoad dynamicServerListLoadBalancer.setServerListImpl(new Numbe dynamicServerListLoadBalancer.enableAndInitLearnNewServer } catch (final ClientException e) { e.printStackTrace(); } } 11 . 7
  130. 130. BOOK API GETS THE REGISTEREDBOOK API GETS THE REGISTERED INSTANCESINSTANCES final HealthClient healthClient = consul.healthClient(); final List<ServiceHealth> nodes = healthClient.getHealthyServiceInstances("CONSUL_NUMBER_API"). final List<Server> servers = nodes.stream() .map(serviceHealth -> new Serve URI.create(serviceHealth.ge serviceHealth.getService(). .collect(toList()); 11 . 8
  131. 131. BOOK API LOAD-BALANCES WITH FEIGNBOOK API LOAD-BALANCES WITH FEIGN return HystrixFeign.builder() .logger(new Logger.JavaLogger()) .logLevel(Logger.Level.FULL) .target(LoadBalancingTarget.create(NumbersApi.class, "http:// 11 . 9
  132. 132. DEMODEMO 11 . 10
  133. 133. WHAT’S NEXT ?WHAT’S NEXT ? Securing Microservices Adding a Security Token 11 . 11
  134. 134. SECURITYSECURITY Number API is a public API Book API HTTP GETs are public Book API HTTP POST / PUT / DELETE need authen ca on We need to centralize HTTP requests Filter the ones that need auth 12 . 1
  135. 135. ARCHITECTUREARCHITECTURE
  136. 136. 12 . 2
  137. 137. GATEWAYGATEWAY Centralize requests Think of it as a Proxy Expose the service endpoint in the Proxy Call the service through the Proxy Intercepts the request Apply Authen ca on and Authoriza on 12 . 3
  138. 138. SEVERAL TO CHOOSE FROMSEVERAL TO CHOOSE FROM Amazon API Gateway Apigee Gateway Tribestream Access Gateway 12 . 4
  139. 139. WHAT IS TRIBESTREAM ACCESS GATEWAY?WHAT IS TRIBESTREAM ACCESS GATEWAY? API Security For Microservices OAuth 2 JWT H p Signatures Route Microservices Load Balancer 12 . 5
  140. 140. JSON WEB TOKENJSON WEB TOKEN Lightweight token Contains « some » data (claims) Base64 Can be Encrypted Passed in the HTTP Header Sent at each request 12 . 6
  141. 141. A TOKENA TOKEN 12 . 7
  142. 142. A TOKENA TOKEN 12 . 8
  143. 143. A TOKENA TOKEN 12 . 9
  144. 144. ASKING FOR A TOKENASKING FOR A TOKEN @Injectable() export class AuthService { private _jwt: string; login(login: string, password: string): Observable<any> { var headers: Headers = new Headers(); headers.append('Content-Type', 'application/x-www-form-urlenc var body = `username=${login}&password=${password}`; return this.http .post(this.basePath, body, requestOptions) .map((response: Response) => { if (response.status !== 200) { return undefined; 12 . 10
  145. 145. PASSING THE TOKEN AROUNDPASSING THE TOKEN AROUND public _deleteWithHttpInfo(id: number, extraHttpRequestParams?: a const path = this.basePath + '/books/${id}'.replace('${' + 'id let queryParameters = new URLSearchParams(); var jwt = this.authService.jwt; if (jwt != null) { this.defaultHeaders.set('Authorization', jwt); } let requestOptions: RequestOptionsArgs = new RequestOptions({ method: RequestMethod.Delete, headers: headers, search: queryParameters, withCredentials:this.configuration.withCredentials }); return this http request(path requestOptions); 12 . 11
  146. 146. DEMODEMO
  147. 147. 12 . 12
  148. 148. WHAT’S NEXT ?WHAT’S NEXT ? Stressing the architecture Adding clients 12 . 13
  149. 149. HANDLING LOADHANDLING LOAD We have microservices all over They all depend on each other We have several clients We have several services Things (can) go wrong Things always go wrong ! 13 . 1
  150. 150. DEMODEMO 13 . 2
  151. 151. WHAT’S NEXT ?WHAT’S NEXT ? Much more But we don’t have  me 13 . 3
  152. 152. RECAPRECAP Let’s step back and do a recap The architecture evolved thourgh demos 14 . 1
  153. 153. ONE ANGULAR APP INVOKES A REMOTEONE ANGULAR APP INVOKES A REMOTE SERVICESERVICE 14 . 2
  154. 154. ONE SERVICE NEEDS TO TALK TO ANOTHERONE SERVICE NEEDS TO TALK TO ANOTHER ONEONE 14 . 3
  155. 155. WE DON’T SEE ANYTHING SO WE ADDWE DON’T SEE ANYTHING SO WE ADD MONITORINGMONITORING
  156. 156. 14 . 4
  157. 157. WE NEED TO CONFIGURE DIFFERENTWE NEED TO CONFIGURE DIFFERENT ENVIRONMENTSENVIRONMENTS
  158. 158. 14 . 5
  159. 159. TO AVOID HARD CODED IP ADDRESSES, WETO AVOID HARD CODED IP ADDRESSES, WE INTRODUCE A REGISTRYINTRODUCE A REGISTRY
  160. 160. 14 . 6
  161. 161. TO AVOID FAILURE, WE INTRODUCE ATO AVOID FAILURE, WE INTRODUCE A CIRCUIT BREAKERCIRCUIT BREAKER
  162. 162. 14 . 7
  163. 163. TO SCALE WE ADD MORE INSTANCES ANDTO SCALE WE ADD MORE INSTANCES AND NEED A CLIENT LOAD-BALANCERNEED A CLIENT LOAD-BALANCER
  164. 164. 14 . 8
  165. 165. WE NEED SECURITYWE NEED SECURITY
  166. 166. 14 . 9
  167. 167. WE NEED TO HANDLE LOADWE NEED TO HANDLE LOAD 14 . 10
  168. 168. WE USED MANY MICRO-SERVICE DESIGNWE USED MANY MICRO-SERVICE DESIGN PATTERNSPATTERNS 14 . 11
  169. 169. BUT THERE ARE MOREBUT THERE ARE MORE
  170. 170. 14 . 12
  171. 171. CONCLUSIONCONCLUSION 15 . 1
  172. 172. LESSONS LEARNTLESSONS LEARNT Micro Services are hard Micro Services are bloody hard Need to integrate with a lot of infrastucture Run in different environments (local, docker, pi) The more technologies the harder The more languages the harder The more versions the harder 15 . 2
  173. 173. AND…AND… We didn’t have databases We didn’t have a complex business logic We didn’t have a complex network We didn’t duplicate and load balance the registry We didn’t use asynchronous events We didn’t do integra on tes ng We didn’t do tracing (Zipkin) We didn’t do rate limit on our APIs 15 . 3
  174. 174. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 4
  175. 175. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 5
  176. 176. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 6
  177. 177. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 7
  178. 178. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 8
  179. 179. WHAT DO THE OTHERS THINK?WHAT DO THE OTHERS THINK? 15 . 9
  180. 180. ADVANTAGESADVANTAGES Deliver new features quicker Smaller, more agile teams Deliver business features as services Scale services independently Address unpredictable loads Cloud 15 . 10
  181. 181. BUT REMEMBERBUT REMEMBER Use this type of architecture If you need it Because it brings you advantages Not because the others are doing it 15 . 11
  182. 182. THANK YOUTHANK YOU
  183. 183. 15 . 12
  184. 184. THANKS FOR THE PIS !THANKS FOR THE PIS ! 15 . 13
  185. 185. VOXXED DAYS MICROSERVICESVOXXED DAYS MICROSERVICES 15 . 14
  186. 186. Q & AQ & A
  187. 187. 15 . 15
  188. 188. KEEPING IN TOUCHKEEPING IN TOUCH Antonio Goncalves  Roberto Cortez  @agoncal @radcortez h ps://github.com/agoncal/baking‐microservice‐pie 15 . 16

×