JavaOne: Efficiently building and deploying microservices

Post on 27-Nov-2014

275 views 5 download

Tags:

description

Since Martin Fowler’s article on microservices in the beginning of 2014, there has been a lot of controversy about the topic. Although most articles talk about microservices from an architectural perspective, this session intends to go further and also provide examples of and best practices for building and deploying polyglot applications in an enterprise Java environment. In the session, the build process focuses on efficiency and shows that microservices don’t necessarily cause overhead for a project. Microservices don't imply copying and pasting the same boilerplate code over and over. The deployment process in the presentation is, of course, automated but also demonstrates best practices for integration testing between different active services.

transcript

Efficiently

building

and deployingMICROSERVICES

Bart Blommaerts

Me• bart.blommaerts@hp.com• @DaggieBe

HP Enterprise Services• EMEA Java SME• Technical Lead at Flemish Government

Web• https://github.com/bart-blommaerts/• http://www.daggie.be

MICROSERVICES

Why?

Monoliths …• Don’t scale easily• Are difficult

– To understand– To maintain – To test– To deploy

• Make it difficult to adopt new technology

A monolithic application is like a house of cards ...

Small

Do 1 thing well• 1 responsibility• About use case / business capability

Not about LOC

Stateless

Small

Decomposition• A monolitic application has disadvantages• Decompose the monolith into microservices

Smart endpoints and dumb pipes

Loosely coupled• Make the service smart. Keep the communication dumb.

• Favor coarse-grained over fine-grained communication.

Smart endpoints and dumb pipes

Synchronous• HTTP request / response

Smart endpoints and dumb pipes

Synchronous• HTTP request / response

Smart endpoints and dumb pipes

Asynchronous• Lightweight messaging

Smart endpoints and dumb pipes

Asynchronous• Event-driven

Decentralized governance

API interface• Language agnostic• Multiple versions allowed / encouraged• Publish anything of interest. Don’t wait to be asked.• Evolutionary

Disposable

Decentralized data management

Polyglot persistence• Each service owns it’s data storage

Decentralized data management

Eventual consistency• Transactions impose coupling• Synchronizing databases might be needed

Do 1 thing

Design for failure

Self-monitoring• Application will use services as components: many moving parts• Any service can fail (or be unreachable):

– Detect quickly– Restore automatically (if possible)

Automation

Infrastructure (deployment)• Large number of services will require automation

– Use existing solutions (eg. Jenkins, Bamboo, ..)• Automation as an enabler for microservices

Recap

SmallSmart endpoints and dumb

pipesDecentralised governance

Decentralised data management

Design for failureAutomation

building

and deploying

Building: Synchronous

Person• Spring Boot• Tomcat

@ComponentScan@EnableAutoConfigurationpublic class PersonApplication {

public static void main(String[] args) {SpringApplication.run(PersonApplication.class,

args);}

}

Building: Synchronous

Address• DropWizard• Jetty

@Overridepublic void run(AddressConfiguration configuration, Environment environment) {

final AddressResource resource = new AddressResource();final AddressHealthCheck addressHealthCheck = new

AddressHealthCheck();

environment.healthChecks().register("address", addressHealthCheck);

environment.jersey().register(resource);}

Building: Synchronous

PersonAddress• DropWizard• Jetty• Calling Person and Address service, using Jersey.

@Overridepublic void run(PersAddrConfiguration configuration, Environment environment) {

final Client client = new JerseyClientBuilder(environment).using(

configuration.getJerseyClientConfiguration()).build(getName());

final PersonAddressResource resource = new PersonAddressResource(client);

Building: Asynchronous

Person Publisher• Spring Boot• Tomcat• Rabbit MQ

@AutowiredRabbitTemplate rabbitTemplate;

rabbitTemplate.convertAndSend(QUEUE_NAME, repository.getAllPersons());

Building: Asynchronous: Person Publisher@BeanQueue queue() {

return new Queue(QUEUE_NAME, false);}

@BeanTopicExchange exchange() {

return new TopicExchange(TOPIC_EXCHANGE);}

@BeanBinding binding(Queue queue, TopicExchange exchange) {

return BindingBuilder.bind(queue).to(exchange).with(QUEUE_NAME);}

Building: Asynchronous

Person Listener• Spring Boot• Tomcat• Rabbit MQ

Application:@Beanprivate MessageListenerAdapter listenerAdapter(PersonListener listener) {

return new MessageListenerAdapter(listener, "receiveMessage");}…PersonListener: public void receiveMessage(Map<Integer, Person> message)

Building: Sample

Address Publisher

Deploying

Automation• Simple sample application: 5 servlet containers, 1 messaging queue• Configure a deployment pipeline• Use deployment automation from the start• Consider a PaaS

– Cloud Foundry, OpenShift, ...

Efficiently

Efficiently

Synchronous vs Asynchronous• Decide early• Rule of thumb

– Reading: synchronous– Updating: asynchronous

Decentralised governance

Service templating• Microservices are language agnostic

– But don’t change technology because you can. Change because it makes sense.

• Start with a common technology stack

Modularity• Services can be modules of the system

– Own life cycle– Independently deployable– But .. “Options” in regard to re-use

Deploying

DevOps• Own your service

– Eat your own dog food• Monitor the monitoring ..

– Use the monitoring to make the service self-operational• Log everything

Efficiently

Tracking• Microservices will be using other microservices• Keep track of

– a correlation id between services– The ‘age’ of the data / response

Efficiently

Tracking: CorrelationId

Publisher:protected Message createMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {

messageProperties.setCorrelationId(correlationId.getBytes());return super.createMessage(object, messageProperties);

}

Listener: protected Object extractMessage(Message message) throws Exception {

byte[] correlationId = message.getMessageProperties().getCorrelationId();

Efficiently

Free Lunch?• Complexity• DRY• Latency and marshalling• Versioning• API Interface• Architect security in from the beginning

http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html

Thank you