Spring Cloud之 Feign&Hystrix& Gateway


Feign聲明式服務調用
1、Feign 是一個聲明式的 REST 客戶端,它用了基於接口的注解方式,很方便實現客戶端配置。
2、Feign 最初由 Netflix 公司提供,但不支持SpringMVC注解,后由 SpringCloud 對其封裝,支持了SpringMVC注解,讓使用者更易於接受。

Feign 快速入門

一、feign消費方

1、在消費端引入 open-feign 依賴

2、編寫yaml文件

server:
  port: 9000

eureka:
  instance:
    hostname: localhost #主機名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: feign-consumer #設置當前應用的名稱。將來會在eureka中Application顯示。將來需要使用該名稱獲取路徑

3、編寫Feign調用接口

package com.zxj.consumer.feign;

import com.zxj.consumer.config.FeignLogConfig;
import com.zxj.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 *
 * feign聲明式接口。發起遠程調用的。
 *
 String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
 Goods goods = restTemplate.getForObject(url, Goods.class);
 *
 * 1. 定義接口
 * 2. 接口上添加注解 @FeignClient,設置value屬性為 服務提供者的 應用名稱
 * 3. 編寫調用接口,接口的聲明規則 和 提供方接口保持一致。
 * 4. 注入該接口對象,調用接口方法完成遠程調用
 *
 */
@FeignClient(value = "FEIGN-PROVIDER")
public interface GoodsFeignClient {

    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);
}

注意和提供方中的方法保持一致


在消費方啟動類 添加 @EnableFeignClients 注解,開啟Feign功能

二、feign提供方

1、編寫yaml文件,定義服務名,並將服務注冊到eureka中

server:
  port: 8001

eureka:
  instance:
    hostname: localhost #主機名
    prefer-ip-address: true #將當前實例的ip注冊到eureka server中。默認是false注冊主機名
    ip-address: 127.0.0.1 #設置當前實例的ip
    instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} #設置web控制台現實的實例id
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: feign-provider #設置當前應用的名稱。將來會在eureka中Application顯示,將來需要使用該名稱來獲取路徑

提供方controller

package com.zxj.provider.controller;

import com.zxj.provider.domain.Goods;
import com.zxj.provider.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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;

/**
 * Goods Controller 服務提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;

    @GetMapping("/findOne/{id}")
    public Goods findOne(@PathVariable("id") int id){

        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//將端口號,設置到了 商品標題上
        return goods;
    }
}

測試調用

三、編寫eureka注冊中心

1、引入依賴包

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

2、編寫yaml文件

server:
  port: 8761
eureka:
  instance:
    hostname: localhost #主機名
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服務端地址,將來客戶端使用該地址和eureka進行通信
    register-with-eureka: false # 是否將自己的路徑 注冊到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: false # 是否需要從eureka中抓取路徑。eureka server 不需要的,eureka consumer client 需要
  server:
    enable-self-preservation: false # 關閉自我保護機制
    eviction-interval-timer-in-ms: 3000 # 檢查服務的時間間隔

3、編寫啟動類

@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class, args);
    }
}

這里的feign的提供方應該在前,消費方應該在后
Feign 其他功能 – 超時設置

Feign 底層依賴於 Ribbon 實現負載均衡和遠程調用。
Ribbon默認1秒超時。
超時配置:

ribbon:
  ConnectTimeout: 1000   #連接超時時間,毫秒
  ReadTimeout: 1000     #邏輯處理超時時間,毫秒

直接在消費端的application.yml配置文件中添加

Feign 其他功能 – 日志記錄
1、Feign 只能記錄 debug 級別的日志信息。

logging:
  level:
    com.itheima: debug


2、定義Feign日志級別Bean

/*
        NONE,不記錄
        BASIC,記錄基本的請求行,響應狀態碼數據
        HEADERS,記錄基本的請求行,響應狀態碼數據,記錄響應頭信息
        FULL;記錄完成的請求 響應數據

     */

@Configuration
public class FeignLogConfig {
    @Bean
    public Logger.Level level(){
        return Logger.Level.FULL;
    }
}

