springcloud服務網關Zuul高級篇 學習記錄-純潔的微笑

以前已經集成了網關,而且已經抽離優化成一個服務,如今看他的高級部分。Zuul還有更多的應用場景,好比:鑑權、流量轉發、請求統計等等,這些功能均可以使用Zuul來實現。java

1.鑑權-自定義Filter,進行token檢測。建立一個MyFilterweb

package com.example.zuul.filter;

import com.netflix.zuul.ZuulFilter;

public class MyFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre"; //定義filter的類型,有pre、route、post、error四種
    }

    @Override
    public int filterOrder() {
        return 10; //定義filter的順序,數字越小表示順序越高,越先執行
    }

    @Override
    public boolean shouldFilter() {
        return true; //表示是否須要執行該filter,true表示執行,false表示不執行
    }

    @Override
    public Object run() {
        return null; //filter須要執行的具體操做
    }

}

這是一個簡單filter示例,後面咱們進行業務封裝。spring

package com.example.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

public class TokenFilter extends ZuulFilter {
    private final Logger logger = LoggerFactory.getLogger(TokenFilter.class);

    @Override
    public String filterType() {
        return "pre"; // 能夠在請求被路由以前調用
    }

    @Override
    public int filterOrder() {
        return 0; // filter執行順序,經過數字指定 ,優先級爲0,數字越大,優先級越低
    }

    @Override
    public boolean shouldFilter() {
        return true;// 是否執行該過濾器,此處爲true,說明須要過濾
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        logger.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString());

        String token = request.getParameter("token");// 獲取請求的參數

        if (StringUtils.isNotBlank(token)) {
            ctx.setSendZuulResponse(true); //對請求進行路由
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);
            return null;
        } else {
            ctx.setSendZuulResponse(false); //不對其進行路由
            ctx.setResponseStatusCode(400);
            ctx.setResponseBody("token is empty");
            ctx.set("isSuccess", false);
            return null;
        }
    }
}

仔細對比,發下,二者的區別,就在與run的裏面,進行業務實現部分apache

2.將自創建的filter,加入啓動項裏面api

package com.example.zuul;

import com.example.zuul.filter.TokenFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableZuulProxy  //支持網關路由
public class ZuulApplication {

   public static void main(String[] args) {
      SpringApplication.run(ZuulApplication.class, args);
   }


   /**
    * 啓動類增長請求攔截
    * @return
    */
   @Bean
   public TokenFilter tokenFilter() {
      return new TokenFilter();
   }

}

啓動網關服務,進行檢測app

出現提示,說明自創建的filter已經生效。maven

 

如今咱們在進行測試路由熔斷,這裏須要說明的是,他與熔斷器的區別,他針對的是一個服務,熔斷器針對的一個遠程調用的方法,進行熔斷處理ide

 

package com.example.zuul.fallback;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

@Component
public class ProducerFallback implements FallbackProvider{

    private final Logger logger = LoggerFactory.getLogger(FallbackProvider.class);

    //指定要處理的 service。
    @Override
    public String getRoute() {
        return "spring-cloud-producer";
    }

    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return 200;
            }

            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("The service is unavailable.".getBytes());
            }

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

    @Override
    public ClientHttpResponse fallbackResponse( String xxx,Throwable cause) {
        if (cause != null && cause.getCause() != null) {
            String reason = cause.getCause().getMessage();
            logger.info("Excption {}",reason);
        }
        return fallbackResponse();
    }
}

將上面熔斷的服務中止,請求進行嘗試,發現返回spring-boot

The service is unavailable

服務熔斷測試成功post

 

 

 

測試網關的路由重試功能。

1.在zuul網關服務pom中,添加路由重試的依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.1.5.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>zuul</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>zuul</name>
   <description>Demo project for Spring Boot</description>

   <properties>
      <java.version>1.8</java.version>
      <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
   </properties>

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

      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <!-- 增長服務註冊中心依賴 -->
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
      </dependency>
      <!-- 啓用Zuul Retry-重試功能 -->
      <dependency>
         <groupId>org.springframework.retry</groupId>
         <artifactId>spring-retry</artifactId>
      </dependency>

   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

2.配置文件開啓重試的功能

spring.application.name=gateway-service-zuul
server.port=8888

#這裏的配置表示,訪問/it/** 直接重定向到http://www.ityouknow.com/**
#zuul.routes.baidu.path=/it/**
#zuul.routes.baidu.url=http://www.ityouknow.com/
#zuul.routes.hello.path=/api/**
#zuul.routes.hello.url=http://localhost:9001/

zuul.routes.api-a.path=/consumer/**
zuul.routes.api-a.serviceId=spring-cloud-consumer

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/


#############Zuul Retry############
#是否開啓重試功能
zuul.retryable=true
#對當前服務的重試次數
ribbon.MaxAutoRetries=2
#切換相同Server的次數
ribbon.MaxAutoRetriesNextServer=0

3.在相關的方法,增長線程沉睡,觸發屢次重試

package com.example.servicefeign.controller;

import com.example.servicefeign.interfaceServer.HelloRemote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope // 使用該註解的類,會在接到SpringCloud配置中心配置刷新的時候,自動將新的配置更新到該類對應的字段中。
@RestController
public class HelloController {

    @Autowired
    HelloRemote hello;//註冊接口層

    @Value("${neo.hello:111}")
    private String config;

    @RequestMapping("/hello/{name}")
    public String index(@PathVariable("name") String name) throws Exception{
        System.out.println("調用接口-----------------");
        Thread.sleep(1000L);
        return hello.hello(name);
    }

    /**
     * 獲取配置中心參數
     */
    @GetMapping("/config")
    public String getConfig(){
        return this.config;
    }

}

index方法中,已經增長了線程休眠時間。

執行程序,進行調用,查看日誌

 

 

網關的重試,成功調起

相關文章
相關標籤/搜索