springcloud zuul 动态路由

zuul简介

        Zuul 是Spring Cloud 子项目Spring Cloud Netflix的一个组件,它是Netflix对ApiGateway实现的一份答卷,应用很是普遍。常见的功能以下java

  • 身份验证
  • 压力测试
  • Canary Testing
  • 动态路由
  • 安全控制 
  • ...............

zuul实例 

      OK,既然标题提到zuul动态路由,此文章主要介绍下zuul动态路由,那么咱们写个小demo看看zuulnginx

  • 一、首先建立对应的pom文件
  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zuul</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
  • 二、其次对应的主应用@EnableZuulProxy注解开启Zuul
  • @EnableZuulProxy
    @EnableEurekaClient
    @SpringCloudApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
        }
    
        @Bean
        public PreFilter preFilter() {
            return new PreFilter();
        }
    
        @Bean
        public RoutingFilter routingFilter() {
            return new RoutingFilter();
        }
    
        @Bean
        public PostFilter postFilter() {
            return new PostFilter();
        }
    
        @Bean
        public ErrorFilter errorFilter() {
            return new ErrorFilter();
        }
    
    
    }
  • 三、application.properties中配置Zuul应用的基础信息,如:应用名、服务端口等。
  • spring.application.name=api-gateway
    server.port=9091
  • 到此简单的zuul就能够跑了,可是若须要用到微服务中那么还需以下配置

路由服务

#反响代理配置  
#这里的配置相似nginx的反响代理  
#当stripPrefix=true的时候 (http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/user/list)  
#当stripPrefix=false的时候(http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/api/user/list)  
zuul.routes.api.path=/api/**  
#代理前缀默认会从请求路径去除
zuul.routes.api.stripPrefix=false

zuul的其余配置

#提升超时配置(有的同窗碰到第一次代理时都是timeout,须要配置以下配置)git

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:60000程序员

ribbon.ConnectTimeout: 3000github

ribbon.ReadTimeout: 60000spring

服务过滤

在服务网关中定义过滤器只须要继承zuulfltier抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。api

好比下面的例子,定义了一个Zuul过滤器,实现了在请求被路由以前检查请求中是否有accessToken参数,如有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。安全

public class AccessFilter extends ZuulFilter  {
    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
    @Override
    public String filterType() {
        return "pre";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("accessToken");
        if(accessToken == null) {
            log.warn("access token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            return null;
        }
        log.info("access token ok");
        return null;
    }
}

自定义过滤器的实现,须要继承ZuulFilter,须要重写实现下面四个方法:架构

  • filterType:返回一个字符串表明过滤器的类型,在zuul中定义了四种不一样生命周期的过滤器类型,具体以下:
    • pre:能够在请求被路由以前调用
    • routing:在路由请求时候被调用
    • post:在routing和error过滤器以后被调用
    • error:处理请求时发生错误时被调用
  • filterOrder:经过int值来定义过滤器的执行顺序
  • shouldFilter:返回一个boolean类型来判断该过滤器是否要执行,因此经过此函数可实现过滤器的开关。在上例中,咱们直接返回true,因此该过滤器老是生效。
  • run:过滤器的具体逻辑。须要注意,这里咱们经过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,而后经过ctx.setResponseStatusCode(401)设置了其返回的错误码,固然咱们也能够进一步优化咱们的返回,好比,经过ctx.setResponseBody(body)对返回body内容进行编辑等。

        在实现了自定义过滤器以后,还须要实例化该过滤器才能生效,还须要在应用主类中增长四个过滤器的实例化。app

  为何服务网关是微服务架构的重要部分?

  • 不只仅实现了路由功能来屏蔽诸多服务细节,更实现了服务级别、均衡负载的路由。
  • 实现了接口权限校验与微服务业务逻辑的解耦。经过服务网关中的过滤器,在各生命周期中去校验请求的内容,将本来在对外服务层作的校验前移,保证了微服务的无状态性,同时下降了微服务的测试难度,让服务自己更集中关注业务逻辑的处理。
  • 实现了断路器,不会由于具体微服务的故障而致使服务网关的阻塞,依然能够对外服务。

    问题总结

        一、第一次代理请求是链接超时(timeout) 须要配置 进行以下配置

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:60000

ribbon.ConnectTimeout: 3000

ribbon.ReadTimeout: 60000

        二、com.netflix.discovery.TimedSupervisorTask(线程池拒绝策略异常),相信不少人都碰到了这个问题,度娘了有的说不影响,确实是不影响,可是程序员都有强迫症。

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@427829d8 rejected from java.util.concurrent.ThreadPoolExecutor@5f0345ff[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]  
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048) ~[na:1.7.0_79]  
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821) [na:1.7.0_79]  
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372) [na:1.7.0_79]  
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110) ~[na:1.7.0_79]  
    at com.netflix.discovery.TimedSupervisorTask.run(TimedSupervisorTask.java:62) ~[eureka-client-1.4.11.jar:1.4.11]  
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_79]  
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_79]  
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178) [na:1.7.0_79]  
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292) [na:1.7.0_79]  
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_79]  
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_79]  
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_79]

    ok废话很少说,直接上解决方案,将对应的eurake版本升级,此问题应该是eurake自带的bug

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RELEASE</version> // 注意关键点在这
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

此问题的参考文档  https://github.com/Netflix/eureka/issues/907

相关文章
相关标签/搜索