3、啟用該Bean:
@FeignClient(configuration = XxxConfig.class)

@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {

    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);
}

** Hystrix 熔斷器**
Hystix 是 Netflix 開源的一個延遲和容錯庫,用於隔離訪問遠程服務、第三方庫,防止出現級聯失敗(雪崩)。
雪崩:一個服務失敗,導致整條鏈路的服務都失敗的情形。

A調用B,B調用C,如果c出現問題,接着b和a也會出現問題
Hystrix 概述
Hystix 是 Netflix 開源的一個延遲和容錯庫,用於隔離訪問遠程服務、第三方庫,防止出現級聯失敗(雪崩)。
雪崩:一個服務失敗,導致整條鏈路的服務都失敗的情形。
Hystix 主要功能
隔離

  1. 線程池隔離




  2. 信號量隔離

    降級: 異常,超時

熔斷
限流

Hystrix 降級
Hystix 降級:當服務發生異常或調用超時,返回默認數據

Hystrix 降級 – 服務提供方
1、在服務提供方,引入 hystrix 依賴

2、定義降級方法

3、使用 @HystrixCommand 注解配置降級方法

4、在啟動類上開啟Hystrix功能:@EnableCircuitBreaker

Hystrix 降級 – 服務消費方
1、feign 組件已經集成了 hystrix 組件。(如果沒有引入feign的依賴則需要引入hystrix 的依賴)

2、定義feign 調用接口實現類,復寫方法,即 降級方法

3、在 @FeignClient 注解中使用 fallback 屬性設置降級處理類。

4、配置開啟 feign.hystrix.enabled = true

注意:如果服務方返回的是降級后的數據,也就是征程的數據了,消費方就不會再出現降級

Hystrix 熔斷
Hystrix 熔斷機制,用於監控微服務調用情況,當失敗的情況達到預定的閾值(5秒失敗20次),會打開斷路器,拒絕所有請求,直到服務恢復正常為止。
熔斷器默認的情況下是開啟的機制

修改提供方的代碼

發現降級了

多刷幾次降級的頁面后發現正常的也降級了


稍等5秒鍾左右又恢復正常了

參數設置
circuitBreaker.sleepWindowInMilliseconds:監控時間
circuitBreaker.requestVolumeThreshold:失敗次數
circuitBreaker.errorThresholdPercentage:失敗率


Hystrix 熔斷監控
Hystrix 提供了 Hystrix-dashboard 功能,用於實時監控微服務運行狀態。
但是Hystrix-dashboard只能監控一個微服務。

Netflix 還提供了 Turbine ,進行聚合監控。

快速入門:
1、創建hystrix-monitor模塊,引入坐標

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

        <!-- turbine -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2、配置application.yml文件

spring:
  application:
    name: hystrix-monitor
server:
  port: 8769
turbine:
  combine-host-port: true
   //#配置需要被監控的服務名稱列表
  app-config: hystrix-provider,hystrix-consumer #可以從eureka的頁面中獲取名稱
  cluster-name-expression: "'default'"
  aggregator:
    cluster-config: default
    #instanceUrlSuffix: /actuator/hystrix.stream
  
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

3、 創建啟動類

@SpringBootApplication
@EnableEurekaClient

@EnableTurbine //開啟Turbine 很聚合監控功能
@EnableHystrixDashboard //開啟Hystrix儀表盤監控功能
public class HystrixMonitorApp {
    public static void main(String[] args) {
        SpringApplication.run(HystrixMonitorApp.class, args);
    }
}

4、修改被監控模塊( hystrix-provider和 hystrix-consumer 模塊)
(1)導入依賴

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

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

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>        

(2)配置Bean
此處為了方便,將其配置在啟動類中。

@Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

(3)啟動類上添加注解@EnableHystrixDashboard

@EnableEurekaClient //該注解 在新版本中可以省略
@SpringBootApplication
@EnableCircuitBreaker // 開啟Hystrix功能
@EnableHystrixDashboard // 開啟Hystrix儀表盤監控功能
public class ProviderApp {

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

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

5、啟動測試
(1)、啟動服務:

