1. Zuul基本概念
1.1. What is Zuul?
Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.
1.2. Why did we build Zuul?
The volume and diversity of Netflix API traffic sometimes results in production issues arising quickly and without warning. We need a system that allows us to rapidly change behavior in order to react to these situations.
Zuul uses a range of different types of filters that enables us to quickly and nimbly apply functionality to our edge service. These filters help us perform the following functions:
- Authentication and Security – identifying authentication requirements for each resource and rejecting requests that do not satisfy them.
- Insights and Monitoring – tracking meaningful data and statistics at the edge in order to give us an accurate view of production.
- Dynamic Routing – dynamically routing requests to different backend clusters as needed.
- Stress Testing – gradually increasing the traffic to a cluster in order to gauge performance.
- Load Shedding – allocating capacity for each type of request and dropping requests that go over the limit.
- Static Response handling – building some responses directly at the edge instead of forwarding them to an internal cluster
- Multiregion Resiliency – routing requests across AWS regions in order to diversify our ELB usage and move our edge closer to our members
2. 构建Zuul服务
我们构建两个服务:Book服务,提供图书借阅服务;网关服务,作为request统一入口,将request重定向到Book。
2.1. 构建Book服务
BookApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class BookApplication {
@RequestMapping(value = "/getbook")
public String getBook() {
return "get book success!";
}
public static void main(String[] args) {
SpringApplication.run(BookApplication.class, args);
}
}
Book/resources/application.properties
spring.application.name=book
server.port=8090
2.2. 构建网关服务
引入Zuul依赖 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
编写Zuul拦截器。Zuullan拦截器必须继承ZuulFilter类,同时覆盖filterType()、filterOrder()、shouldFilter()、run()四个方法。
- filterType():拦截类型,包括,前置拦截”pre”,路由中拦截”route”,后置拦截”post”,异常拦截”error”;
- filterOrder(): 拦截等级,即filter执行的先后顺序;
- shouldFilter():是否拦截;
- run():拦截器的主体方法
这里我们构建一个SimpleFilter作为例子
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}
配置路由规则。因为本例不使用eureka进行服务注册,所以禁用掉eureka
zuul.routes.books.url=http://localhost:8090
ribbon.eureka.enabled=false
server.port=8080
最后,程序主入口中加入@EnableZuulProxy,该注解将为GatewayApplication添加反向代理功能。
同时,加入对SimpleFilter的调用
@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public SimpleFilter simpleFilter() {
return new SimpleFilter();
}
}
3. 测试
访问http://localhost:8080/books/getbook,可以看到请求已经被重定向到Book服务
查看getway服务的日志,拦截器也输出了日志。
参考: