Spring Cloud Ribbon
Spring Cloud Ribbon
Ribbon to load-balancer który działa po stronie klienta. W praktyce oznacza to, że ilość aktywnych instancji zwracana jest przez Service Discovery np. Eureka. Następnie wybór która usługa zwrócona przez Service Discovery zostanie wywołana leży po stronie klienta. Eureka Service Discovery umożliwia efektywne zarządzanie usługami bez konieczności deklarowania adresów kolejnych instancji na sztywno w kodzie źródłowym aplikacji. Zdecydowanie dobrą praktyką jest korzystanie z mechanizmu Service Discovery. Jeśli jednak jest uzasadnienie biznesowe do używania predefiniowanej listy serwerów to jak najbardziej jest możliwe używanie projektu Spring Cloud Ribbon bez konieczności stawiania serwera Eureki. Polecam zapoznać się z materiałem: http://bushkarl.gitbooks.io/spring-cloud/content/spring_cloud_netflix/client_side_load_balancer_ribbon.html.
W artykule tym zaprezentuję użycie mechanizmu load-balancera Ribbon właśnie bez użycia mechanizmu Service Discovery (artykuł z użyciem load-balancera i serwera Eureki dostępny jest tutaj).
[źródło] http://www.slideshare.net/ewolff/microservice-with-spring-boot-and-spring-cloud
Aplikacja serwerowa – niezbędne zależności:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
RestController:
@RestController public class WebController { @Value("${server.port}") String port; @RequestMapping(value = "/") public String home() { return "Okay!"; } @RequestMapping("/greeting") public String hello() { return "Hello from a service running at port: " + port + "!"; } }
Klasa startowa:
@SpringBootApplication public class SpringCloudServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudServerApplication.class, args); } }
Plik application.properties:
server.port = 8092
Aplikacja ta powinna być uruchomiona na 3 różnych portach. Port modyfikujemy z poziomu pliku application.properties.
Aplikacja kliencka – niezbędne zależności:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Klasa konfiguracyjna:
public class Configuration { @Autowired IClientConfig ribbonClientConfig; @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } @Bean public IRule ribbonRule(IClientConfig config) { return new AvailabilityFilteringRule(); } }
RestController:
@RestController public class WebController { @Autowired RestTemplate restTemplate; @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } @RequestMapping("/helloworld") public String home() { return this.restTemplate.getForObject("http://helloworld/greeting", String.class); } }
Klasa startowa:
@SpringBootApplication @RibbonClient(name = "ribbon-client", configuration = Configuration.class) public class SpringCloudClientApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudClientApplication.class, args); } }
Plik application.yaml:
spring: application: name: Ribbon-Client helloworld: ribbon: eureka: enabled: false listOfServers: localhost:8090,localhost:8091,localhost:8092 ServerListRefreshInterval: 1000 server: port: 8089
Po wywołaniu adresu:
http://localhost:8089/helloworld
za pomocą algorytmu load-balancera – Round Robin otrzymamy wynik:
Hello from a service running at port: 8090!
po kolejnym odświerzeniu adresu:
Hello from a service running at port: 8091!
i po następnym odświerzeniu adresu:
Hello from a service running at port: 8092!
W momencie kiedy jeden mikroserwis przestanie działać otrzymamy błąd – (niedziałająca usługa nie została wyrejestrowana – sztywna definicja w kodzie źródłowym aplikacji):
I/O error on GET request for "http://helloworld/greeting": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
Leave a comment