Top Banner
Building Distributed Systems with Netflix OSS and Spring Cloud © 2015 Matt Stine 1
84

Building Distributed Systems with Netflix OSS and Spring Cloud

Jul 14, 2015

Download

Software

Matt Stine
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Building Distributed Systems with Netflix OSS and Spring Cloud

Building Distributed Systems with

Netflix OSSandSpring Cloud© 2015 Matt Stine 1

Page 2: Building Distributed Systems with Netflix OSS and Spring Cloud

MeMatt Stine (@mstine)Senior Product ManagerPivotalhttp://[email protected]

© 2015 Matt Stine 2

Page 3: Building Distributed Systems with Netflix OSS and Spring Cloud

There Seems to Be Some Hype...

© 2015 Matt Stine 3

Page 4: Building Distributed Systems with Netflix OSS and Spring Cloud

Define: Microservice“Loosely coupled service oriented architecture with bounded contexts...”Adrian Cockcroft

© 2015 Matt Stine 4

Page 5: Building Distributed Systems with Netflix OSS and Spring Cloud

Spring BootA Microframework for Microservices

© 2015 Matt Stine 5

Page 6: Building Distributed Systems with Netflix OSS and Spring Cloud

It Can Get Pretty Small...@RestControllerclass ThisWillActuallyRun { @RequestMapping("/") String home() { "Hello World!" }}

© 2015 Matt Stine 6

Page 7: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 7

Page 8: Building Distributed Systems with Netflix OSS and Spring Cloud

With Spring Data REST!@Entity@Table(name = "city")public class City implements Serializable {

@Id @GeneratedValue private Long id;

@Column(nullable = false) private String name;

@Column(nullable = false) private String county;

//...

}

© 2015 Matt Stine 8

Page 9: Building Distributed Systems with Netflix OSS and Spring Cloud

With Spring Data REST!@RepositoryRestResource(collectionResourceRel = "cities", path = "cities")public interface CityRepository extends PagingAndSortingRepository<City, Long> {}

© 2015 Matt Stine 9

Page 10: Building Distributed Systems with Netflix OSS and Spring Cloud

