作用

API网关

  • 后台服务统一的调用入口
  • 转发的路由规则如下:
zuul:
 routes:
 # 远程服务: 调用路径
 # 下面配置的是默认规则,不配置也可以自动配置
 # 如果不配置,可以根据注册表自动配置

实现步骤

1.添加依赖:Zuul/eureka client
2.配置application.yml:application.name/server.port/zuul.route.服务

spring:
  application:
    name: zuul
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

zuul:
  routes:
    item-service: /item-service/**
    user-service: /user-service/**
    order-service: /order-service/**

3.启动类添加注解@EnableZuulProxy

@EnableZuulProxy
@SpringBootApplication
public class Sp11ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sp11ZuulApplication.class, args);
    }
}

统一的权限校验

定义过滤器

通过继承 ZuulFilter 过滤器,来实现权限判断
没登陆就阻止访问
已登录就允许访问--http://.../...?token=...

@Component
public class AccessFilter extends ZuulFilter{
    //是否执行过滤代码
    @Override
    public boolean shouldFilter() {
        //对指定的serviceid过滤,如果要过滤所有服务,直接返回 true
        
        RequestContext ctx = RequestContext.getCurrentContext();
        String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
        if(serviceId.equals("item-service")) {
            return true;
        }
        return false;
    }

    //过滤代码
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();
        String token = req.getParameter("token");
        if (token == null) {
            //此设置会阻止请求被路由到后台微服务
            ctx.setSendZuulResponse(false);
            //向客户端的响应
            ctx.setResponseStatusCode(200);
            ctx.setResponseBody(JsonResult.err().code(JsonResult.NOT_LOGIN).toString());
        }
        //zuul过滤器返回的数据设计为以后扩展使用,
        //目前该返回值没有被使用
        return null;
    }

    //过滤器类型
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    //过滤器顺序号
    @Override
    public int filterOrder() {
        //该过滤器顺序要 > 5,才能得到 serviceid
        return FilterConstants.PRE_DECORATION_FILTER_ORDER+1;
    }
}

zuul 集成 ribbon

默认启用了负载均衡,但没有启用重试

启用重试

  1. 添加 spring-retry 依赖
  2. zuul.retryable=true
  3. 有默认重试参数(无需配置重试参数)

zuul + hystrix 降级

创建降级类

  • getRoute() 方法中指定应用此降级类的服务id,星号或null值可以通配所有服务
@Slf4j
@Component
public class ItemServiceFallback implements FallbackProvider {
    @Override
    public String getRoute() {
        //当执行item-service失败,
        //应用当前这个降级类
        return "item-service";
        //星号和null都表示所有微服务失败都应用当前降级类
        //"*"; //null;
    }

    //该方法返回封装降级响应的对象
    //ClientHttpResponse中封装降级响应
    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return response();
    }

    private ClientHttpResponse response() {
        return new ClientHttpResponse() {
            //下面三个方法都是协议号
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }
            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }
            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {
            }

            @Override
            public InputStream getBody() throws IOException {
                log.info("fallback body");
                String s = JsonResult.err().msg("后台服务错误").toString();
                return new ByteArrayInputStream(s.getBytes("UTF-8"));
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}

迈克丝
82 声望5 粉丝

一步一步学技术,踏踏实实涨经验,兴趣广泛,广交好友,希望大家多多指正/批评.