springcloud學習(五)之GateWay

GateWay簡介

網關(GateWay)

局域⽹中就有⽹關(翻譯過來就叫作GateWay)這個概念,局域⽹接收或者發送數據出去經過這個⽹關,⽐如⽤Vmware虛擬機軟件搭建虛擬機集羣的時候,每每咱們須要選擇IP段中的⼀個IP做爲⽹關地址。
咱們學習的GateWay(Spring Cloud GateWay),它只是衆多⽹關解決⽅案中的⼀種,是微服務架構中的重要組成部分java

Spring Cloud GateWay

Spring Cloud GateWay是Spring Cloud的⼀個全新項⽬,⽬標是取代Netflix Zuul,它基於
Spring5.0+SpringBoot2.0+WebFlux(基於⾼性能的Reactor模式響應式通訊框架Netty,異步⾮阻塞模型)等技術開發,性能⾼於Zuul,官⽅測試, GateWay是Zuul的1.6倍,旨在爲微服務架構提供⼀種簡單有效的統⼀的API路由管理⽅式。
Spring Cloud GateWay不只提供統⼀的路由⽅式(反向代理)而且基於 Filter(定義過濾器對請求過濾,完成⼀些功能) 鏈的⽅式提供了⽹關基本的功能,例如:鑑權、流量控制、熔斷、路徑重寫、⽇志監控等。git

GateWay的使用

新建GateWay網關項目,因爲gateway不須要引⼊starter-web模塊,須要引⼊web-flux,而我們以前的父工程裏面有web組件,因此咱們不能以lagou-parent爲父工程創建gateway。web

<!--GateWay ⽹關-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--引⼊webflux-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

application.yml中作一些關於路由規則的配置:spring

