Zuul网关配置、ZuulException: Forwarding error

深碍√TFBOYSˉ_ 2022-04-13 15:14 341阅读 0赞
声明,使用JDK8、springcloud2.01 、maven3.5.4、idea

Zuul 是什么,有什么作用:

核心作用3个:
过滤和路由、异常处理;
另外、Zuul 集成了负载均衡,在线面案例会有展示、

下面分别讲Zuul 的基础使用,以及这三个作用的案例演示、

1、基本配置如下:
1.1、添加Zuul 以及Eureka 依赖;
  1. <!-- 网关依赖-->
  2. <dependencies>
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  6. </dependency>
  7. <!-- eureka -->
  8. <dependency>
  9. <groupId>org.springframework.cloud</groupId>
  10. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  11. </dependency>
  12. </dependencies>
1.2、yml 文件、Zuul 路由规则配置:

由于存在Eureka 客户端,所以直接指定服务端的名字即可;
后面还有更简化的配置;

  1. server:
  2. port: 10010 #端口
  3. spring:
  4. application:
  5. name: api-gateway # 网关名字
  6. zuul:
  7. routes:
  8. user-service: # 路由的 id
  9. path: /user-service/** #映射路径
  10. # url: http://127.0.0.1:8081 #映射路径对应的实际的url地址
  11. # 访问路径规则 添加 映射路径的规则
  12. serviceId: user-service # 指定服务端的名称

简化配置:直接指定服务端的 ID 指向 映射路径 path

zuul.routes..path=/xxx/**: 来指定映射路径。是自定义的路由名
zuul.routes..serviceId=/user-service:来指定服务名。
简化配置:
zuul.routes.= 即简化成如下配置:

  1. zuul:
  2. routes:
  3. user-service: /user-service/** # 这里是映射路径

默认配置: Zuul 默认配置规则就是服务path 对应就是服务ID ,意思就是不配置Zuul 也是OK的。

忽略配置:
想要禁用某一个路由规则 采用如下配置:

  1. zuul:
  2. ignored-services:
  3. - user-service
  4. - consumer
1.3、配置好Zuul ,

访问代理 http://localhost:10010/user-service/user/2
出现500报错,报错如下:

  1. com.netflix.zuul.exception.ZuulException: Forwarding error
  2. 、、省略
  3. Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: path

异常原因如下图:
在这里插入图片描述
明显路径映射不对,仔细查看发现yml 文件中path 、url 和user-service 在同一级路径了,都是坑;
修改如下图,恢复正常访问;
1


1、添加前缀: /api
使用 zuul.prefix : /api 的语法,yml具体配置如下:
访问:http://localhost:10010/api/user-service/user/2

  1. zuul:
  2. prefix: /api # 添加路由前缀
  3. routes:
  4. user-service: # 路由的 id
  5. path: /user-service/** #映射路径
  6. # url: http://127.0.0.1:8081 #映射路径对应的实际的url地址
  7. # 访问路径规则 添加 映射路径的规则
  8. serviceId: user-service # 指定服务端的名称

在这里插入图片描述
访问结果如下:
在这里插入图片描述


  1. 2018.12.5 更新


1、异常处理:

zuul 为我们提供了一个名叫 ZuulFallbackProvider 的接口、 在服务挂掉时候调用该接口返回信息,我们通过实现该接口,重写接口中fallbackResponse 方法,返回错误的处理规则、给出信息提示:

  1. Component
  2. public class ApiFallbackProvider implements ZuulFallbackProvider{
  3. @Override
  4. public String getRoute() {
  5. return "eurekaclient";
  6. }
  7. @Override
  8. public ClientHttpResponse fallbackResponse() {
  9. return new ClientHttpResponse() {
  10. @Override
  11. public HttpStatus getStatusCode() throws IOException {
  12. return HttpStatus.OK;
  13. }
  14. @Override
  15. public int getRawStatusCode() throws IOException {
  16. return 200;
  17. }
  18. @Override
  19. public String getStatusText() throws IOException {
  20. return "{code:0,message:\"服务器异常!\"}";
  21. }
  22. @Override
  23. public void close() {
  24. }
  25. @Override
  26. public InputStream getBody() throws IOException {
  27. return new ByteArrayInputStream(getStatusText().getBytes());
  28. }
  29. @Override
  30. public HttpHeaders getHeaders() {
  31. HttpHeaders headers = new HttpHeaders();
  32. headers.setContentType(MediaType.APPLICATION_JSON);
  33. return headers;
  34. }
  35. };
  36. }
2、动态路由:

Zuul 实现动态路由,是因为Zuul 集成的有负载均衡、有负载均衡的效果。

  • 首先更改服务提供者 EurekaClient 端口、启动多个服务提供者,然后访问服务 http://localhost:8761/ 如下图,有2个服务提供者:
  • 启动网关、 不断访问地址:http://localhost:8080/api/index 会看到如下,端口交替出现、意味着服务提供者交替提供服务;
    就是默认的轮询的方式;

1

3、过滤、服务拦截:

1、服务网关还有个作用就是接口的安全性校验,这个时候我们就需要通过 zuul 进行统一拦截,zuul 通过继承过滤器 ZuulFilter 进行处理:
2、重写ZuulFilter 类中的 方法、

  1. package com.syntactic.filter;
  2. /** * @auther SyntacticSugar * @data 2018/12/5 0005下午 5:00 */
  3. @Component
  4. public class ApiFilter extends ZuulFilter {
  5. @Override
  6. public String filterType() {
  7. return "pre";
  8. }
  9. @Override
  10. public int filterOrder() {
  11. return 0;
  12. }
  13. @Override
  14. public boolean shouldFilter() {
  15. return true;
  16. }
  17. @Override
  18. public Object run() {
  19. // 逻辑代码
  20. }
  21. }

filterType 为过滤类型,可选值有 pre(路由之前)、routing(路由之时)、post(路由之后)、error(发生错误时调用)。
filterOrdery 为过滤的顺序,如果有多个过滤器,则数字越小越先执行
shouldFilter 表示是否过滤,这里可以做逻辑判断,true 为过滤,false 不过滤
run 为过滤器执行的具体逻辑;

以下逻辑做一个权限校验、

  1. @Override
  2. public Object run() {
  3. // 逻辑代码
  4. RequestContext currentContext = RequestContext.getCurrentContext();
  5. HttpServletRequest request = currentContext.getRequest();
  6. // 获取传递的参数、验证权限
  7. String token = request.getParameter("token");
  8. //
  9. if (!"123456".equals(token)) {
  10. currentContext.setSendZuulResponse(false);
  11. currentContext.setResponseStatusCode(400);
  12. // 把提示信息显示到 页面
  13. try {
  14. currentContext.getResponse().getWriter().write("token is invalid");
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. return null;
  20. }

访问:http://localhost:8080/api/index 非法
访问 http://localhost:8080/api/index?token=12345 有效
1
2

发表评论

表情:
评论列表 (有 0 条评论,341人围观)

还没有评论,来说两句吧...

相关阅读