SpringCloud(三) Zuul
Zuul
有了eureka 、 feign 和 hystrix 后,基本上就搭建了简易版的分布式项目,但仍存在一些问题,比如:
1、如果我们的微服务中有很多个独立服务都要对外提供服务,那么我们要如何去管理这些接口?特别是当项目非常庞大的情况下要如何管理?
2、在微服务中,一个独立的系统被拆分成了很多个独立的服务,为了确保安全,权限管理也是一个不可回避的问题,如果在每一个服务上都添加上相同的权限验证代码来确保系统不被非法访问,那么工作量也就太大了,而且维护也非常不方便。
所以出现了网关,它就像一个安检站一样,所有外部的请求都需要经过它的调度与过滤,然后 API 网关来实现请求路由、负载均衡、权限验证等功能。
使用 Zuul 构建 API 网关
创建spring boot工程并添加依赖:
<!--添加 spring cloud 的 zuul 的起步依赖--> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--添加 spring cloud 的 eureka 的客户端依赖--> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在入口类上添加@EnableZuulProxy 注解,开启 Zuul 的 API 网关服务功能:
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class SpringcloudZuulApplication { public static void main(String[] args) {
SpringApplication.run(SpringcloudZuulApplication.class, args);
} }
在application.yml中添加路由规则
# 配置路由规则
zuul:
routes:
hello:
path: /api-zuul/**
serviceId: springcloud-consumer
说明:以上配置的路由规则就是匹配所有符合/api-zuul/**的请求,只要路径中带有/api-zuul/都将被转发到 springcloud-consumer 服务上。比如:localhost:8766/api-zuul/web/hello转发到 http://localhost:8764/web/hello
构建成功
使用 Zuul 进行请求过滤
定义一个过滤器类并继承自 ZuulFilter,并将该 Filter 作为一个 Bean:
@Component
public class AuthFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
} @Override
public int filterOrder() {
return 0;
} @Override
public boolean shouldFilter() {
return true;
} @Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if (token == null) {
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401); ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
ctx.setResponseBody("非法访问");
}
return null;
}
}
- filterType 方法的返回值为过滤器的类型,决定了过滤器在哪个生命周期执行,pre 表示在路由之前执行过滤器,其他值还有 post、error、route 和 static,当然也可以自定义。
- filterOrder 方法表示过滤器的执行顺序,当过滤器很多时,我们可以通过该方法的返回值来指定过滤器的执行顺序。
- shouldFilter 方法用来判断过滤器是否执行,true 表示执行,false 表示不执行。
- run 方法则表示过滤的具体逻辑,如果请求地址中携带了 token 参数的话,则认为是合法请求,否则为非法请求,如果是非法请求的话,首先设置ctx.setSendZuulResponse(false),表示不对该请求进行路由,然后设置响应码和响应值。这个 run 方法的返回值目前暂时没有任何意义,可以返回任意值。
不携带token,localhost:8766/api-zuul/web/hello
携带token,localhost:8766/api-zuul/web/hello?token=213
Zuul 的路由规则
在前面的例子中,
zuul:
routes:
hello:
path: /api-zuul/**
serviceId: springcloud-consumer
当访问地址符合 /api-zuul/ 规则的时候,会被自动定位到springcloud-consumer 服务上,有点麻烦,还可以简化为:
zuul:
routes:
springcloud-consumer: /api-zuul/**
zuul.routes 后面跟着的是服务名,服务名后面跟着的是路径规则,这种配置方式更简单。
默认情况下,Eureka 上所有注册的服务都会被 Zuul 创建映射关系来进行路由。
#默认的规则
zuul.routes.springcloud-consumer.path=/springcloud-consumer/**
zuul.routes.springcloud-consumer.serviceId=springcloud-consumer
但如果希望 springcloud-service-provider 作为服务提供者只对服务消费者提供服务,不对外提供服务:
zuul.ignored-services=springcloud-service-provider
还可以进一步细化,比如不想给/hello 接口路由:
zuul.ignored-patterns=/**/hello/**
也可以统一的为路由规则增加前缀:
zuul.prefix=/myapi
路由规则通配符:
一般情况下 API 网关只是作为各个微服务的统一入口,但是有时候我们可能也需要在 API 网关服务上做一些特殊的业务逻辑处理,那么我们可以让请求到达 API 网关后,再转发给自己本身,由 API 网关自己来处理,那么我们可以进行如下的操作:
@RestController
public class GateWayController {
@RequestMapping("/api/local")
public String hello() {
return "exec the api gateway.";
}
}
在 application.yml 中:
zuul:
routes:
gateway:
path: /gateway/**
url: forward:/api/local
Zuul 的异常处理
首先看一下Zuul 请求的生命周期:
- 正常情况下所有的请求都是按照 pre、route、post 的顺序来执行,然后由 post 返回 response
- 在 pre 阶段,如果有自定义的过滤器则执行自定义的过滤器
- pre、routing、post 的任意一个阶段如果抛异常了,则执行 error 过滤器
有两种方式统一处理异常:
禁用 zuul 默认的异常处理 SendErrorFilter 过滤器,然后自定义我们自己的 Errorfilter 过滤器
zuul:
routes:
springcloud-consumer: /api-zuul/**
SendErrorFilter:
error:
disable: true
@Component
public class ErrorFilter extends ZuulFilter {
private static final Logger logger =
LoggerFactory.getLogger(ErrorFilter.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
try {
RequestContext context = RequestContext.getCurrentContext();
ZuulException exception = (ZuulException)context.getThrowable();
logger.error("进入系统异常拦截", exception);
HttpServletResponse response = context.getResponse();
response.setContentType("application/json; charset=utf8");
response.setStatus(exception.nStatusCode);
PrintWriter writer = null;
try {
writer = response.getWriter();
writer.print("{code:"+ exception.nStatusCode +",message:\""+
exception.getMessage() +"\"}");
} catch (IOException e) {
e.printStackTrace();
} finally {
if(writer!=null){
writer.close();
}
}
} catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e);
}
return null;
}
}
在 AuthFiler 里的run()方法添加异常
int i = 10 / 0
自定义全局 error 错误页面
开启 zuul 默认的异常处理 SendErrorFilter 过滤器,并注释掉 ErrorFilter 类
@RestController
public class ErrorHandlerController implements ErrorController {
/**
* 出异常后进入该方法,交由下面的方法处理
*/
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public Object error(){
RequestContext ctx = RequestContext.getCurrentContext();
ZuulException exception = (ZuulException)ctx.getThrowable();
return exception.nStatusCode + "--" + exception.getMessage();
}
}
SpringCloud(三) Zuul的更多相关文章
- springcloud学习之路: (三) springcloud集成Zuul网关
网关就是做一下过滤或拦截操作 让我们的服务更加安全 用户访问我们服务的时候就要先通过网关 然后再由网关转发到我们的微服务 1. 新建一个网关服务Module 2. 依然选择springboot工程 3 ...
- Oauth2.0 整合springCloud的Zuul 解决关键BUG 报错信息:Principal must not be null
不清楚Oauth2.0 的 可以查看我前几篇博文 2018.4.8 补充 我出现这个原因:是我在资源服务器使用了 如下图所示 Principal Oauth2.0 提供的获取用户信息的方法 使其找到相 ...
- SpringCloud之Zuul:服务网关
Zuul在Web项目中的使用见上文<SpringBoot中使用Zuul>,下面例子为Zuul在Spring Cloud的使用. 开发工具:IntelliJ IDEA 2019.2.3 一. ...
- Spring-Cloud之Zuul路由网关-6
一.为什么需要Zuul? Zuul 作为微服务系统的网关组件,用于构建边界服务( Edge Service ),致力于动态路由.过滤.监控.弹性伸缩和安全.Zuul 作为路由网关组件,在微服务架构中有 ...
- SpringCloud之Zuul网关原理及其配置
Zuul是spring cloud中的微服务网关.网关: 是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也 ...
- 非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了!
Zuul是spring cloud中的微服务网关.网关:是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也是 ...
- SpringCloud网关ZUUL集成consul
最近一直在搞基于springcloud的微服务开发,为了不限定微服务开发语言,服务发现决定采用consul不多说上代码 pom文件 <project xmlns="http://mav ...
- SpringCloud系列——Zuul 动态路由
前言 Zuul 是在Spring Cloud Netflix平台上提供动态路由,监控,弹性,安全等边缘服务的框架,是Netflix基于jvm的路由器和服务器端负载均衡器,相当于是设备和 Netflix ...
- springcloud的Zuul配置重试和fallback
可以参考如下blog: SpringCloud学习03之api服务网关zuul反向代理及重试配置 springCloud学习04之api服务网关zuul回退fallback 注意:重试的开启需要处理幂 ...
随机推荐
- Codeforces 1276F - Asterisk Substrings(SAM+线段树合并+虚树)
Codeforces 题面传送门 & 洛谷题面传送门 SAM hot tea %%%%%%% 首先我们显然可以将所有能够得到的字符串分成六类:\(\varnothing,\text{*},s, ...
- HDU 6116 路径计数
HDU 6116 路径计数 普通生成函数常用于处理组合问题,指数生成函数常用于处理排列问题. 考虑 对于 $ a $ 个 $ A $ 分为很多堆,这么分的方案数是 $ C_{a-1}^{i-1} $ ...
- Linux— 查看系统发布版本信息
[root@zf-test-web01-4 ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core)
- 类成员函数调用delete this会发生什么呢?
有如下代码 class myClass { public: myClass(){}; ~myClass(){}; void foo() { delete this; } }; int main() { ...
- spring整合mybatis — 更新完毕
1.准备工作 -- 导入依赖 <dependency> <groupId>org.springframework</groupId> <artifactId& ...
- 学习java的第十天
一.今日收获 1.java完全学习手册第二章2.9程序流程控制中的选择结构与顺序结构的例题 2.观看哔哩哔哩上的教学视频 二.今日问题 1.例题的问题不大,需要注意大小写,新的语句记忆不牢 2.哔哩哔 ...
- Go Robot
1 <html> 2 <meta http-equiv="Content-Type" content="text/html; charset=utf-8 ...
- 论文解读(GraRep)《GraRep: Learning Graph Representations with Global Structural Information》
论文题目:<GraRep: Learning Graph Representations with Global Structural Information>发表时间: CIKM论文作 ...
- oracle中的数组
Oracle中的数组分为固定数组和可变数组. 一.固定数组固定数组:在定义的时候预定义了数组的大小,在初始化数组时如果超出这个大小,会提示ORA-06532:超出小标超出限制!语法: T ...
- Linux基础命令---mget获取ftp文件
mget 使用lftp登录mftp服务器之后,可以使用mget指令从服务器获取文件.mget指令可以使用通配符,而get指令则不可以. 1.语法 mget [-E] [-a] [- ...