Introduction
Zuul is a Netflix JVM-based router and server-side load balancer. The most commonly used scenario is to replace the Nginx reverse proxy backend microservice for front-end UI access.
Zuul uses Ribbon to locate an instance that is forwarded by discovery, and all requests are executed with the hystrix command, so the failure will be displayed in the Hystrix metric.
Note: Zuul does not include the discovery client, so for service ID-based routes, one of the routes needs to be provided in the classpath.
Zuul is an API gateway and filtering component provided by Spring Cloud. It provides the following functions:
In this tutorial, we will use zuul to forward the web request/product to the corresponding product service, and define a pre filter to verify whether zuul has been forwarded.
Basic environment
Project source code
Click here
Create Zuul Service
Create a maven project in IntelliJ:
Then add the following code in pom.xml:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.zxuqian</groupId> <artifactId>apiGateway</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <!-- name has changed, before: spring-cloud-starter-zuul --> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <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-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependency> </dependency> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M9</version> <type>pom</type> <scope>import</scope> </dependency> </dependency> </dependencyManagement> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repository> </repository> </repository> </repositories></project>
It should be noted that the artifactId of zuul given by the Spring official website tutorial is spring-cloud-starter-zuul, which is the name of the old version of zuul. It has been renamed spring-cloud-starter-netflix-zuul in our Finchley.M9 version.
Add src/main/resources/bootstrap.yml file and specify spring.application.name:
spring: application: name: zuul-server
Create the cn.zxuqian.Application class:
package cn.zxuqian;import cn.zxuqian.filters.PreFilter;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;import org.springframework.context.annotation.Bean;@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public PreFilter preFilter() { return new PreFilter(); }}Here @EnableZuulProxy is used to specify a reverse proxy using zuul and forward our request to the corresponding server. Then eureka's service discovery was enabled. Zuul will also use Ribbon for load balancing by default, so you can discover registered services through eureka. PreFilter is a prefilter that performs some operations before the request request is processed. Its code is as follows:
package cn.zxuqian.filters;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;public class PreFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(PreFilter.class); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s method request %s", request.getMethod(), request.getRequestURL().toString())); return null; }} filterType - There are four built-in filter types in Zuul, pre, route, post, and error, which represent before, during, after, and after an error.
filterOrder - specifies the order in which the filter is executed.
shouldFilter - Whether to enable this filter.
run - The business logic of the filter. Here I just simply log the request method and request path of reqeust.
Next, create the zuul-server.yml file in the git repository in our configuration center and add the following configuration:
server: port: 8083zuul: routes: products: path: /product/** serviceId: product-service
Here, the port of zuul is configured to be 8083, and then all /product/ requests are mapped to our product-service service. If the serviceId is not configured, the products Key will be the ServiceId by default. In our example, the ServiceId includes -, so the ServiceId is specified below. Submit to git after configuration is complete.
Update productService
The URI of productService has been changed a little to make it more in line with rest style:
@RequestMapping("/list")public String productList() { log.info("Access to /products endpoint"); return "Coat, jacket, sweater, T-shirt";}Here, the path matching @RequestMapping is changed to /list, which was previously /products.
Update the web client
Add a new method to ProductService in our web client:
public String productListZuul() { return this.restTemplate.getForObject("http://zuul-server/product/list", String.class);}This time we directly request the zuul-server service, and then it will proxy our request to the product-service service. Finally, add a request handling method in the ProductController:
@RequestMapping("/product/list")public String productListZuul() { return productService.productListZuul();}Used to process /product/list requests, and then call methods in ProductService class.
test
Use mvn spring-boot:run to start configServer, registry, zuulServer, productService, and web projects, then start the second productService, and use SERVER_PORT=8082 spring-boot:run.
Visit http://localhost:8080/product/list several times, and in addition to seeing the returned results in the browser, we will also see the following words in the command line window of zuulServer:
GET method request http://xuqians-imac:8083/product/list
Then in the command line windows of the two productServices, we will also see random appearances
Access to /products endpoint
This means that zuulServer will also automatically load balancing.
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.