1.什么是zuul?
Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
路由转发很容易理解,之前都是访问每个服务的端口,8081,8082等,现在我们需要统一的网关,来管理这些端口,比如所有的服务都统一由9000进入,统一一个入口,这样对后面的端口管理等都有很大的好处
过滤就是在统一入口的基础上,进一步功能的封装,比如现在都是走9000端口了,我们可以在zuul服务统一的进行token设置,编码管理和跨域处理等,不需要后面每个服务都单独考虑这些通用的问题。
2.zuul快速入门
新建一个model模块,叫zuul,需要注册到注册中心,然后配置下,加上启动注解即可。
注意有个坑,我的SpringBoot版本过高,后面会报错,需要提前降低版本。
springboot 在2.4版本之后就不支持zuul 改用Gateway 如果还要用zuul的话 把springboot
和springcloud的版本降低就好了
之前就SpringBoot和Spring’Cloud版本冲突已经改了一个版本了,现在又因为版本和zuul冲突,后面我们学习gateway就可以用最新版本了
我现在还是改成最熟悉的版本吧
SPringBoot版本 2.2.1.RELEASE
SpringCloud版本 Hoxton.SR12
这块一定要降版本2.4版本之后的肯定会有问题。
2.1 pom文件
<dependencies>
<!--引入eureka的客户端依赖-->
<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>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
2.2 applation.yml
server:
port: 9000
spring:
application:
name: zuul
# Eureka配置:配置服务注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka
instance:
prefer-ip-address: true
hostname: localhost
zuul:
routes:
demo1:
path: /demo1/**
service-id: demo1
baidu:
path: /baidu/**
url: http://www.baidu.com
我们的demo1是注册中心上的服务名称,service-id我们可以重新命名,但是一般不需要。
2.3 启动类加上@EnableZuulProxy注解
package com.liu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class zuulApplication {
public static void main(String[] args) {
SpringApplication.run(zuulApplication.class, args);
}
}
启动测试,localhost:9000 + baidu 直接跳转说明zuul启动成功,
后面我们通过localhost:9000 + demo1(服务名) +demo1 接口 即可访问。
这样后面,我们所有的服务访问都通过9000加上注册中心中的服务名称即可。
3 过滤
过滤就是根据上面的通一入口来的了,我们既然设置了通用的入口,那么所有的跨域问题和token验证等都在这一层设置即可。
3.1 新增AuthFilter继承ZuulFilter
package com.liu.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Service;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
@Service
public class AuthFilter extends ZuulFilter {
//filter的类型,前置pre,后置post
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
//filter的执行顺序,值越小,越先执行
@Override
public int filterOrder() {
return 1;
}
//判断请求是否需要过滤
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request.getRequestURI().contains("demo1")) { //含有demo1需要过滤,当路径中只有部分匹配时,也要进行过滤
return true;
}
return false;
}
//请求过滤的规则
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
//解决浏览器跨域问题
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Expose-Headers", "Location");
return null;
}
}
shouldFilter() 一般默认true,所有的都开启过滤。
当然也可以根据注册中心中微服务名称选择过滤,
具体的过滤规则放在run中,上面只写了跨域问题,其他过着加上即可。
之前跨域问题生产环境还遇到个大坑,跨域问题