Spring:
  application:
    name: lagou-cloud-gateway
  cloud:
      gateway:
        routes: # 路由能夠有多個
          - id: service-autodeliver-router # 咱們⾃定義的路由 ID,保持惟⼀
            uri: http://127.0.0.1:8090 # ⽬標服務地址 ⾃動投遞微服務(部署多實例)
        #動態路由: uri配置的應該是⼀個服務名稱,⽽不該該是⼀個具體的服務實例的地址
        # gateway⽹關從服務註冊中⼼獲取實例信息而後負載後路由
            predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默認⽅法來將 Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。
              - Path=/autodeliver/**
          - id: service-resume-router # 咱們⾃定義的路由 ID,保持惟⼀
            uri: http://127.0.0.1:8081 # ⽬標服務地址
        #http://localhost:9002/resume/openstate/1545132
        #http://127.0.0.1:8081/openstate/1545132
            predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默 認⽅法來將Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。
              - Path=/resume/**
            filters:
              - StripPrefix=1

正常訪問服務消費者8090的地址是
http://localhost:8090/autodeliver/checkStateTimeoutFallBack/1545132

經過網關配置代理以後的地址:
http://localhost:9002/autodeliver/checkStateTimeoutFallBack/1545132
架構

動態路由

上面咱們是直接寫死了目標服務的請求地址,這樣對於咱們集羣部署多個服務是不行的,咱們應該改形成從eureka服務註冊中心獲取服務列表並進行訪問,即所謂的動態路由。
動態路由配置方式:url: lb://在eureka註冊的服務名稱
lb表示從註冊中心獲取服務,後面是須要轉發的服務名稱。
例如:app

uri: lb://lagou-service-resume

由於須要從註冊中心獲取服務列表,因此須要在pom.xml中添加eureka的客戶端依賴。
測試:負載均衡

能夠看到網關分發請求到不一樣的服務,實現了動態路由。框架

GateWay過濾器

從過濾器⽣命週期(影響時機點)的⻆度來講,主要有兩個pre和post:異步

生命週期時機點 做用
pre 這種過濾器在請求被路由以前調⽤。咱們可利⽤這種過濾器實現身份驗證、在集羣中選擇 請求的微服務、記錄調試信息等
post 這種過濾器在路由到微服務之後執⾏。這種過濾器可⽤來爲響應添加標準的 HTTPHeader、收集統計信息和指標、將響應從微服務發送給客戶端等。

從過濾器類型的⻆度, Spring Cloud GateWay的過濾器分爲GateWayFilter和GlobalFilter兩種:ide

過濾器類型 影響範圍
GateWayFilter 應用到單個路由上
GlobalFilter 應用到全部路由上

好比GateWayFilter能夠去掉url中的佔位後再轉發路由,以下:

- id: service-resume-router # 咱們⾃定義的路由 ID,保持惟⼀
            #uri: http://127.0.0.1:8081 # ⽬標服務地址
            uri: lb://lagou-service-resume # ⽬標服務地址
        #http://localhost:9002/resume/openstate/1545132
        #http://127.0.0.1:8081/openstate/1545132
            predicates: # 斷⾔:路由條件, Predicate 接受⼀個輸⼊參數,返回⼀個布爾值結果。該接⼝包含多種默 認⽅法來將Predicate 組合成其餘複雜的邏輯(⽐如:與,或,⾮)。
              - Path=/resume/**
            filters:
              - StripPrefix=1

和前面的動態路由相比,主要是添加了下面的參數:

filters:
              - StripPrefix=1

StripPrefix這個參數的意思是去掉訪問url的第一個參數,再進行匹配。
好比http://localhost:9002/resume/openstate/1545132這個請求,會匹配目標服務的http://127.0.0.1:8081/openstate/1545132

自定義全局過濾器實現IP訪問限制(黑白名單功能)

思路:請求過來時,判斷髮送請求的客戶端的ip,若是在⿊名單中,拒絕訪問.
⾃定義GateWay全局過濾器時,咱們實現Global Filter接⼝便可,經過全局過濾器能夠實現⿊⽩名單、限流等功能。
在網關服務中自定義全局過濾器:

@Slf4j
@Component
public class BlackListFilter implements GlobalFilter, Ordered {


    private static List<String> blackList=new ArrayList<>();
    static {
        blackList.add("0:0:0:0:0:0:0:1");//模擬本機地址
    }

    /**
     * 過濾器核⼼⽅法
     * @param exchange 封裝了request和response對象的上下⽂
     * @param chain ⽹關過濾器鏈(包含全局過濾器和單路由過濾器)
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 思路:獲取客戶端ip,判斷是否在⿊名單中,在的話就拒絕訪問,不在的話就放⾏
          // 從上下⽂中取出request和response對象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

// 從request對象中獲取客戶端ip
        String clientIp = request.getRemoteAddress().getHostString();
        // 拿着clientIp去⿊名單中查詢,存在的話就拒絕訪問
        if(blackList.contains(clientIp)){
            //// 拒絕訪問,返回
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            log.debug("------>Ip:"+clientIp+" 在黑名單中,被拒絕訪問!");
            String data="Request be denied!!";
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
            return response.writeWith(Mono.just(wrap));
        }

        // 合法請求,放⾏,執⾏後續的過濾器
        return chain.filter(exchange);
    }

    /**
     * 返回值表示當前過濾器的順序(優先級),數值越⼩,優先級越⾼
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

效果:

GateWay高可用

⽹關做爲⾮常核⼼的⼀個部件,若是掛掉,那麼全部請求均可能⽆法路由處理,所以咱們須要作
GateWay的⾼可⽤。
GateWay的⾼可⽤很簡單: 能夠啓動多個GateWay實例來實現⾼可⽤,在GateWay的上游使⽤Nginx等負載均衡設備進⾏負載轉發以達到⾼可⽤的⽬的。
舉例:
啓動多個GateWay實例(假如說兩個,⼀個端⼝9002,⼀個端⼝9003),剩下的就是使⽤Nginx等完成負載代理便可。示例以下:

upstream gateway {
server 127.0.0.1:9002;
server 127.0.0.1:9003;
}
location / {
proxy_pass http://gateway;
}

案例源碼

gateway案例源碼地址:gateway案例源碼地址

歡迎訪問個人博客:https://www.liuyj.top

相關文章
相關標籤/搜索