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.

Zobacz kod na GitHubie i zapisz się na bezpłatny newsletter!

.

2 Comments

Leave a comment

Your email address will not be published.


*