GithubHelp home page GithubHelp logo

curioustauseef / workshops-microservices-patterns Goto Github PK

View Code? Open in Web Editor NEW

This project forked from 42patterns/workshops-microservices-patterns

0.0 0.0 0.0 2.67 MB

Code samples for microservices patterns workshop

Java 59.83% HTML 2.85% CSS 11.67% JavaScript 25.24% Dockerfile 0.41%

workshops-microservices-patterns's Introduction

Distilling microservices patterns

Welcome to microservices patterns workshop. This workshop is intended to guide you through multiple microservice patterns, based on modularising a simplistic TODO application™.

Before we start

For sanity, when setting up a new task, start with mvn install with the parent pom.xml

To pre-download half of internet of Maven dependencies, you can go to training dependencies repository and follow the instructions. This will force download most (or all) dependencies used in the exercises.

Splitting up monoliths

tasks external ui

There is a TODO application: two independent services talking over HTTP (REST): todo-app and todo-app-ui

Context

The todo-app™ is a simple TODO application built in a old-school way: EJB components with servlets and JSF sitting on a single application server (wildfly). You can run the server with mvn wildfly:run and play a bit with the app by browsing to http://localhost:8080/index.jsf

However, as the business evolves - the UI is planned to be replaced by a modern, JavaScript based frontend application. As a part of refactoring initiative a new front-end has be designed and implemented: todo-ui, which is a Single Page Application, with an idea to communicate with the old application through a set of REST-like HTTP calls. The front end can be run independently by running npm start from todo-app-ui folder.

Task #0

Make it run!

If you navigate to http://localhost:8080 you can see the new UI in place. It’s deployed as independent a resource-jar file (Servlet 3.0) and it mock the real todo list behaviour. Whenever new item is added, it’s not persisted and disappears upon refresh.

However, first step is done: legacy application is combined with the new UI.

Task #1

Based on the defined interfaces, extend the existing application and provide a set of required API.

What additional changes needs to be done to allow application to application communication, when deployed separately? How can the application still be developed separately but deployed as a monolith?

Important
Implement the missing methods in the TodoResource class for the test to successfully pass.

How to run

The Pact is prepared by the JavaScript application. It states the expectation; what resources are expected from the provider.

It’s expressed as a Pact contract created in the test phase. The pact is than passed over to provider.

The pact file is located in todo-app/src/test/resources. An Arquillian test is built to validate the contract (TodoResourceProviderIT)

The test is run as a part of Intergration Testing phase which can be triggered with Maven’s mvn clean verify. It spins wildfly instance on pre-integration phase and stops it during post-integration phase.

Tip

The missing UI artifact com.example.patterns:todo-app-ui can be buld with mvn clean install in the todo-app-ui folder. This builds the whole static html application outside the maven target folder (in /tmp) - not to download all node modules on every exercise.

The build can be also run manually:

  • npm install - download dependencies

  • npm run build - trigger browserify and copy static (html, css) files

  • mvn clean install -Plocal - create static resources jar file

Important
The automatic build can be problematic on Windows (as most nodejs builds) but manual path is validated and working at least on Windows7.

TIP

If you experience some nodejs issues while building the frontend application you can install it directly from file mvn install:install-file -DgroupId=com.example.patterns -DartifactId=todo-app-ui -Dversion=1.0-SNAPSHOT -Dpackaging=jar -Dfile=todo-app-ui-1.0-SNAPSHOT.jar when in folder todo-app-ui

Afterwards, you can build the whole project without todo-app-ui with maven mvn clean install -pl !todo-app-ui

== API Gateway

tasks banner service

The TODO application™ become a great success, so that business wants to monetize the business by adding commercial banners on the top of the page.

=== Context

A new service has been added to the pool: a todo page displays a commercial banner provider directly from a service owned by the marketing department. The functionality is provided by a banners-service service, which is a full stack microservice - provides a random image, ready to include directly onto the todo page.