With Spring Data REST!@SpringBootApplication@EnableJpaRepositories@Import(RepositoryRestMvcConfiguration.class)public class Application {

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

© 2015 Matt Stine 10

Page 11: Building Distributed Systems with Netflix OSS and Spring Cloud

With Spring Data REST!{ "_links" : { "next" : { "href" : "http://localhost:8080/cities?page=1&size=20" }, "self" : { "href" : "http://localhost:8080/cities{?page,size,sort}", "templated" : true } }, "_embedded" : { "cities" : [ { "name" : "HOLTSVILLE", "county" : "SUFFOLK", "stateCode" : "NY", "postalCode" : "00501", "latitude" : "+40.922326", "longitude" : "-072.637078",

© 2015 Matt Stine 11

Page 12: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 12

Page 13: Building Distributed Systems with Netflix OSS and Spring Cloud

Writing a Single Service is

Nice...© 2015 Matt Stine 13

Page 14: Building Distributed Systems with Netflix OSS and Spring Cloud

But No Microservice

is an Island© 2015 Matt Stine 14

Page 15: Building Distributed Systems with Netflix OSS and Spring Cloud

Challenges of Distributed Systems» Configuration Management

» Service Registration & Discovery

» Routing & Load Balancing

» Fault Tolerance (Circuit Breakers!)

» Monitoring

» Concurrent API Aggregation & Transformation

© 2015 Matt Stine 15

Page 16: Building Distributed Systems with Netflix OSS and Spring Cloud

© 2015 Matt Stine 16

Page 17: Building Distributed Systems with Netflix OSS and Spring Cloud

Spring CloudDistributed System Patterns FTW!

© 2015 Matt Stine 17

Page 18: Building Distributed Systems with Netflix OSS and Spring Cloud

ConfigurationManagement© 2015 Matt Stine 18

Page 19: Building Distributed Systems with Netflix OSS and Spring Cloud

Spring Environment» Properties

» Profiles

© 2015 Matt Stine 19

Page 20: Building Distributed Systems with Netflix OSS and Spring Cloud

app.groovy@RestControllerclass BasicConfig {

@Value('${greeting}') String greeting

@RequestMapping("/") String home() { "${greeting} World!" }}

© 2015 Matt Stine 20

Page 21: Building Distributed Systems with Netflix OSS and Spring Cloud

application.ymlgreeting: Hello

© 2015 Matt Stine 21

Page 22: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 22

Page 23: Building Distributed Systems with Netflix OSS and Spring Cloud

Boot Priority1.Command Line Args

2.JNDI

3.Java System Properties

4.OS Environment Variables

5.Properties Files

6.@PropertySource

7.Defaults

© 2015 Matt Stine 23

Page 24: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 24

Page 25: Building Distributed Systems with Netflix OSS and Spring Cloud

Profiles© 2015 Matt Stine 25

Page 26: Building Distributed Systems with Netflix OSS and Spring Cloud

application.ymlgreeting: Hello

---

spring: profiles: spanishgreeting: Hola

© 2015 Matt Stine 26

Page 27: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 27

Page 28: Building Distributed Systems with Netflix OSS and Spring Cloud

Distributed?

© 2015 Matt Stine 28

Page 29: Building Distributed Systems with Netflix OSS and Spring Cloud

ConfigServer!

© 2015 Matt Stine 29

Page 30: Building Distributed Systems with Netflix OSS and Spring Cloud

Config Server app.groovy@Grab("org.springframework.cloud:spring-cloud-starter-bus-amqp:1.0.0.RC1")@Configuration@EnableAutoConfiguration@EnableConfigServerclass ConfigServer {}

© 2015 Matt Stine 30

Page 31: Building Distributed Systems with Netflix OSS and Spring Cloud

Config Server application.ymlserver: port: 8888

spring: cloud: config: server: git: uri: https://github.com/mstine/config-repo.git

© 2015 Matt Stine 31

Page 32: Building Distributed Systems with Netflix OSS and Spring Cloud

https://github.com/mstine/config-repo/blob/master/demo.ymlgreeting: Bonjour

© 2015 Matt Stine 32

Page 33: Building Distributed Systems with Netflix OSS and Spring Cloud

Config Client app.groovy@Grab("org.springframework.cloud:spring-cloud-starter-bus-amqp:1.0.0.RC1")@RestControllerclass BasicConfig {

@Autowired Greeter greeter

@RequestMapping("/") String home() { "${greeter.greeting} World!" }}

@Component@RefreshScopeclass Greeter {

@Value('${greeting}') String greeting

}

© 2015 Matt Stine 33

Page 34: Building Distributed Systems with Netflix OSS and Spring Cloud

Config Client bootstrap.ymlspring: application: name: demo

© 2015 Matt Stine 34

Page 35: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 35

Page 36: Building Distributed Systems with Netflix OSS and Spring Cloud

Cloud

Bus!© 2015 Matt Stine 36

Page 37: Building Distributed Systems with Netflix OSS and Spring Cloud

curl -X POST http://localhost:8888/bus/refresh

© 2015 Matt Stine 37

Page 38: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 38

Page 39: Building Distributed Systems with Netflix OSS and Spring Cloud

ServiceRegistration &

Discovery© 2015 Matt Stine 39

Page 40: Building Distributed Systems with Netflix OSS and Spring Cloud

Eureka© 2015 Matt Stine 40

Page 41: Building Distributed Systems with Netflix OSS and Spring Cloud

ProducerConsumer© 2015 Matt Stine 41

Page 42: Building Distributed Systems with Netflix OSS and Spring Cloud

Eureka Service Registry@GrabExclude("ch.qos.logback:logback-classic")@EnableEurekaServerclass Eureka {}

© 2015 Matt Stine 42

Page 43: Building Distributed Systems with Netflix OSS and Spring Cloud

Producer@EnableDiscoveryClient@RestControllerpublic class Application {

int counter = 0

@RequestMapping("/") String produce() { "{\"value\": ${counter++}}" }}

© 2015 Matt Stine 43

Page 44: Building Distributed Systems with Netflix OSS and Spring Cloud

Consumer@EnableDiscoveryClient@RestControllerpublic class Application {

@Autowired DiscoveryClient discoveryClient

@RequestMapping("/") String consume() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("PRODUCER", false)

RestTemplate restTemplate = new RestTemplate() ProducerResponse response = restTemplate.getForObject(instance.homePageUrl, ProducerResponse.class)

"{\"value\": ${response.value}" }}

public class ProducerResponse { Integer value}

© 2015 Matt Stine 44

Page 45: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 45

Page 46: Building Distributed Systems with Netflix OSS and Spring Cloud

Routing &Load Balancing© 2015 Matt Stine 46

Page 47: Building Distributed Systems with Netflix OSS and Spring Cloud

Ribbon© 2015 Matt Stine 47

Page 48: Building Distributed Systems with Netflix OSS and Spring Cloud

Consumer with Load Balancer@AutowiredLoadBalancerClient loadBalancer

@RequestMapping("/")String consume() { ServiceInstance instance = loadBalancer.choose("producer") URI producerUri = URI.create("http://${instance.host}:${instance.port}");

RestTemplate restTemplate = new RestTemplate() ProducerResponse response = restTemplate.getForObject(producerUri, ProducerResponse.class)

"{\"value\": ${response.value}"}

© 2015 Matt Stine 48

Page 49: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 49

Page 50: Building Distributed Systems with Netflix OSS and Spring Cloud

Consumer with Ribbon-enabled RestTemplate@AutowiredRestTemplate restTemplate

@RequestMapping("/")String consume() { ProducerResponse response = restTemplate.getForObject("http://producer", ProducerResponse.class)

"{\"value\": ${response.value}"}

© 2015 Matt Stine 50

Page 51: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMO© 2015 Matt Stine 51

Page 52: Building Distributed Systems with Netflix OSS and Spring Cloud

Feign Client@FeignClient("producer")public interface ProducerClient {

@RequestMapping(method = RequestMethod.GET, value = "/") ProducerResponse getValue();}

© 2015 Matt Stine 52

Page 53: Building Distributed Systems with Netflix OSS and Spring Cloud

Consumer with Feign Client@SpringBootApplication@FeignClientScan@EnableDiscoveryClient@RestControllerpublic class Application {

@Autowired ProducerClient client;

@RequestMapping("/") String consume() { ProducerResponse response = client.getValue();

return "{\"value\": " + response.getValue() + "}"; }

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

© 2015 Matt Stine 53

Page 54: Building Distributed Systems with Netflix OSS and Spring Cloud

Demo© 2015 Matt Stine 54

Page 55: Building Distributed Systems with Netflix OSS and Spring Cloud

FaultTolerance© 2015 Matt Stine 55

Page 56: Building Distributed Systems with Netflix OSS and Spring Cloud

Hystrix© 2015 Matt Stine 56

Page 57: Building Distributed Systems with Netflix OSS and Spring Cloud

Circuit Breaker

© 2015 Matt Stine 57

Page 58: Building Distributed Systems with Netflix OSS and Spring Cloud

Consumer app.groovy@EnableDiscoveryClient@EnableCircuitBreaker@RestControllerpublic class Application {

@Autowired ProducerClient client

@RequestMapping("/") String consume() { ProducerResponse response = client.getProducerResponse()

"{\"value\": ${response.value}" }

}

© 2015 Matt Stine 58

Page 59: Building Distributed Systems with Netflix OSS and Spring Cloud

Producer Client@Componentpublic class ProducerClient {

@Autowired RestTemplate restTemplate

@HystrixCommand(fallbackMethod = "getProducerFallback") ProducerResponse getProducerResponse() { restTemplate.getForObject("http://producer", ProducerResponse.class) }

ProducerResponse getProducerFallback() { new ProducerResponse(value: 42) }}

© 2015 Matt Stine 59

Page 60: Building Distributed Systems with Netflix OSS and Spring Cloud

Demo© 2015 Matt Stine 60

Page 61: Building Distributed Systems with Netflix OSS and Spring Cloud

Monitoring© 2015 Matt Stine 61

Page 62: Building Distributed Systems with Netflix OSS and Spring Cloud

DEMOhttp://localhost:8082/

© 2015 Matt Stine 62

Page 63: Building Distributed Systems with Netflix OSS and Spring Cloud

HystrixDashboard© 2015 Matt Stine 63

Page 64: Building Distributed Systems with Netflix OSS and Spring Cloud

Hystrix Dashboard

© 2015 Matt Stine 64

Page 65: Building Distributed Systems with Netflix OSS and Spring Cloud

Hystrix Dashboard@Grab("org.springframework.cloud:spring-cloud-starter-hystrix-dashboard:1.0.0.RC1")

import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard

@EnableHystrixDashboardclass HystrixDashboard {}

© 2015 Matt Stine 65

Page 66: Building Distributed Systems with Netflix OSS and Spring Cloud

Demo© 2015 Matt Stine 66

Page 67: Building Distributed Systems with Netflix OSS and Spring Cloud

ConcurrentAPIAggregation &Transformation© 2015 Matt Stine 67

Page 68: Building Distributed Systems with Netflix OSS and Spring Cloud

RxJava© 2015 Matt Stine 68

Page 69: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Catalog Service@RequestMapping(value = "/catalog/movies/{mlId}", method = RequestMethod.GET)public Movie movie(@PathVariable String mlId) { return movieRepository.findByMlId(mlId);}

© 2015 Matt Stine 69

Page 70: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Catalog Service{ id: 1001, title: "GoldenEye (1995)", mlId: "2", genres: [ { id: 1001, mlId: "1", name: "Action" }, { id: 1002, mlId: "2", name: "Adventure" }, { id: 1016, mlId: "16", name: "Thriller" } ]}

© 2015 Matt Stine 70

Page 71: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Review Service@RequestMapping(value = "/reviews/reviews/{mlId}", method = RequestMethod.GET)public Iterable<Review> reviews(@PathVariable String mlId) { return reviewRepository.findByMlId(mlId);}

© 2015 Matt Stine 71

Page 72: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Review Service[{ id: "54b85cbe004e0464177e90e4", mlId: "2", userName: "mstine", title: "GoldenEye (1995)", review: "Pretty good...", rating: 3},{ id: "54b85cbe004e0464177e90e5", mlId: "2", userName: "starbuxman", title: "GoldenEye (1995)", review: "BOND BOND BOND!", rating: 5},{ id: "54b85cbf004e0464177e90e8", mlId: "2", userName: "littleidea", title: "GoldenEye (1995)", review: "Good show!", rating: 4}]

© 2015 Matt Stine 72

Page 73: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Recommendations Servicepublic interface MovieRepository extends GraphRepository<Movie> { Movie findByMlId(String mlId);

@Query("MATCH (movie:Movie) WHERE movie.mlId = {0} MATCH movie<-[:LIKES]-slm-[:LIKES]->recommendations " + "RETURN distinct recommendations") Iterable<Movie> moviesLikedByPeopleWhoLiked(String mlId);}

© 2015 Matt Stine 73

Page 74: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Recommendations Service@RequestMapping(value = "/recommendations/forMovie/{mlId}", method = RequestMethod.GET)public Iterable<Movie> recommendedMoviesForMovie(@PathVariable String mlId) { return movieRepository.moviesLikedByPeopleWhoLiked(mlId);}

© 2015 Matt Stine 74

Page 75: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Recommendations Service@RequestMapping(value = "/recommendations/forMovie/{mlId}", method = RequestMethod.GET)public Iterable<Movie> recommendedMoviesForMovie(@PathVariable String mlId) { return movieRepository.moviesLikedByPeopleWhoLiked(mlId);}

© 2015 Matt Stine 75

Page 76: Building Distributed Systems with Netflix OSS and Spring Cloud

Movie Recommendations Service[{ id: 6, mlId: "1", title: "Toy Story (1995)"},{ id: 1, mlId: "4", title: "Get Shorty (1995)"},{ id: 2, mlId: "5", title: "Copycat (1995)"},{ id: 0, mlId: "3", title: "Four Rooms (1995)"}]

© 2015 Matt Stine 76

Page 77: Building Distributed Systems with Netflix OSS and Spring Cloud

APIGateway© 2015 Matt Stine 77

Page 78: Building Distributed Systems with Netflix OSS and Spring Cloud

Catalog Integration Service@Servicepublic class CatalogIntegrationService {

@Autowired RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "stubMovie") public Observable<Movie> getMovie(final String mlId) { return new ObservableResult<Movie>() { @Override public Movie invoke() { return restTemplate.getForObject("http://catalog-service/catalog/movies/{mlId}", Movie.class, mlId); } }; }

private Movie stubMovie(final String mlId) { Movie stub = new Movie(); stub.setMlId(mlId); stub.setTitle("Interesting...the wrong title. Sssshhhh!"); return stub; }}

© 2015 Matt Stine 78

Page 79: Building Distributed Systems with Netflix OSS and Spring Cloud

Reviews Integration Service@Servicepublic class ReviewsIntegrationService {

@Autowired RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "stubReviews") public Observable<List<Review>> reviewsFor(String mlId) { return new ObservableResult<List<Review>>() { @Override public List<Review> invoke() { ParameterizedTypeReference<List<Review>> responseType = new ParameterizedTypeReference<List<Review>>() { }; return restTemplate.exchange("http://reviews-service/reviews/reviews/{mlId}", HttpMethod.GET, null, responseType, mlId).getBody(); } }; }

private List<Review> stubReviews(String mlId) { Review review = new Review(); review.setMlId(mlId); review.setRating(4); review.setTitle("Interesting...the wrong title. Sssshhhh!"); review.setReview("Awesome sauce!"); review.setUserName("joeblow"); return Arrays.asList(review); }

}

© 2015 Matt Stine 79

Page 80: Building Distributed Systems with Netflix OSS and Spring Cloud

Recommendations Integration Service@Servicepublic class RecommendationsIntegrationService { @Autowired RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "stubRecommendations") public Observable<List<Movie>> getRecommendations(final String mlId) { return new ObservableResult<List<Movie>>() { @Override public List<Movie> invoke() { ParameterizedTypeReference<List<Movie>> responseType = new ParameterizedTypeReference<List<Movie>>() { }; return restTemplate.exchange("http://recommendations-service/recommendations/forMovie/{mlId}", HttpMethod.GET, null, responseType, mlId).getBody(); } }; }

private List<Movie> stubRecommendations(final String mlId) { Movie one = new Movie(); one.setMlId("25"); one.setMlId("A movie which doesn't exist"); Movie two = new Movie(); two.setMlId("26"); two.setMlId("A movie about nothing"); return Arrays.asList(one, two); }}

© 2015 Matt Stine 80

Page 81: Building Distributed Systems with Netflix OSS and Spring Cloud

Concurrently Aggregate and Transform@RequestMapping("/movie/{mlId}")public DeferredResult<MovieDetails> movieDetails(@PathVariable String mlId) { Observable<MovieDetails> details = Observable.zip(

catalogIntegrationService.getMovie(mlId), reviewsIntegrationService.reviewsFor(mlId), recommendationsIntegrationService.getRecommendations(mlId),

(movie, reviews, recommendations) -> { MovieDetails movieDetails = new MovieDetails(); movieDetails.setMlId(movie.getMlId()); movieDetails.setTitle(movie.getTitle()); movieDetails.setReviews(reviews); movieDetails.setRecommendations(recommendations); return movieDetails; }

); return toDeferredResult(details);}

© 2015 Matt Stine 81

Page 82: Building Distributed Systems with Netflix OSS and Spring Cloud

Demo© 2015 Matt Stine 82

Page 83: Building Distributed Systems with Netflix OSS and Spring Cloud

Thanks!Matt Stine (@mstine)

» Spring Cloud: http://cloud.spring.io

» This Presentation: https://github.com/mstine/nfjs_2015/tree/master/DistributedSystemsWithSpringCloud

» SpringBox-Cloud: https://github.com/mstine/microservices-lab/tree/master/springbox-cloud

© 2015 Matt Stine 83

Page 84: Building Distributed Systems with Netflix OSS and Spring Cloud

Image Credits» http://i.imgur.com/atz81.jpg

» http://theroomermill.net/wp-content/uploads/2014/06/island-house.jpg

» Circuit Breaker: Nygard, Michael. Release It!

© 2015 Matt Stine 84