Spring Cloud Zuul
The development environment
- The idea of 2019.1.2
- Jdk1.8.0 _201
- Spring Boot 2.1.9. RELEASE
- Spring Cloud Greenwich SR3
Zuul introduction
Zuul is a gateway service developed by Netflix that provides dynamic routing, monitoring, flexibility, and security. It can be used with Eureka,Ribbon,Hystrix, and other components. Verification filtering can also be supported by creating filters to make microservice applications more focused on business logic development.
The advantage of using Zuul Gateway services is to provide REST apis to external systems in a unified way, with additional functions such as permission control, load balancing, and so on, that exist separately from the original services.
Zuul provides different types of filters for processing requests that allow us to do the following
- Permission control and security: Identifies information needed for authentication and rejects requests that do not meet the criteria
- Monitor: Monitors request information
- Dynamic routing: Dynamically routes requests to different service clusters in the background as required
- Stress test: Ramp up the traffic to the cluster for performance evaluation
- Load balancing: Allocates capacity for each type of request and discards requests that exceed the quota
- Current limiting
- Blacklist and whitelist filtering
- Static resource processing: Responses to static resources are handled directly in Zuul without the need to forward these requests to the internal cluster
The filter
ZuulFilter is a basic abstract class that defines some abstract methods
-
FilterType: filter type, including “pre”, “route”, “post”, “error”, “static”
- Pre: executed before the request is routed
- Route: Executed when the request is routed
- Post: Executed after the request has been routed
- Error: Executed when an error occurs in the request
- Static: Special Filter see StaticResponseFilter, which allows the response to be generated from Zuul itself, rather than forwarding the request to the source
-
FilterOrder method: Priority, higher level, faster execution (lower value indicates higher level)
-
ShouldFilter method: switch, if true, the run method is executed, otherwise not
-
The run method: logical operation performed by filter
Code implementation
1. Create a service registry
Create zuul-Eureka-server project, introduce Eureka-server dependency, project complete source code can be viewed: Spring Cloud Zuul sample source code
Here are some key pieces of code
Pom adds dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Copy the code
The @enableeurekaserver annotation is added to the startup class
@EnableEurekaServer
@SpringBootApplication
public class ZuulEurekaServerApplication {
public static void main(String[] args) { SpringApplication.run(ZuulEurekaServerApplication.class, args); }}Copy the code
Yml configuration
server:
port: 8761
spring:
application:
name: zuul-eureka-server
eureka:
instance:
hostname: localhost # eureka instance name
client:
register-with-eureka: false # Do not register yourself with the registry
fetch-registry: false # Whether to retrieve services
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ Registry access address
Copy the code
2. Create service provider 1
Create zuul-server-provider project, introduce Eureka-client dependency, project complete source code can be viewed: Spring Cloud Zuul example source code
Here are some key pieces of code
Pom adds dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Copy the code
Write the HelloController service
@RestController
@Slf4j
public class HelloController {
@RequestMapping("/hello")
public String index(@RequestParam String name) {
log.info("request one name is " + name);
return "hello " + name + "This is the first messge"; }}Copy the code
The startup class adds the @enableDiscoveryClient annotation
@SpringBootApplication
@EnableDiscoveryClient
public class ZuulServerProviderApplication {
public static void main(String[] args) { SpringApplication.run(ZuulServerProviderApplication.class, args); }}Copy the code
Yml configuration
spring:
application:
name: zuul-server-provider
server:
port: 9000
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
Copy the code
3. Create service provider 2
Create zuul-server-provider2 project, introduce eureka-client dependency, other same service provider 1 project, project complete source code can be seen: Spring Cloud Zuul sample source code
The difference code is posted below
Write the service, here to do service degradation test, set the current thread to a very long sleep time
@RestController
@Slf4j
public class HelloController {
@RequestMapping("/hello")
public String index(@RequestParam String name) {
log.info("request two name is " + name);
try{
// To perform a service degradation test, set a very long sleep time, deliberately causing the service access to timeout
Thread.sleep(1000000);
}catch ( Exception e){
log.error(" hello two error",e);
}
return "hello " + name + ", this is two messge"; }}Copy the code
4. Create zuul service gateway
Create zuul-server-gateway project, introduce Netflix-Zuul and Eureka-client dependencies, project complete source code can be viewed: Spring Cloud Zuul example source code
Here are some key pieces of code
Pom. The XML configuration
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
Copy the code
Create a filter tokenfilter.java
package com.easy.zuulServerGateway.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class TokenFilter extends ZuulFilter {
@Override
public String filterType(a) {
// Can be called before the request is routed
return "pre";
}
@Override
public int filterOrder(a) {
//filter Execution sequence. The priority is 0. A larger number indicates a lower priority
return 0;
}
@Override
public boolean shouldFilter(a) {
// Whether to run the filter. If the value is true, filtering is required
return true;
}
@Override
public Object run(a) {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString());
// Get the request parameters
String token = request.getParameter("token");
if (StringUtils.isNotBlank(token)) {
// Route requests
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
ctx.set("isSuccess".true);
return null;
} else {
// Do not route it
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(400);
ctx.setResponseBody("token is empty");
ctx.set("isSuccess".false);
return null; }}}Copy the code
Create a fuse corresponding to the Zuul-server-provider service (fusing for the entire service or for a single service interface), providerFallback.java
package com.easy.zuulServerGateway.fallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@Slf4j
@Component
public class ProviderFallback implements FallbackProvider {
@Override
public String getRoute(a) {
return "zuul-server-provider";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
if(cause ! =null) {
String reason =cause.getMessage();
log.info("Excption {}", reason);
}
return fallbackResponse();
}
public ClientHttpResponse fallbackResponse(a) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode(a) {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode(a) {
return 200;
}
@Override
public String getStatusText(a){
return "OK";
}
@Override
public void close(a) {}@Override
public InputStream getBody(a) {
return new ByteArrayInputStream("The service is unavailable.".getBytes());
}
@Override
public HttpHeaders getHeaders(a) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
returnheaders; }}; }}Copy the code
Yml configuration
spring:
application:
name: zuul-service-gateway
server:
port: 8888
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
# Whether to enable the retry function
zuul:
retryable: true
Number of retries for the current service
ribbon:
MaxAutoRetries: 2
# Number of times to switch the same Server
MaxAutoRetriesNextServer: 0
Copy the code
Start the class add @ EnableZuulProxy annotations, to start the service gateway ZuulServerGatewayApplication. Java
package com.easy.zuulServerGateway;
import com.easy.zuulServerGateway.filter.TokenFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableZuulProxy
public class ZuulServerGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerGatewayApplication.class, args);
}
@Bean
public TokenFilter tokenFilter(a) {
return newTokenFilter(); }}Copy the code
First, the four services of the sample are created, and then run the sample to see the effect
use
The four existing projects are as follows
Zuul-eureka-server: service registry, service name: zuul-Eureka-server, port: 8761 Zuul-server-provider: service provider 1, service name: zuul-server-provider, port: 8761 9000 Zuul-server-provider2: indicates the service provider. Service name: indicates the zuul-server-provider. Port: indicates the 9001 zuul-server-gateway: indicates the service gateway. 8888
Run the test
Start zuul-Eureka-server, zuul-server-gateway, and zuul-server-provider respectively
- Access the address: http://localhost:8888/zuul-server-provider/hello? Name =yuntian, return: token is empty, request intercepted return.
- Access the address: http://localhost:8888/zuul-server-provider/hello? Name =yuntian&token=xx, return: hello yuntian, this is first messge, indicating a normal response to the request.
Start the zuul – server – provider2
- Many times visit http://localhost:8888/zuul-server-provider/hello? Name =yuntian&token=xx
Hello yuntian, this is first messge The service is unavailable...Copy the code
The zuul-server-provider2 project has enabled a circuit breaker, and The service is unavailable.
data
- Spring Cloud Zuul example source code
- Spring Boot, Spring Cloud example learning