路由是微服务架构不可或缺的一部分。例如,/可能被映射到您的web应用程序,/api/users被映射到用户服务,/api/shop被映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载平衡器。

用途如下:

  • 认证方式
  • 见解
  • 压力测试
  • 金丝雀测试
  • 动态路由
  • 服务迁移
  • 减载
  • 安全
  • 静态响应处理
  • 主动/主动流量管理

使用

新建一个项目,pom.xml配置

<!--        zuul-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

<!--        eureka-client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置文件


server.port=80

spring.application.name=service-zuul

# 心跳检测
eureka.instance.lease-renewal-interval-in-seconds=2
# 心跳超时时间
eureka.instance.lease-expiration-duration-in-seconds=10
# 实例以ip作为链接,而不是取机器名
eureka.instance.ip-address=true
# 服务实例名称
eureka.instance.instance-id=${spring.application.name}-${server.port}
# 实例注册中心
eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka/,http://eureka8762:8762/eureka/,http://eureka8763:8763/eureka/

zuul.host.connect-timeout-millis=5000

启动类加@EnableZuulProxy注解

可以直接访问了

localhost/service-reception/test01

一般配置路由规则,使用路由规则访问

# 忽略某个服务名,禁止通过该服务名访问.*直接通配所有
zuul.ignored-services=*

# 路由规则
zuul.routes.reception.service-id=service-reception
zuul.routes.reception.path=/reception/**

过滤器

PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等

ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient或 Netfilx Ribbon请求微服务

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等

ERROR:在其他阶段发生错误时执行该过滤器

@Component
public class TestFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.DEBUG_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        String requestURI = currentContext.getRequest().getRequestURI();
        StaticLog.info("自定义zuulFilter:requestURI: {}", requestURI);
        return null;
    }
}

过滤器禁用

比如要实现自定义的ErrorFilter,禁用zuul默认的异常过滤器

zuul.SendErrorFilter.error.disable=true

熔断降级

示例

@Component
public class ProviderFallback implements FallbackProvider {
    
    @Override
    public String getRoute() {
        return "*";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.set("Content-Type", "text/html; charset=UTF-8");
                return headers;
            }

            @Override
            public InputStream getBody() throws IOException {
                // 响应体
                return new ByteArrayInputStream("服务正在维护,请稍后再试.".getBytes());
            }

            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.BAD_REQUEST;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.BAD_REQUEST.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.BAD_REQUEST.getReasonPhrase();
            }

            @Override
            public void close() {
            }

        };
    }

}