=== Task #1

Introduce an API gateway - a new component which hosts the UI and routes appropriate requests to services:

Important
Implement the missing TODOs in GatewayApp.java in the api-gateway project

=== How to run

To start the gateway run mvn spring-boot:run from api-gateway project. The gateway listens on the port 9999.

Banner service is a simple Spark Java micro framework. Run it from banners-service folder with mvn package exec:java command.

Tip
Remember that UI has changed (new banners) so UI needs to be rebuilt. If you have problems with building the UI directly with nodejs, install the jar file again (mvn install:install-file -DgroupId=com.example.patterns -DartifactId=todo-app-ui -Dversion=1.0-SNAPSHOT -Dpackaging=jar -Dfile=todo-app-ui-1.0-SNAPSHOT.jar) from todo-app-ui folder.

== Circuit breaking

tasks banner service

The quality of the banners-service is below expectations and it fail frequently.

=== Context

The ads providing services goes offline on regular basis. From TODO application™ perspective this is not acceptable, as if results in a broken image icon on the front page. To mitigate that, a default-banner.png has been provided to substitute the missing image.

=== Task #2

In the api-gateway implementation provide a fallback for a missing image (either on exception of with a dedicated tool like Hystrix or Failsafe).

Tip
As the service provides an image directly, same "data structure" must be provided by the fallback mechanism (byte[])
Tip
Failsafe documentation (https://github.com/jhalterman/failsafe) is a nice guide for different implemantation flavours.
Important
Provide a default fallback option in the GatewayApp#getBanners() method.

=== Task #3

While writing your own API Gateway might be a good idea, sometimes it becomes a bit cumbersome. There are multiple out of the box libraries implementing this pattern (like Neflix Zuul).

Zuul provides configurable tooling for building a reverse proxy, especially with some Spring Cloud conventions. Additionally, it comes with circuit breaking and load balancing mechanism provided by another Netflix libraries: Hystrix and Ribbon (we will look deeper into these later on).

Important
Provide a default fallback mechanism (similar to the in-house built api-gateway from the previous task. Please use ZuulFallbackProvider interface and provide it as a standard spring bean.

=== How to run

Run mvn spring-boot:run from api-gateway-zuul project. The gateway listens on the port 9999.

== Load balancing

tasks profanity

No profane words should be allowed in the todo-app; everything matching profanity checks should be filtered-out.

=== Context

Additional service (profnity-filter) has been introduced in the application landscape. It handles POST or PUT calls, checks profanity with an external profanity-check-service, amends the title (if required) and passes the request to the legacy TODO Application™.

=== Task #4

For performance reasons more than one banners-service service can be started multiple times and the load should be evenly distributed between all services. The banners-service service listens on port 8081 by default, but it can be configured with -DPORT {port number} parameter (to avoid ports collision).

Start multiple instances of banners service and distribute the workload evenly between all available instances of banners-service.

Tip
A quickstart reference manual from Spring is available here: https://spring.io/guides/gs/client-side-load-balancing/
Important
In the api-gateway application, use the Spring based RibbonClient (from spring-cloud-starter-ribbon) to easily load balance between instances. The static list of servers can be added in the application configuration file.

=== Task #5

As our in-house implemented api-gateway is getting a bit more complex, maybe it’s a good moment to have a look deeper look into out of the box tooling. In the api-gateway-zuul provide a static list of servers for each service (in the application.properties file - in a similar fashion it was done for api-gateway). Additionally, add an appropriate filter configuration (implementing ZuulFilter), to check POST or PUT requests and forward them to profanity-filter instead of the original legacy TODO Application™.

Important
Configure Netflix Zuul to evenly distribute load between all service instances.

== Service discovery

tasks discovery

The number of hardcode service locations (hostnames and/or ports) is unacceptably low: it make the deployments static and fragile. What is more, some ports are assigned randomly which makes the situation additionally complex.

=== Context

Eureka is a REST based service that is used for the purpose of load balancing and failover of middle-tier servers. When the number of services and instances increases greatly, it’s impossible to manage embedded configuration. Eureka inverses this process, allowing service registrations as well as pulling the latest service location directly from store.

In the our microservices environment the profranity-filter and todo-app are already auto registered.

The profanity-filter combines both automatic configuration (with @EnableDiscoveryClient) and manual configuration of services which are external (thus - don’t register themselves). The latter is done through explicit @RibbonClient annotation.

Finally, both banners-service and todo-app are not a spring applications, therefor require additional steps to register with Eureka.

The todo-app did it through explicit call to Eureka HTTP service (see the DiscoveryClientConfig bean).

The banner-service registration is done with the Eureka Client.

Tip
Original Eureka Client example might be helpful to proceed: https://github.com/Netflix/eureka/tree/master/eureka-examples
Tip
Besides Eureka Client dependency com.netflix.eureka:eureka-client:1.6.2, add javax.inject:javax.inject:1 which is used for client’s dependency injection engine.
Tip
Eureka REST operations and description of client-server communication might be helpful for debugging and manual cancellation
Note
It takes time to propagate new instance within Eureka ecosystem; from instance registration to local load balancer (ribbon) cache. An detailed description (inluding configuration options) is available on github.

=== Task #6

To make the configuration consistent, introduce service discovery features in the rest of the services. api-gateway (or api-gateway-zuul) can leverage Spring Cloud autoconfiguration.

Tip
The Spring’s quickstart manual can give you heads up: https://spring.io/guides/gs/service-registration-and-discovery/
Important
Auto register the api-gateway through @EnableDiscoverClient annotation.

=== How to run

Run the discovery service through mvn spring-boot:run -f registry.

Tip
Lookup registered application at http://localhost:8761/eureka/apps

== Monitoring

=== Task #7

Include profanity-filter service in zipkin monitoring.

Tip
This is a spring-boot application, so adding appropriate spring-cloud dependency should do the job

=== Task #8

Include banners-service in zipkin monitoring. This is a non-spring project so OpenZipkin instrumentation library is recommended. There are dedicated libraries for different frameworks (like one for JAXRS - used in todo-app; lookup RestApplication class for inspiration).

Banners service is based on SparkJava so pickup the right instrumentation library from https://github.com/openzipkin/brave/tree/master/instrumentation and use accordingly.

=== Task #9

Calling external profanity-check-service is not explicitly logged with Zipkin annotation. However, you can create additional Span through API. Add span for calling external service and log appropriate 'Client Sent' and 'Client Received' events

Tip
Spring Sleuth documentation is quite comprehensive in that matter. https://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html#_span_lifecycle

=== How to run

Run Zipkin through mvn spring-boot:run -f zipkin

Tip
Zipkin UI runs by default at http://localhost:9411

== Security

tasks auth

Access to the application should be limited to users defined within a third-party authorisation service. Both username and password and token based authentication must be possible.

=== Context

The authentication provider in the application landscape is a RedHat Keycloak Identity and Access Management System. It provides both OAuth2 as well as JWT authentication - and both will be used for user verification.

=== Task #10

One of the approaches in securing microservices environments is to terminate access token on the api-gateway and pass only username, email and roles and one of the headers. In the given example token is available as a part of KeycloakPrincipal which you can inject directly into the controller.

Pass the appropriate authorisation values to the downstream services, embedding them to the request header.

Tip
Lookup the token structure in the http://jwt.io/#debugger to choose appropriate fields
Tip
You can easily embedded authorisation fields to all Spring’s RestTemplate request by adding appropriate implementation of ClientHttpRequestInterceptor class. Implement the class and add username (X-Username) and roles (X-Roles) headers.

=== How to run

Start the Authentication service (Keycloak) by mvn spring-boot:run -f keycloak

workshops-microservices-patterns's People

Contributors

kubamarchwicki avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.