Messaging Microservices with Spring Cloud

Dave Syer, 2016
Twitter: @david_syer
Email: dsyer@pivotal.io

Agenda

Microservices

Life after REST

Messaging

Patterns:

Conclusion: There is a range of applications and problems to which messaging is an effective solution.

Philosophy

Simple things should be easy, and complex things should be possible.


Alan Kay

A Simple Streaming Application

@EnableBinding(Source.class)
@SpringBootApplication
public class Application {

  @Autowired
  Source source;

  @RequestMapping(value="/", method=POST)
  public String send() {
    source.output()
      .send(MessageBuilder.withPayload("Hello World").build);
    return "OK";
  }

}

What's a Source?

Answer: it's an interface...

public interface Source {

  String OUTPUT = "output";

  @Output(Source.OUTPUT)
  MessageChannel output();

}

Source Sending Messages

   +--------+     +---------------------------+
   | Source |---->| "output"                  |
   +--------+     +---------------------------+

Add a Sink

   +--------+     +---------------------------+     +---------+
   | Source |---->| "output"                  |---->| Sink    |
   +--------+     +---------------------------+     +---------+

Enable All the Things

@EnableBinding(Source.class)
...
@EnableBinding(Sink.class)
...
@EnableBinding(Processor.class)
...

or even

@EnableBinding(MyCoffeeShop.class)

Consuming Messages

You can use the MessageChannel interfaces (e.g. inject a SubscribableChannel and subscribe to it).

@EnableBinding(Processor.class)
public class TransformProcessor {

  @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
  public Object transform(String message) {
    return message.toUpper();
  }

}

Consuming Messages

Or you can use a @StreamListener (more like @RequestMapping):

@EnableBinding(Processor.class)
public class TransformProcessor {

  ...

  @StreamListener(Processor.INPUT)
  @SendTo(Processor.OUTPUT)
  public VoteResult handle(Vote vote) {
    return record(vote);
  }
}

(With @StreamListener you also get support for Reactor and RxJava.)

Tasks as Well

@SpringBootApplication
public class Task {

  @Bean
  public ApplicationRunner(Source source) {
    return app -> { System.out.println("Hello World"); };
  }

  ...
}

Enable that Task!

@EnableTask
@SpringBootApplication
public class Task {

  @Bean
  public ApplicationRunner(Source source) {
    return app -> { System.out.println("Hello World"); };
  }

  ...
}

Spring Cloud Data Flow

A programming and operating model for streams and tasks on a structured platform.

Components:

Structured Platform?

It's an SPI. Examples:

Architecture

  +---------------------------------+
  |            Client               | (shell or browser)
  +---------------------------------+
                |^
  Platform      v|                    (cf, k8s, mesos, etc.)
  +---------------------------------+
  |       +------+ +------+         |
  |       |Server| |  DB  |         |
  |       +------+ +------+         |
  | +----+----+----+----+----+----+ |
  | |    |    |Apps|    |    |    | | (streams and tasks)
  | +-----------------------------+ |
  | |         Transport           | | (rabbit, kafka, etc.)
  +---------------------------------+

Streams and Tasks

Streams have a DSL, e.g. http | transform | hdfs, but fundamentally they are just apps sending each other messages. Each node in the pipeline is a Spring Boot app using Spring Cloud Stream.

Tasks are short- (or finite-) lived apps. Data Flow orchestrates them and uses Spring Cloud Task to record their exit status.

EOF

#