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

Rethinking REST in a Microservices World

h3nk3
April 28, 2016

Rethinking REST in a Microservices World

Presentation given at Reactive NY meetup in NYC at 2016-04-27.

h3nk3

April 28, 2016
Tweet

More Decks by h3nk3

Other Decks in Programming

Transcript

  1. Rethinking REST in a Microservices World Henrik Engstrom - Software

    Engineer, Lightbend @h3nk3 Reactive NY Meetup - April 27, 2016
  2. Agenda • What is Asynchronous Communication? • Synchronous vs. Asynchronous

    Communication Architectures • REST - the perils thereof • Introduction to Lagom • Q&A
  3. • AIO: callback only uses a thread when it is

    executed • AIO: should definitely be used, but is not enough! What is Asynchronous IO (AIO)? // Java 8 Asynchronous IO example CompletionStage<Response> someResponse = makeRequest(); CompletionStage<MyModel> futureModel = someResponse.thenApply(response -> { MyModel model = decode(response.getBody()); return model; });
  4. What is Asynchronous Communication (AC)? • Not blocking requests •

    In a Microservices architecture this translates to: A service processing a request should not block on other services • AC != AIO
  5. Synchronous Systems • Synchronous Communication leads to ◦ Failures bubble

    up ◦ Slow response times bubble up ◦ SPOFs ◦ Bottlenecks • So what can we do instead?
  6. Synchronous Systems - part 2 • Some changes to the

    architecture perhaps? ◦ Load balancers ◦ Caching sprinkled everywhere ◦ Various other optimizations ◦ Most of the time added in retrospect … ◦ … which leads to complex and inherently fragile architectures • So what can we do instead? Take two.
  7. Asynchronous Systems • A combination of ◦ Data Distribution -

    messaging/CQRS/Event Sourcing ◦ and timeouts for service calls • In other words you want to use a combination of asynchronous communication and asynchronous IO
  8. Asynchronous Communication Customer Service Account Service Portfolio Service Cash Account

    Service Message Service AIO with timeout Data distribution/subscription
  9. Asynchronous Communication Customer Service Account Service Portfolio Service Cash Account

    Service Message Service AIO with timeout Data distribution/subscription
  10. REST - pros and cons • REST is traditionally used

    as a synchronous communication protocol ◦ Client Request leads to Service Response • Can be used for asynchronous messaging ◦ HTTP 202 - Accepted ◦ HTTP 204 - No Content • REST in itself is not a problem but it can lead to an architecture that is...
  11. REST - Monolith to Microservices • REST tends to be

    our go-to but… ◦ Don’t just do a 1:1 service/interface replacement • Instead… ◦ Design for an asynchronous architecture • Pro-tip: Watch Ben Christensen’s “Don’t build a distributed Monolith” talk from Microservices Practitioner Summit 2016* *Lagom will soon support dependency on Swagger as an alternative to direct binary dependencies as suggested in Christensen’s talk
  12. Service Design - A service should • Handle one thing

    • Be autonomous - do not rely on other services • Own its data • Look at DDD for inspiration ◦ Bounded Context ◦ Ubiquitous Language ◦ Aggregate Root, Entity, Value Object, etc.
  13. Introduction to Lagom [lah-gome] • Framework that is opinionated: ◦

    Services are asynchronous ◦ Intra-service communication handled for you ◦ Streaming out of the box ◦ Built in resilience ◦ Developer friendly ◦ Seamless deployment
  14. Lagom - Under the hood • sbt build tool (developer

    experience) • Play (web framework built on top of Netty) • Jackson (serialization) • Guice (DI) • Akka (clustering, streams, persistence) • Cassandra (persistence layer) • Architectural Concepts: immutability, Event Sourcing/CQRS, circuit breakers
  15. Lagom - Service Anatomy Message Service API Customer Service Implementation

    Message Service Implementation Customer Service API
  16. Lagom - API: Service Descriptor public interface HelloService extends Service

    { ServiceCall<NotUsed, String, String> sayHello(); default Descriptor descriptor() { return named("hello").with( call(sayHello()) ); } } All code examples can be studied in full format (including imports) in the Lagom documentation
  17. Lagom - API: Defining Services interface ServiceCall<Id, Request, Response> {

    CompletionStage<Response> invoke(Id id, Request request); } • ServiceCall takes 3 params: Id, Request and Response ◦ Id: extracted from incoming identifier (usually in the path of a REST request) ◦ Request: type of incoming request message (e.g. String) ◦ Response: type of outgoing response message (e.g. String) • CompletionStage “A stage of a possibly asynchronous computation, that performs an action or computes a value when another CompletionStage completes”
  18. Lagom - API: What you get • Service named hello

    with one call sayHello • Lagom will map sayHello() call to a POST request on a static path of /sayHello, with text/plain request and response bodies • All of the above is, of course, configurable...
  19. Lagom -API: REST Based Descriptor default Descriptor descriptor() { return

    named("orders").with( restCall(Method.POST, "/order/:orderId/item", addItem()), restCall(Method.GET, "/order/:orderId/item/:itemId", getItem()), restCall(Method.DELETE, "/order/:orderId/item/:itemId", deleteItem()) ).with(ItemId.class, IdSerializers.create("ItemId", ItemId::of, id -> Arrays.asList(id.orderId(), id.itemId())) ).with(OrderId.class, IdSerializers.create("OrderId", OrderId::of, OrderId::id)); }
  20. Lagom - API: Strict Messages • A single message that

    can be represented by a Java object • These type of messages get buffered and parsed (e.g. as JSON) • If both types are strict it is a traditional request response call (albeit in an asynchronous fashion if between services) • Strict messages means that the request/response is loaded in memory before processing logic is executed
  21. Lagom - API: Streamed Messages ServiceCall<Integer, String, Source<String, ?>> tick();

    default Descriptor descriptor() { return named("clock").with( pathCall("/tick/:interval", tick()) ); } • A streamed message is of type Source (an Akka streams API) • It allows asynchronous streaming and handling of messages • Lagom will select transport protocol (typically WebSockets) • To achieve the above is quite tricky if you roll your own...
  22. Lagom - Implementing Services • CompletionStage ◦ A promise =

    value may not yet be computed = you can’t interact with it immediately ◦ Instead you attach callbacks: thenApply and thenCompose ◦ Callbacks allow your code to be asynchronous - not waiting/holding thread ◦ completedFuture can be used for values that are completed immediately public class HelloServiceImpl implements HelloService { public ServiceCall<NotUsed, String, String> sayHello() { return (id, name) -> completedFuture("Hello " + name); } }
  23. Lagom - Consuming Services public class MyServiceImpl implements MyService {

    private final HelloService helloService; @Inject public MyServiceImpl(HelloService helloService) { this.helloService = helloService; } @Override public ServiceCall<NotUsed, NotUsed, String> sayHelloLagom() { return (id, msg) -> { CompletionStage<String> response = helloService.sayHello().invoke("Lagom"); return response.thenApply(answer -> "Hello service said: " + answer ); }; } }
  24. Lagom - Event Sourcing/CQRS • Capture all changes as events

    (immutable facts) • Query (read) data on “the other side” • Some Advantages: ◦ No need for ORM ◦ Easy to test and debug ◦ Append only can enable great performance • Yes, Lagom can still be used without using ES* *Only ES and Cassandra is supported out of the box though
  25. Lagom - ES: PersistentEntity • Has a stable entity identifier,

    can be accessed from anywhere in the cluster, is run by an actor and the state is persistent using ES • Corresponds to Aggregate Root in DDD • For any id there will only be one entity • All you have to do is to extend PersistentEntity<Command, Event, State> and override some methods and voila, ES!
  26. Lagom - ES: PersistentEntity public class Post extends PersistentEntity<BlogCommand, BlogEvent,

    BlogState> { @Override public Behavior initialBehavior(Optional<BlogState> snapshotState) { // TODO define command and event handlers } }
  27. Lagom - ES: Using PersistentEntity public class BlogServiceImpl implements BlogService

    { private final PersistentEntityRegistry persistentEntities; @Inject // PersistentEntityRegistry gets injected @Override public ServiceCall<String, AddPost, String> addPost() { return (id, request) -> { PersistentEntityRef<BlogCommand> ref = persistentEntities.refFor(Post.class, id); return ref.ask(request).thenApply(ack -> "OK"); }; } }
  28. Lagom - ES Read Side • Retrieving data: Cassandra Query

    Language, e.g. “SELECT id, title FROM postsummary;” • Updating read side: extend CassandraReadSideProcessor • Streaming of events: use the eventStream method of the PersistentEntityRegistry class
  29. Lagom - Running in Development > cd <your-lagom-project> > sbt

    runAll [info] ... [info] Service helloworld-impl listening for HTTP on 0:0:0:0:0:0:0:0:23966 [info] Service hellostream-impl listening for HTTP on 0:0:0:0:0:0:0:0:27462 (Services started, use Ctrl+D to stop and go back to the console...) Behind the scenes: • An embedded Service Locator is started • A Cassandra server is started • Your services start and register with the Service Locator
  30. Lagom - Running in Production • sbt-native packager is used

    to produce zip, MSI, RPM, Docker • Lightbend ConductR* (our container orchestration tool) • Lightbend Reactive Platform* ◦ Split Brain Resolver (for Akka cluster) ◦ Lightbend Monitoring *Requires a Lightbend subscription (ConductR is free to use during development)
  31. Lagom - The Next Steps? (in random order) • Scala

    API • Swagger integration • Maven support • Support for more DBs • Integration with other cluster orchestration tools • … What is missing?
  32. Lagom - Your Next Steps • Try Lagom yourself ◦

    https://lightbend.com/lagom • Sample application https://www.lightbend.com/activator/template/lagom- java-chirper • Read Jonas Bonér's free book Reactive Services Architecture ◦ https://lightbend.com/reactive-microservices-architecture • Great presentation by Greg Young on why you should use ES ◦ https://www.youtube.com/watch?v=JHGkaShoyNs • Please help us improve Lagom: ◦ https://github.com/lagom/lagom