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ństwo – nie każde zapytanie powinno być w systemie zrealizowane,
- zarządzanie ruchem – definiowanie 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 awarie – kiedy 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ę:
[źródło] http://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(); httpervletRequest 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:
[źródło] http://www.slideshare.net/doanduyhai/cassandra-drivers-and-libraries
Polecam również zapoznać się z :
Leave a comment