Spring Cloud Zuul


Spring Cloud Zuul

Zuul to  serwer pracujący w charakterze API Gateway – bramy do systemu, czyli fasady, pod którą kryją się wywołania danych mikroserwisów. Takie rozwiązanie daje dostęp do usług w sposób zunifikowany. Na podstawie zdefiniowanych filtrów ruch kierowany jest do konkretnych mikroserwisów. Do zalet wzorca Api Gateway należą:

  • bezpieczeństwonie każde zapytanie powinno być w systemie zrealizowane,
  • zarządzanie ruchemdefiniowanie filtrów i kierowanie do konkretnych mikroserwisów,
  • testowanie ruch można skierować na nowe usługi w celu ich przetestowania a kiedy coś pójdzie nie tak ruch można zawsze skierować na działający serwis,
  • monitoring wiemy jak ruch jest rozdzielany na poszczególne usługi,
  • odporność na awariekiedy coś nie działa ruch może być skierowany do innych serwisów,
  • opakowanie żądania w dodatkowe nagłówki.

W artykule zaprojektujemy następującą architekturę:

boot-25_3

[źródło] https://www.javainuse.com/spring/spring-cloud-netflix-zuul-tutorial

Konfigurujemy Service Discovery – Eureka – niezbędne zależności:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</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-eureka</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</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:

@EnableEurekaServer
@SpringBootApplication
public class SpringCloudEurekaServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudEurekaServerApplication.class, args);
	}
}

Plik application.properties:

#Port for Registry service
server.port                         = 8761
 
#Service should not register with itself
eureka.client.register-with-eureka  = false
eureka.client.fetch-registry        = false
 
#Managing the logging
logging.level.com.netflix.eureka    = OFF
logging.level.com.netflix.discovery = OFF

API Gateway – Zull – niezbędne zależności:

<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-zuul</artifactId>
	</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>

Plik application.properties:

# Application Config
server.port                      = 8082
spring.application.name          = API-Gateway
 
# Eureka Config
eureka.client.eureka-server-port = 8761
 
# Test service mapping
zuul.routes.hello.path           = /hello/**
zuul.routes.hello.serviceId      = app

Klasa startowa:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class SpringCloudApiGatewayApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudApiGatewayApplication.class, args);
	}
 
	@Bean
	public SimpleFilter simpleFilter() {
		return new SimpleFilter();
	}
}

Klasa filtru – filtrowanie żądań:

public class SimpleFilter extends ZuulFilter {
 
    private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
 
    @Override
    public String filterType() {
        return "pre";
    }
 
    @Override
    public int filterOrder() {
        return 1;
    }
 
    @Override
    public boolean shouldFilter() {
        return true;
    }
 
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("SAMPLE FILTER LOG] %s request to %s", request.getMethod(), request.getRequestURL().toString()));
        return null;
    }
}

Mikroserwis – App – 1 – niezbędne zależności:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</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</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</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.SR6</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

RestController:

@RestController
public class PortController {
 
    @RequestMapping
    public String helloWorld() {
        return "Hello World";
    }
 
    @RequestMapping("/port")
    public String appPort() {
        return "app port: 8081";
    }
}

Plik application.properties:

# Application Config
server.port                      = 8081
spring.application.name          = app
 
# Eureka Config
eureka.client.eureka-server-port = 8761

Klasa startowa:

@SpringBootApplication
@EnableEurekaClient
public class SpringCloudAppApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudAppApplication.class, args);
	}
}

Mikroserwis – App – 2 – zależności są dokładnie takie same jak dla mikroserwisu pierwszego.

RestController:

@RestController
public class PortController {
 
    @RequestMapping
    public String helloWorld() {
        return "Hello World";
    }
 
    @RequestMapping("/port")
    public String appPort() {
        return "app port: 8086";
    }
}

Plik application.properties:

# Application Config
server.port                      = 8086
spring.application.name          = app
 
# Eureka Config
eureka.client.eureka-server-port = 8761

Klasa startowa:

@SpringBootApplication
@EnableEurekaClient
public class SpringCloudAppApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudAppApplication.class, args);
	}
}

Czas na testy!

http://localhost:8082/hello/port

Odświeżając powyższy adres kilkukrotnie zauważyć można, że Zull domyślnie używa mechanizmu Ribbon Load Balancer. Round Robin Load Balancer oznacza, że każde kolejne żądanie kierowane jest kolejno do aktywnej instancji danego mikroserwisu. Cykl ten jest powtarzany:

Znalezione obrazy dla zapytania round robin balancing

[źródło] https://www.slideshare.net/doanduyhai/cassandra-drivers-and-libraries

Polecam również zapoznać się z :


Leave a comment

Your email address will not be published.


*