  • eureka-server
  • hystrix-provider
  • hystrix-consumer
  • hystrix-monitor

(2)、訪問:

在瀏覽器訪問http://localhost:8769/hystrix/ 進入Hystrix Dashboard界面

界面中輸入監控的Url地址 http://localhost:8769/turbine.stream,監控時間間隔2000毫秒和title,如下圖

  • 實心圓:它有顏色和大小之分,分別代表實例的監控程度和流量大小。如上圖所示,它的健康度從綠色、黃色、橙色、紅色遞減。通過該實心圓的展示,我們就可以在大量的實例中快速的發現故障實例和高壓力實例。
  • 曲線:用來記錄 2 分鍾內流量的相對變化,我們可以通過它來觀察到流量的上升和下降趨勢。

** Gateway 網關**
網關旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。
在微服務架構中,不同的微服務可以有不同的網絡地址,各個微服務之間通過互相調用完成用戶請求,客戶端可能通過調用N個微服務的接口完成一個用戶請求。
存在的問題:
客戶端多次請求不同的微服務,增加客戶端的復雜性
認證復雜,每個服務都要進行認證
http請求不同服務次數增加,性能不高
網關就是系統的入口,封裝了應用程序的內部結構,為客戶端提
供統一服務,一些與業務本身功能無關的公共邏輯可以在這里實現,
諸如認證、鑒權、監控、緩存、負載均衡、流量管控、路由轉發等
在目前的網關解決方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等

Gateway 網關快速入門
1.搭建網關模塊

2.引入依賴:starter-gateway

3.編寫啟動類

@SpringBootApplication
@EnableEurekaClient
public class ApiGatewayApp {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApp.class, args);
    }
}

4.編寫配置文件

server:
  port: 80

spring:
  application:
    name: api-gateway-server

  cloud:
    # 網關配置
    gateway:
      # 路由配置:轉發規則
      routes: #集合
      # id: 唯一標識。默認是一個UUID
      # uri: 轉發路徑
      # predicates: 條件,用於請求網關路徑的匹配規則
      - id: gateway-provider
        uri: http://localhost:8001/
        predicates:
          - Path=/goods/**

5.啟動測試

結果如下圖片所示時表示訪問成功

Gateway 網關路由配置 – 靜態路由
訪問地址固定不變

Gateway 網關路由配置 – 動態路由

引入eureka-client配置

修改uri屬性:uri: lb://服務名稱

Gateway 網關路由配置 – 微服務名稱配置

能夠訪問成功

Gateway 過濾器

Gateway 支持過濾器功能,對請求或響應進行攔截,完成一些通用操作。
Gateway 提供兩種過濾器方式:“pre”和“post”
pre 過濾器,在轉發之前執行,可以做參數校驗、權限校驗、流量監控、日志輸出、協議轉換等。
post 過濾器,在響應之前執行,可以做響應內容、響應頭的修改,日志的輸出,流量監控等。
Gateway 還提供了兩種類型過濾器
GatewayFilter:局部過濾器,針對單個路由
GlobalFilter :全局過濾器,針對所有路由

Gateway 過濾器 – 局部過濾器
1.GatewayFilter 局部過濾器,是針對單個路由的過濾器。
2.在Spring Cloud Gateway 組件中提供了大量內置的局部過濾器,對請求和響應做過濾操作。
3.遵循約定大於配置的思想,只需要在配置文件配置局部過濾器名稱,並為其指定對應的值,就可以讓其生效。

Gateway 過濾器 – 全局過濾器

GlobalFilter 全局過濾器,不需要在配置文件中配置,系統初始化時加載,並作用在每個路由上。
Spring Cloud Gateway 核心的功能也是通過內置的全局過濾器來完成。
自定義全局過濾器步驟:
1.定義類實現 GlobalFilter 和 Ordered接口
2.復寫方法
3.完成邏輯處理

@Component
public class MyFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        System.out.println("自定義全局過濾器執行了~~~");

        return chain.filter(exchange);//放行
    }

    /**
     * 過濾器排序
     * @return 數值越小 越先執行
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

隨便訪問一個頁面成功后


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM