Zuul
案例1:搭建Zuul网关服务器
》1:创建工程导入依赖
在IDEA中创建ZUUL网关工程 Zuul-Server-C9008
可以通过复制Service-A9001之后修改
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
》2:编写启动类
创建启动类 C9008
@EnableZuulProxy : 通过 @EnableZuulProxy 注解开启Zuul网管功能
package com.dev1;
//省略导包
@SpringBootApplication
@EnableZuulProxy
public class C9008 {
public static void main(String[] args) {
SpringApplication.run(C9008.class,args);
}
}
》3:编写配置
创建配置文件 application.yml ,并添加相应配置
server:
port: 9008
spring:
application:
name: Zuul-Server-C9008
案例2:Zuul 中的路由转发
基础路由配置
最直观的理解:“路由”是指根据请求URL,将请求分配到对应的处理程序。在微服务体系中,Zuul负责接收所有的请求。根据不同的URL匹配规则,将不同的请求转发到不同的微服务处理。
只需要在 application.yml文件中配置路由规则即可:
server:
port: 9008
spring:
application:
name: Zuul-Server-C9008
zuul:
routes:
serivce-1:
path: /person-service/**
url: http://127.0.0.1:9001
# http://127.0.0.1:9001/person/find/2
person-service :配置路由id,可以随意取名
url :映射路径对应的实际url地址
path :配置映射路径,这里将所有请求前缀为/person-service/的请求,转发到http://127.0.0.1:9001
处理配置好Zuul路由之后启动服务,在浏览器中输入
http://localhost:9008/person-service/person/find/1
即可访问到微服务A。
内部过程:首先是
http://localhost:9008/person-service/person/find/1
符合符件/person-service/**则 将/person/find/1拼接到
url的后面 http://127.0.0.1:9001/person/find/2
面向服务的路由
Zuul支持与Eureka整合开发,根据ServiceID自动的从注册中心中获取服务地址并转发请求
(1)添加Eureka客户端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)开启Eureka客户端发现功能
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class C9008 {
public static void main(String[] args) {
SpringApplication.run(C9008.class,args);
}
}
(3)添加Eureka配置,获取服务信息
eureka:
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
client:
service-url:
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
(4)修改映射配置,通过服务名称获取
因为已经有了Eureka客户端,我们可以从Eureka获取服务的地址信息,因此映射时无需指定IP地址,而
是通过服务名称来访问,而且Zuul已经集成了Ribbon的负载均衡功能。
serviceId: 指定需要转发的微服务实例名称
zuul:
routes:
serivce-2:
path: /person-service/**
serviceId: Service-A9001
# http://localhost:9001/person/find/2
依次启动 Eureaka-Center8000,Eureaka-Center9000,Service-A9001,Zuul-Server-C9008,在浏览器上通过访问
http://localhost:9008/person-service/person/find/1
查看最终效果
简化的路由配置
在刚才的配置中,我们的规则是这样的:
zuul.routes.<route>.path=/xxx/** : 来指定映射路径。 <route> 是自定义的路由名
zuul.routes.<route>.serviceId=/person-service :来指定服务名。
而大多数情况下,我们的 <route>
路由名称往往和服务名会写成一样的。
因此Zuul就提供了一种简化的配置语法:
zuul.routes.<serviceId>=<path>
上面的配置可以简化为一条:
zuul:
routes:
Service-A9001: /person-service/**
# http://localhost:9001/person/find/2
默认的路由规则
在使用Zuul的过程中,上面讲述的规则已经大大的简化了配置项。
但是当服务较多时,配置也是比较繁琐的。因此Zuul就指定了默认的路由规则:
默认情况下,一切服务的映射路径就是服务名本身。
例如服务名为: Service-A ,则默认的映射路径就是: /Service-A/**
zuul:
routes:
Service-A9001: /Service-A9001/**
案例3:身份认证过滤器
自定义过滤器
接下来我们来自定义一个过滤器,模拟一个登录的校验。基本逻辑:如果请求中有access-token参数,则认为请求有效,放行。
先验证流程通过,再编写逻辑
package com.dev1.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import org.springframework.http.HttpStatus;
import javax.servlet.http.HttpServletRequest;
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre"; //定义过滤器类型
}
@Override
public int filterOrder() {
//指定过滤器的执行顺序
//返回值越小,执行顺序越高
return 1;
}
@Override
public boolean shouldFilter() {
//当前过滤器是否生效
return true;
}
/**
* 指定过滤器中的业务逻辑
* 身份认证:
* 1.所有的请求需要携带一个参数 : access-token
* 2.获取request请求
* 3.通过request获取参数access-token
* 4.判断token是否为空
* 4.1 token==null : 身份验证失败
* 4.2 token!=null : 执行后续操作
* 在zuul网关中,通过RequestContext的上下问对象,可以获取对象request对象
*/
@Override
public Object run() throws ZuulException {
//System.out.println("执行了过滤器");
//1.获取zuul提供的上下文对象RequestContext
RequestContext ctx = RequestContext.getCurrentContext();
//2.从RequestContext中获取request
HttpServletRequest request = ctx.getRequest();
//3.获取请求参数access-token
String token = request.getParameter("access-token");
//4.判断
if (token ==null) {
//4.1 如果token==null ,拦截请求,返回认证失败
ctx.setSendZuulResponse(false); // 拦截请求
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
//4.2 如果token!=null ,继续后续操作
return null;
}
}