SpringCloud Zuul 网关路由
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现(eureka)、服务消费(consume)、负载均衡(hibbon)、断路器(hystrix)、智能路由(zuul)、配置管理(config)等;
Zuul 网关路由
由于在不同的作用域下所以要进行跨域的操作,所以用网关路由,ajax请求发送到网关路由,网关路由进行分发到不同的域下
Zuul是Netflix开源的微服务网关,他可以和Eureka,Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系
列的过滤器,这些过滤器可以完成以下功能:
身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求
审查与监控:
1.动态路由:动态将请求路由到不同后端集群
2.压力测试:逐渐增加指向集群的流量,以了解性能
3.负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
4.静态响应处理:边缘位置进行响应,避免转发到内部集群
5.多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化
spring-cloud-starter-zuul 是 Spring Cloud对Zuul功能的整合和增强。
实现ZUUL步骤:
1>创建SpringBoot项目,引入依赖pring-cloud-starter-eureka
spring-cloud-starter-zuul
2>项目配置文件application.yml中配置注册中心地址
3>在入口函数使用 @EnableZuulProxy注解启用Zuul网关路由
(1)pom.xml主要依赖
<!-- SpringBoot 项目 统一 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<!-- SpringCloud Eureka 注册中心 依赖 -->
<dependency>
重点注意:
引入Eureka客户端依赖 spring-cloud-starter-eureka
引入网关zuul依赖 spring-cloud-starter-zuul
6.3.2 配置项目配置文件
在项目配置文件application.yml中配置eureka,其它无特殊配置
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- SpringCloud Zuul 网关路由 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
<!-- SpringCloud 所有子项目 版本集中管理.MS:统一所有SpringCloud依赖项目的版本 依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- SpringBoot 项目打jar包的Maven插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<!-- SpringBoot项目打包jar名称 -->
<finalName>zuul</finalName>
</build>
<!-- SpringCloud 官方远程仓库.MS:部分本地仓库和镜像仓库没有SpringCloud子项目依赖。 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
(2)在项目配置文件application.yml中配置eureka
eureka:
client:
serviceUrl:
#eureka注册中心地址
defaultZone: http://localhost:8888/eureka/
server:
#项目端口号
port: 8889
spring:
application:
#服务名称,随便写
name: service-zuul
(3)修改入口函数
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@SpringCloudApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
分别启动
springcloud-eureka 、 springcloud-provider 、 springcloud-consumer-feign
springcloud-zuul
通过网关路由访问springcloud-provider和 springcloud-consumer-feign 的controller方法
#---------------- 默认路由规则 -----------------------
#使用Eureka注册中心则zuul服务网关会自动生成以下路由规则
#zuul:
# routes:
# api-a:
# path: /service-provider/**
# service-id: service-provider
# api-b:
# path: /service-consumer/**
# service-id: service-consumer
分别是路由网管的端口号,提供者的服务名称,提供服务的controller的方法
网关过滤器的实现步骤
在springcloud-zuul项目的Spring容器中加入网关过滤器com.netflix.zuul.ZuulFilter抽象类的子实现类,
package com.ysd.filter;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@Component
public class ZuulTokenFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(ZuulTokenFilter.class);
@Override
public String filterType() {
return "pre";//过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为pre,代表会在请求被路由之前执行。
}
@Override
public int filterOrder() {
return 0;//过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。
}
@Override
public boolean shouldFilter() {
return true;//判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。
}
/**
* 过滤器的具体逻辑。 这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,
* 然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,
* 当然我们也可以进一步优化我们的返回,比如,通过ctx.getResponse()对响应内容进行编辑等。
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("token");
String refer = request.getHeader("refer");
if (accessToken != null) {
return null;// 网关路由放行
}
log.warn("token is empty");
ctx.setSendZuulResponse(false);// 网关路由过滤不路由
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("token is empty");
} catch (Exception e) {
}
return null;// 网关路由放行
}
}
访问 http://localhost:8889/service-consumer/getProviderFuture?
token=666 会被网关过滤器放行并正常路由到 http://localhost:8002/getFuture?token=666 说明网关
过滤器组件运行正常。