Spring Cloud Zuul
Spring Cloud Zuul路由是微服务架构的不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
使用微服务来构建整个API服务时,系统会有不同职责的应用在运行着,没有统一的访问路径就会造成访问混乱难以维护,这就迫切需要zuul来提供统一的访问接口。
- zuul的存在的意义就是将“1对N”的问题转化为“1对1”问题,即进行请求转发,将用户的请求根据模块内定好的协议转发到响应的服务模块.在zuul的配置文件定义了路由转发协议。
- 在用户的请求真正达到微服务之前,可以进行一些预处理,如来源合法性的校验、权限校验、错误拦截等。
Zuul的实现
继续上篇文章的注册发现工程
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
启动类添加路由启动注解和允许跨域访问
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@SpringBootApplication
@EnableZuulProxy //开启路由
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
//实现前后端分离里,所有的服务接口调用都会经过zuul,所以使用CorsFilter来实现前端的跨域访问
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setMaxAge(18000L);
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
配置文件
#服务端口
server.port=8888
#服务名
spring.application.name=cloud-zuul
#多次请求的时候,会把这些header再带过来,然后请求zuul转发的接口又在写入一次,造成重复了,方案就是zuul转发的时候,过滤掉这些header
zuul.ssl-hostname-validation-enabled=false
#防止header出现双重Access-Control-Allow-Origin,Access-Control-Allow-Methods,进行过滤
zuul.routes.user.sensitiveHeaders=Access-Control-Allow-Origin,Access-Control-Allow-Methods
#通过注册发现路径映射
#Zuul的路由规则如下:http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
ribbon.ReadTimeout=60000
ribbon.ConnectTimeout=60000
#开启Ribbon的饥饿加载模式
ribbon.eager-load.enabled=true
#指定需要饥饿加载的服务名
ribbon.eager-load.clients=cloud-consumer
#请求的url规则
zuul.routes.user.path=/api/user/**
#转发到的服务名(负载均衡),user可随意写
zuul.routes.user.serviceId=cloud-consumer
#转发后url是否去掉前缀,即去掉/api/user/
zuul.routes.user.stripPrefix=true
进行安全验证时可以添加filter判断是否进行转发请求
- filterType:该函数需要返回一个字符串来代表过滤器的类型,而这个类型就是在HTTP请求过程中定义的各个阶段。在Zuul中默认定义了四种不同生命周期的过滤器类型,具体如下:
- pre:可以在请求被路由之前调用。
- routing:在路由请求时候被调用。
- post:在routing和error过滤器之后被调用。
- error:处理请求时发生错误时被调用。
- filterOrder:通过int值来定义过滤器的执行顺序,数值越小优先级越高。
- shouldFilter:返回一个boolean类型来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。
- run:过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。
/*
* @author uv
* @date 2018/10/9 11:06
* 过滤
*/
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
@Component
public class Filter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
//进行验证,例如token的合法性、参数的合法性验证等确定是否进行转发
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
ctx.setSendZuulResponse(true); //进行路由
return null;
}
}
测试
依次启动eureka,provider,sonsumer,zuul服务,http://localhost:8000/ ,如下
测试url:http://localhost:8888/api/user/test ,测试结果如下,调用成功。
github实例代码:https://github.com/UVliuwei/springcloud-demo