介绍
Springcloud目前的服务网关有Zuul和Springcloud Getway。Zuul是Netflix公司公司开源项目。在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务端。
Zuul的一些作用:
- 权限问题统一处理
- 数据裁剪和聚合
- 简化客户端的调用
- 可以针对不同的客户端提供不同的网关支持。
简单使用
新建一个Springboot项目。
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
</dependency>
2.启动类添加注解
@SpringBootApplication
@EnableZuulProxy //开启网关代理
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
3.配置文件
spring:
application:
name: zuul
server:
port: 2020
eureka:
client:
service-url:
defaultZone: http://localhost:1111/eureka
4.启动测试
启动zuul、eureka-server、eureka-provider。访问http://localhost:2020/eureka-provider/hello,可以看到对应消息。说明Zuul成功调用了eureka-provider,通过Zuul转发给对应的服务(eureka-provider)进行处理。
路由映射配置
1.配置文件
zuul:
routes:
pikachues:
path: /pikachues/**
service-id: eureka-provider
满足/pikachues/**
匹配的请求,将转发到eureka-provider实例处理。
- 简化配置
zuul:
routes:
eureka-provider: /pikachues/**
2.重新启动Zuul
这时你会发现通过http://localhost:2020/eureka-provider/hello和http://localhost:2020/pikachues/hello都可以成功调用。
3.原真实服务名忽略
即让调用只可以通过Zuul配置的规则访问,不可以通过原来的服务名访问。
zuul:
routes:
pikachues:
path: /pikachues/**
service-id: eureka-provider
# ignored-services: eureka-provider
ignored-services: "*"
如果是忽略某一个ignored-services中填具体名称,忽略多个用*。这时候重新启动启动Zuul项目,你会发现只能通过http://localhost:2020/pikachues/hello调用,另外一个调用失败。
4.设置统一公共前缀
zuul:
routes:
pikachues:
path: /pikachues/**
service-id: eureka-provider
# ignored-services: eureka-provider
ignored-services: "*"
prefix: /dpf
这时候重新启动访问:http://localhost:2020/dpf/pikachues/hello
请求过滤
对于来自客户端的请求,可以在Zuul中进行预处理,例如权限判断等。
1.定义一个简单的权限过滤器
public class PermissionFilter extends ZuulFilter {
/**
* 过滤器类型,权限判断一般是 pre
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器优先级
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否过滤
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 核心的过滤逻辑写在这里
* @return 这个方法虽然有返回值,但是这个返回值目前没什么用
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();//获取当前请求
String username = request.getParameter("username");
String password = request.getParameter("password");
if (!"pikahuces".equals(username) || !"123".equals(password)) {
//如果请求条件不满足的话,直接从这里给出响应
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
ctx.setResponseBody("非法访问");
}
return null;
}
}
2.重新启动Zuul
这时候发送请求必须带上username和password两个参数,否则不能通过。
测试:http://localhost:2020/pikachues/hello?username=pikachues&password=123