Zuul 是Spring Cloud 子项目Spring Cloud Netflix的一个组件,它是Netflix对ApiGateway实现的一份答卷,应用很是普遍。常见的功能以下java
OK,既然标题提到zuul动态路由,此文章主要介绍下zuul动态路由,那么咱们写个小demo看看zuulnginx
<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
#反响代理配置 #这里的配置相似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
#提升超时配置(有的同窗碰到第一次代理时都是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>