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

相關文章
相關標籤/搜索