项目作者: otto-de-legacy

项目描述 :
DSL for server-side composition of content from different microservices using RxJava
高级语言: Java
项目地址: git://github.com/otto-de-legacy/rx-composer.git
创建时间: 2016-11-18T18:37:18Z
项目社区:https://github.com/otto-de-legacy/rx-composer

开源协议:Apache License 2.0

下载


RX-Composer

A DSL for reactive composition of content from different microservices using RxJava.

Status

Next Selected Stories
Active Stories

build
codecov
release
license

Work in Progress

  • Ready to be tested
  • Not yet performance- and/or load-tested
  • Not yet in production at otto.de
  • Partly documented

Current Versions

Release: 1.0.0.M1

  1. de.otto.rx-composer:composer-core:1.0.0.M1
  2. de.otto.rx-composer:composer-thymeleaf:1.0.0.M1

Snapshot: 1.0.0.M2-SNAPSHOT

  1. de.otto.rx-composer:composer-core:1.0.0.M2-SNAPSHOT
  2. de.otto.rx-composer:composer-thymeleaf:1.0.0.M2-SNAPSHOT

About

Microservice architectures for web applications are currently at the top of the hype cycle. One of the most
interesting (and complicated) questions is how to integrate microservices in the frontend. The following options
are already well understood:

  • Different pages are rendered by different microservices (or self-contained systems). Hyperlinks are used to
    “integrate” the different pages.
  • A page is rendered by some microservices: one service is rendering the initial HTML, others are integrated
    using AJAX and similar techniques.
  • A page is rendered by some microservices: one service is rendering the initial HTML, others are integrated
    using Edge-Side includes (or Server-Side Indludes) using reverse-proxies.
  • Services are calling other services in order to get data or HTML fragments for different parts of the page.
    The Frontend-Service is integrating the results from the different services into a single HTML page.

The latter solution requires a frontend microservice to gather content from multiple backend microservices.
The more fine-grained you are cutting your microservices, the more important it gets to use asynchronous
communication and retrieve content in parallel, whenever possible. Especially in Java, implementing this in
a tradition way is a non-trivial task.

In addition to this, you would have to deal with unavailable backend services, slow service, and so on: you have
to implement resiliency against failures into your frontend service(s). This is also a non-trivial task…

Rx-Composer is meant to solve such kind of problems. It provides you with an easy to read DSL to describe, what
content to fetch from which microservices. It is handling failures when retrieving content, and it retrieves
content in a reactive way, using RxJava in the implementation.

Examples

Fetching two contents for a single page in parallel

The general pattern for a rx-composer server is to describe the contents to be fetched, then execute the page and
process the resulting contents.

In the first example, we want to fetch two HTTP resources for fragements “X” and “Y”:

  1. // Setup some ServiceClient:
  2. final ServiceClient serviceClient = HttpServiceClient.singleRetryClient();
  3. // Specify what to fetch:
  4. final Page page = consistsOf(
  5. fragment(
  6. X,
  7. withSingle(
  8. contentFrom(serviceClient, "http://example.com/someContent", "text/html")
  9. )
  10. ),
  11. fragment(
  12. Y,
  13. withSingle(
  14. contentFrom(serviceClient, "http://example.com/someOtherContent", "text/html")
  15. )
  16. )
  17. );
  18. // Fetch contents of the page:
  19. final Contents result = page.fetchWith(emptyParameters());
  20. // now we can process the results:
  21. System.out.println("X: " + result.getBody(X);
  22. System.out.println("Y: " + result.getBody(Y);

Both contents will be requested in parallel. The time to fetch both contents will only be a little slower than the
slowest response - instead of the sum of both response times.

Because we are using the singleRetryClient, we already have some build-in resiliency:

  • The client is is using some default timeouts (for example, it is using a read-timeout of 500ms).
  • A Hystrix Circuit-Breaker is used, so using the client will fail-fast, if 50% of all requests are failing.
  • If fetching the resource fails because of a timeout, exception or HTTP server error, the request is
    retried once.

Fetching content with a fallback to some static content on error

Using a ServiceClient like noRetries() or singleRetry, it is possible to configure a fallback, if retrieving
content from the primary ContentProvider fails because of timeouts, exceptions or HTTP server errors.

  1. final Page page = consistsOf(
  2. fragment(X,
  3. withSingle(
  4. contentFrom(serviceClient, "http://example.com/someContent", TEXT_PLAIN,
  5. fallbackTo(staticTextContent(position, "<p>Some Fallback Content</p>"))
  6. )
  7. )
  8. )
  9. );

The fallbackTo methods accepts all kinds of ContentProviders. The following example is falling back to a different
service, using a differently configured ServiceClient:

  1. ...
  2. contentFrom(serviceClient, "http://example.com/someContent", TEXT_PLAIN,
  3. fallbackTo(contentFrom(fallbackClient, "http://example.com/someFallbackContent", TEXT_PLAIN))
  4. )
  5. ...

More Examples

…about how to use rx-composer can be found in the user guide.

Features

TODO

Server-Side Transclusion

TODO

Asynchronous Execution

TODO

Build-In Resiliency

TODO

Tracing and Debugging

TODO

Documentation

The docs folder contains some documentation about the project:

  1. Change Log: Information about the lasted changes, release notes, and so on can be found in the
    change log.

  2. Getting Started: The Getting Started guide contains information about how to include
    rx-composer into your project, about build it, and so on.

  3. Examples: A working example is also contained in this project. It consists of two Spring Boot server modules and
    is described here.

  4. User Guide: If you are looking for some deeper insights, the User Guide might be the
    right place to look.

  5. Contributing: You would like to contribute? Great! Please have a look here for
    information about how to do it.