说明:
Spring Cloud Zuul是SpringClud的网关,我们知道,网关一般是应用的入口,做一些公共的和业务无关的校验工作,例如加验签、加解密等一些操作,而zuul作为微服务的网关,有如下原因:
1、作为系统的统一入口,屏蔽了微服务内部的实现细节;
2、与服务治理框架相结合(例如:Eureka),实现自动化的实例维护、以及负载均衡的路由转发;
3、实现接口的校验与微服务业务逻辑的解耦;
4、通过zuul中的各种过滤器,在各生命周期去校验请求内容,将原本对外服务层做的校验前移,保证了微服务的无状态性,同时降低了微服务的测试难度,让微服务更加关注本身的业务逻辑的处理;
好了,接下来我们开始一个zuul网关服务:
一、引入zuul的pom以来:
<?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>com.ck.springcloud</groupId>
<artifactId>hello-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.7.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</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>
</project>
因为Zuul要结合Eureka使用,所以也要引入Eureka的依赖,下面会讲解Zuul怎么和Eureka的结合使用;
二、增加启动类,增加Zuul的启动配置注解@EnableZuulProxy:
package controller;
import com.netflix.zuul.FilterLoader;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableZuulProxy
@EnableConfigurationProperties(FilterConfiguration.class)
public class Application {
FilterConfiguration filterConfiguration;
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
@Bean
public AccessFilter getAccessFilter(){
return new AccessFilter();
}
@Bean
public FilterConfiguration filterLoader(FilterConfiguration filterConfiguration){
this.filterConfiguration = filterConfiguration;
System.out.println(filterConfiguration.getInterval()+filterConfiguration.getRoot());
return filterConfiguration;
}
}
三、增加配置文件application.yml文件:
spring:
application:
name: api-gateway
server:
port: 5555
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
zuul:
routes:
api-a:
path: /api-a/**
url: http://localhost:8080
api-b:
path: /api-b/**
serviceId: feign-consumer
AccessFilter:
pre:
disable: true
zuuls:
filter:
root: filter
interval: 5
在上面的配置中,我们配置了2个路由规则:
1、是/api-a/**的请求都会转发到http://localhost:8080
2、/api-b/**的请求都会通过Ribbon负载均衡随机转发到微服务名feign-consumer(通过与Eureka注册中心结合,动态的获取所有微服务实例)的实例上;
通过简单的配置,现在一个简单的Spring Cloud Zuul网关就实现了!
Zuul中还可以增加过滤器,在转发请求到微服务之前做拦截过滤,实现过滤器很简单,只要集成ZuulFilter父类;
例子:
package controller;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
public class AccessFilter extends ZuulFilter {
//表明这是一个前置过滤器,在转发到微服务之前执行
@Override
public String filterType() {
return "pre";
}
//多个过滤器之前,通过返回的order判断过滤器的执行顺序
@Override
public int filterOrder() {
return 0;
}
//这个过滤器是否执行,true表示执行
@Override
public boolean shouldFilter() {
return true;
}
//具体的拦截执行逻辑,过去逻辑是如果请求参数中没有accessToken就拦截此次请求
//否则通过
@Override
public Object run() {
System.out.println("access token start");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest httpServletRequest = requestContext.getRequest();
Object accessToken = httpServletRequest.getParameter("accessToken");
if(accessToken == null){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(401);
return null;
}
System.out.println("access token ok");
return null;
}
}
最后别忘记了,在Application启动类中将AccessFilter注册成bean:
@Bean
public AccessFilter getAccessFilter(){
return new AccessFilter();
}
禁用过滤器的方法,一种是修改过滤器的shouldFilter方法,这种方法缺乏灵活性,需要修改程序,第二种方式是增加配置:
zuul.<SimpleClassName>.<filterType>.disable=true
其中SimpleClassName代表过滤器的类名,filterType代表过滤器的类型;