Service Discovery Eureka
Service Discovery Eureka
Instancje mikroserwisów mogą być uruchamiane w zależności o potrzeb. Mechanizm Service Discovery to rozwiązanie które dostarcza scentralizowany rejestr usług, które rejestrują się w nim samodzielnie przy starcie aplikacji. W momencie kiedy zarejestrowana usługa przestaje działać jest ona automatycznie usuwana z mechanizmu Service Discovery. Oznacza to, że mechanizm ten posiada wiedzę ile instancji danej usługi działa co w konsekwencji pozwala na rozproszenie ruchu w równomierny sposób. Do najpopularniejszych rozwiązań tego rodzaju należy – Spring Cloud Netflix Eureka.
[źródło:] http://dzone.com/articles/go-microservices-part-7-service-discovery-amp-load
Niezbędne zależności – stawiamy serwer discovery eureka:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-client</artifactId> <version>3.10.3</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Klasa startowa:
@SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaApplication.class, args); } }
Plik application.yaml:
server: port: 8761 eureka: server: enableSelfPreservation: false instance: hostname: localhost leaseRenewalIntervalInSeconds: 1 leaseExpirationDurationInSeconds: 2 serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Projekt – app-1 – 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-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Klasa startowa:
@SpringBootApplication @EnableDiscoveryClient public class SpringCloudEurekaApp1Application { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaApp1Application.class, args); } }
Klasa kontrolera:
@Controller public class AppController { @RequestMapping(value="/process", method = RequestMethod.GET) public @ResponseBody String showLoginPage(ModelMap model){ return "Processing aap on port: 8094"; } }
Plik application.properties:
server.port = 8094 eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/ spring.application.name = app-producer eureka.instance.instanceId = ${spring.application.name}:${random.int}
Projekt – app-2 – 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-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Klasa startowa:
@SpringBootApplication @EnableDiscoveryClient public class SpringCloudEurekaApp2Application { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaApp2Application.class, args); } }
Klasa kontrolera:
@Controller public class AppController { @RequestMapping(value="/process", method = RequestMethod.GET) public @ResponseBody String showLoginPage(ModelMap model){ return "Processing aap2 on port 8095"; } }
Plik application.properties:
server.port = 8095 eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/ spring.application.name = app-producer eureka.instance.instanceId = ${spring.application.name}:${random.int}
Projekt app-producer – 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-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Klasa startowa:
@SpringBootApplication public class SpringCloudEurekaAppProducerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaAppProducerApplication.class, args); } @Bean public Client client() { return new Client(); } }
Klasa klienta:
public class Client { @Autowired private LoadBalancerClient loadBalancer; public String getEmployee(String url) throws RestClientException, IOException { ServiceInstance serviceInstance = loadBalancer.choose("app-producer"); System.out.println(serviceInstance.getUri()); String baseUrl=serviceInstance.getUri().toString()+url; RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = null; try { response = restTemplate.exchange( baseUrl, HttpMethod.GET, getHeaders(), String.class); } catch (Exception ex) { System.out.println(ex); } return response.getBody(); } private static HttpEntity<?> getHeaders() throws IOException { HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.TEXT_PLAIN_VALUE); return new HttpEntity<>(headers); } }
Po uruchomieniu wszystkich aplikacji zauważyć można, że dwa projekty app-1 oraz app-2 zostały zarejestrowane przy ich starcie w Service Discovery Eureka:
Wywołując poniższy adres metodą GET protokołu HTTP np. z użyciem zwykłej przeglądarki:
http://localhost:7070/process
wynikiem będzie:
Processing aap on port: 8094
oraz w kolejnych wywołaniach zgodnie z algorytmem Round robin:
Processing aap2 on port 8095
Processing aap on port: 8094
Processing aap2 on port 8095
…
Jeśli usługa app-1 przestanie działać zostanie ona automatycznie wyrejestrowana z Eureki.
Czy aby na pewno
http://localhost:7070/process
?
Czy raczej jednak
http://localhost:8761/process
?
Cześć Paweł, sprawdzę i dam znać.