Spring Cloud入門看這一篇就夠了

2022-06-11 15:00:42

SpringCloud微服務

架構演進

  • 單體架構
  • 垂直拆分
  • 分散式SOA面向服務架構
  • 微服務架構

服務呼叫方式:

  • RPC,早期的webservice,現在熱門的dubbo,都是RPC的典型代表
  • HTTP,HttpClient,OKHttp,URLConnection,RestTemplate

Euraka服務註冊中心

註冊中心
  1. 新增依賴
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  1. 使用@EnableEurekaServer註解開啟註冊服務
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
  1. 編寫組態檔application.yml
server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    #是否將自己註冊到Eureka服務中,預設為true(由於當前就是eureka服務,固設定為false)
    registerWithEureka: false 
    #設定是否從eureka服務上獲取註冊資訊,預設為true(由於當前就是eureka服務,固設定為false)
    fetchRegistry: false
  server:
      # 是否開啟自我保護模式(自我保護模式,當eureka在一定時間內沒有接受到某個微服務範例的心跳包,預設90S會登出該範例),
      # 一旦進入自我保護模式,若短時間內丟失大量使用者端,eureka也會保護登入檔的資訊,不再登出
      enable-self-preservation: false
      # 清理間隔。預設為60000ms
      eviction-interval-timer-in-ms: 5000
服務提供者(服務註冊)
  1. 新增依賴
<!-- Eureka使用者端 --> 
<dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 
</dependency

2.新增 @EnableDiscoveryClient 來開啟Eureka使用者端功能

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

3.編寫組態檔

eureka:
  instance:
    #在呼叫服務的時候就已經變成ip地址;需要注意的是:不是在eureka中的控制檯服務範例狀態顯示。
    ip-address: 127.0.0.1
  	prefer-ip-address: true #使用ip註冊
  client:
    # 是否開啟健康檢查
    healthcheck:
      enabled: true
    # 叢集url
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka
服務消費者(服務發現)

消費應用從註冊中心獲取服務列表,從而得知每個服務方的資訊,知道去哪裡呼叫服務方

服務續約

在註冊服務完成以後,服務提供者會維持一個心跳(定時向EurekaServer發起Rest請求),有兩個重要引數可以修改服務續約的行為

eureka: 
	instance: 
	    #服務失效時間,預設值90秒
		lease-expiration-duration-in-seconds: 90 
		#服務續約(renew)的間隔,預設為30秒
		lease-renewal-interval-in-seconds: 30

也就是說,預設情況下每隔30秒服務會向註冊中心傳送一次心跳,證明自己還活著。如果超過90秒沒有傳送心跳,EurekaServer就會認為該服務宕機,會定時(eureka.server.eviction-interval-timer-in-ms設定的時間)從服務列表中剔除

失效剔除和自我保護

服務註冊中心在啟動時會建立一個定時任務,預設每隔一段時間(預設為60秒)將當前清單中超時(預設為90秒)沒有續約的服務剔除。

Eureka Server在執行期間,會統計心跳失敗的比例在15分鐘之內是否低於85%,如果出現低於的情況,Eureka Server會將當前的範例註冊資訊保護起來,不再刪除服務登入檔中的資料(也就是不會登出任何微服務)

Consul

特性
  • 高效的Raft一致性演演算法
  • 支援多資料中心
  • 支援健康檢查
  • HTTP和DNS支援
Consul和Eureka的區別:
  • Consul強一致性(CP),Eureka保證高可用和最終一致性(AP)

  • Consul使用Go語言,Eureka使用Java語言

  • Consul 不同於 Eureka 需要單獨安裝,官網:https://www.consul.io/downloads

Consul架構圖

Consul基本使用

服務提供者

  1. pom.xml新增依賴
<!--SpringCloud提供的基於Consul的服務發現-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
 <!--actuator用於心跳檢查-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  1. 通過@EnableDiscoveryClient註解開啟對服務發現的支援
  2. 編寫組態檔application.yml
spring:
  application:
    name: consul-provider
  ####consul註冊中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name} #註冊中心名字與spring的應用名稱一致
        #-----------------------------相關設定----------------------------|
        #是否註冊
        register: true
        #範例ID
        instance-id: ${spring.application.name}-1
        #服務範例名稱
        service-name: ${spring.application.name}
        #服務範例埠
        port: ${server.port}
        #健康檢查路徑
        healthCheckPath: /actuator/health
        #健康檢查時間間隔
        healthCheckInterval: 15s
        #開啟ip地址註冊
        prefer-ip-address: true
        #範例的請求ip
        ip-address: ${spring.cloud.client.ip-address}

服務消費者

  1. pom.xml新增依賴
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  1. 編寫組態檔application.yml
spring:
  application:
    name: consul-provider
  ####consul註冊中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #設定不需要註冊到Consul中
        register: false

負載均衡Ribbon

Ribbon是 Netflix 釋出的一個負載均衡器,有助於控制 HTTP 和 TCP使用者端行為。Ribbon自動的從註冊中心中獲取服務提供者的

列表資訊,並基於內建的負載均衡演演算法,請求服務。

搭建過程
  1. 啟動兩個服務範例

先編寫請求的介面

@Value("${spring.cloud.client.ip-address}")
private String ip;
@Value("${server.port}")
private String port;
@ResponseBody
@RequestMapping(value = "backInfo", method = RequestMethod.GET)
public String backInfo() {
	return "呼叫的是" + ip + "埠是:" + port;
}

我們假設搭建兩臺服務提供者,埠分別為:8090和8091,將已有服務的設定更改為

server: 
	#的${}表示在jvm啟動時候若能找到對應port則使用,若無則使用後面的預設值
	port: ${port:8090}

另外一臺在啟動的時候可以指定埠port,在如下介面中的 VM options 中設定 -Dport=10087

  1. 啟動負載均衡

因為Eureka中已經整合了Ribbon,所以我們無需引入新的依賴。直接修改消費者的啟動類

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
	return new RestTemplate();
}
  1. 調取服務提供者介面,頁面進行測試,可以分別請求到8090和8091兩個埠
@Autowired
private RestTemplate restTemplate;
@ResponseBody
@RequestMapping(value = "getIpAndPort", method = RequestMethod.GET)
public String printInfo() {
	String url = "http://springbootdemo/backInfo";
	return restTemplate.getForObject(url, String.class);
}
負載均衡策略

Ribbon預設的負載均衡策略是輪詢,Ribbon內建了多種負載均衡策略

修改負載均衡規則的設定:

springbootdemo:
  ribbon: 
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    #格式是: {服務名稱}.ribbon.NFLoadBalancerRuleClassName
  • com.netflix.loadbalancer.RoundRobinRule :以輪詢的方式進行負載均衡。
  • com.netflix.loadbalancer.RandomRule :隨機策略
  • com.netflix.loadbalancer.RetryRule :重試策略
  • com.netflix.loadbalancer.WeightedResponseTimeRule :權重策略
  • com.netflix.loadbalancer.BestAvailableRule :最佳策略
  • com.netflix.loadbalancer.AvailabilityFilteringRule :可用過濾策略

策略選擇:

  1. 如果每個機器設定一樣,則建議不修改策略 (推薦)

  2. 如果部分機器設定強,則可以改為 WeightedResponseTimeRule

原始碼跟蹤

RibbonAutoConfifiguration->LoadBalancerAutoConfiguration->LoadBalancerInterceptor

服務呼叫Feign

Feign是一種宣告式、模板化的HTTP使用者端。

基於Feign的服務呼叫

1.在消費者引入依賴

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

2.啟動類開啟feign支援

@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(basePackages = "com.jyd0124.consume_server.*")
@EnableFeignClients
public class ConsumeServerApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate returnBean() {
        return new RestTemplate();
    }
}

3.建立介面和定義需要遠端呼叫的方法

@FeignClient("springbootdemo")
public interface SpringBootFeign {

    @RequestMapping(value = "/person", method = RequestMethod.GET)
    public Map<String, Object> getPerson(@RequestParam(value = "id") int id);

}

4.呼叫服務。

@Autowired
private SpringBootFeign springBootFeign;
    
@ResponseBody
@RequestMapping(value = "/person/{id}", method = RequestMethod.GET)
public Map<String,Object> printInfo(@PathVariable("id") int id) {
	return springBootFeign.getPerson(id);
}

5.存取,測試結果

負載均衡

Feign中本身已經整合了Ribbon依賴和自動設定,因此我們不需要額外引入依賴,也不需要再註冊RestTemplate 物件,可以通過 ribbon.xx 來進行全域性設定。也可以通過 服務名.ribbon.xx 來對指定服務設定。

Feign的設定
feign:
  client:
    config:
      feignName: ##定義FeginClient的名稱
        connectTimeout: 5000 # 建立連結的超時時長
        readTimeout: 5000 # 讀取超時時長
        # 設定Feign的紀錄檔級別,相當於程式碼設定方式中的Logger
        loggerLevel: full
        # Feign的錯誤解碼器,相當於程式碼設定方式中的ErrorDecoder
        errorDecoder: com.example.SimpleErrorDecoder
        # 設定重試,相當於程式碼設定方式中的Retryer
        retryer: com.example.SimpleRetryer
        # 設定攔截器,相當於程式碼設定方式中的
        RequestInterceptor requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        #設定熔斷不處理404異常
        decode404: false

請求壓縮: 支援對請求和響應進行GZIP壓縮,以減少通訊過程中的效能損耗

#請求壓縮
feign:
  compression:
    request:
      enabled: true # 開啟請求壓縮
    response:
      enabled: true # 開啟響應壓縮
Hystrix支援

Feign預設也有對Hystrix的整合

feign: 
	hystrix: 
		enabled: true # 開啟Feign的熔斷功能
紀錄檔級別

預設情況下Feign的紀錄檔是沒有開啟的。

feign:
  client:
    config:
      feignName:
        loggerLevel: full
        #NONE【效能最佳,適用於生產】:不記錄任何紀錄檔(預設值)
        #BASIC【適用於生產環境追蹤問題】:僅記錄請求方法、URL、響應狀態程式碼以及執行時間
        #HEADERS:記錄BASIC級別的基礎上,記錄請求和響應的header。
        #FULL【比較適用於開發及測試環境定位問題】:記錄請求和響應的header、body和後設資料

熔斷器Hystrix

雪崩效應

在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以相互呼叫(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來呼叫。為了保證其高可用,單個服務通常會叢集部署。由於網路原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,呼叫這個服務就會出現執行緒阻塞,此時若有大量的請求湧入,Servlet容器的執行緒資源會被消耗完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的「雪崩」效應。

Hystrix的特性
  • 服務熔斷

Hystrix的熔斷狀態機模型:

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 2000
      circuitBreaker:
        errorThresholdPercentage: 50 # 觸發熔斷錯誤比例閾值,預設值50%
        sleepWindowInMilliseconds: 10000 # 熔斷後休眠時長,預設值5秒
        requestVolumeThreshold: 10 # 觸發熔斷的最小請求次數,預設20
        
        #設定項可以參考 HystrixCommandProperties 類
  • 服務降級

    通過HystrixdeCommand的fallback實現服務降級。

  • 服務隔離

​ -執行緒池隔離策略

​ - 號誌隔離策略

Ribbon中使用斷路器
  1. 在pom.xml中新增依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
  1. 在啟動類上新增註解開啟Hystrix
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class ConsumeServerApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate returnBean() {
        return new RestTemplate();
    }
}
  1. 編寫熔斷降級邏輯。在方法上加上@HystrixCommand註解,並指定了fallbackMethod熔斷方法
@ResponseBody
@RequestMapping(value = "/info", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "backErrorInfo")
public String printInfo() {
    String url = "http://springbootdemo/backInfo";
    return restTemplate.getForObject(url, String.class);
}
public String backErrorInfo(){
    return "sorry,error";
}
  1. 測試,如果springbootdemo服務關閉,會發現頁面返回了降級處理資訊

Feign中使用斷路器

SpringCloud Fegin預設已為Feign整合了hystrix

  1. 新增設定
feign: 
	hystrix: 
		enabled: true # 開啟Feign的熔斷功能
  1. 設定FeignClient介面的實現類,並通過@Component注入到Ioc容器中
@Component
public class HystrixMethod implements SpringBootFeign {
    @Override
    public Map<String, Object> getPerson(int id) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", 500);
        map.put("msg", "sorry,error");
        return map;
    }
}
  1. 在@FeignClient註解中新增降級方法
@FeignClient(name = "springbootdemo", fallback = HystrixMethod.class)
public interface SpringBootFeign {

    @RequestMapping(value = "/person", method = RequestMethod.GET)
    public Map<String, Object> getPerson(@RequestParam(value = "id") int id);

}
  1. 關閉 springbootdemo 服務,存取測試

Hystrix Dashboard
  1. 新增依賴
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
  1. 在啟動類使用@EnableHystrixDashboard註解啟用儀表盤
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableHystrixDashboard
public class ConsumeServerApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate returnBean() {
        return new RestTemplate();
    }
}
  1. 存取頁面

遇到問題:https://blog.csdn.net/ghyghost/article/details/108053206

斷路器聚合監控Turbine,Turbine是一個聚合Hystrix 監控資料的工具。

閘道器Gateway

介紹

Spring Cloud Gateway 是 Spring 官方基於 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的閘道器,旨在為微服務架構提供一種簡單而有效的統一的 API 路由管理方式。Spring Cloud Gateway 作為 Spring Cloud 生態系中的閘道器,目標是替代 Netflflix ZUUL,其不僅提供統一的路由方式,並且基於 Filter 鏈的方式提供了閘道器基本的功能,例如:安全,監控/埋點,和限流等。

快速入門
  1. 建立gateway-server模組,引入依賴
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 編寫啟動類
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayServerApplication {

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

}
  1. 編寫路由規則
server:
  port: 8765
spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      #由一個ID、一個目的URL、一組斷言工廠、一組Filter組成
      routes:
          # 路由id,可以隨意寫
        - id: consume-server-route
          # 代理的服務地址
          uri: http://127.0.0.1:8081
          # 路由斷言,可以設定對映路徑
          predicates:
            - Path=/person/**
eureka:
  client:
    # 叢集url
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka
  instance:
    prefer-ip-address: true #使用ip註冊
    ip-address: 127.0.0.1
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
  1. 啟動測試

路由
  1. 新增字首PrefixPath
spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      #由一個ID、一個目的URL、一組斷言工廠、一組Filter組成
      routes:
          # 路由id,可以隨意寫
        - id: consume-server-route
          # 代理的服務地址
          uri: http://127.0.0.1:8081
          # 路由斷言,可以設定對映路徑
          predicates:
            - Path=/**
          filters: 
          	# 新增請求路徑的字首 
          	- PrefixPath=/person  

相當於PrefixPath=/personhttp://localhost:8765/180868 --》http://localhost:8765/person/180868 --》http://localhost:8081/person/180868

  1. 去除字首StripPrefifix
spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      #由一個ID、一個目的URL、一組斷言工廠、一組Filter組成
      routes:
          # 路由id,可以隨意寫
        - id: consume-server-route
          # 代理的服務地址
          uri: http://127.0.0.1:8081
          # 路由斷言,可以設定對映路徑
          predicates:
            - Path=/api/person/**
          filters: 
          	# 表示過濾1個路徑,2表示兩個路徑,以此類推
          	- StripPrefix=1

StripPrefix=1 http://localhost:8765/api/person/180868--》http://localhost:8765/person/180868--》http://localhost:8081/person/180868

  1. 動態路由

uri以 lb: //開頭(lb代表從註冊中心獲取服務),後面接的就是你需要轉發到的服務名稱

spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      routes:
          # 路由id,可以隨意寫
        - id: consume-server-route
          # 代理的服務地址
          uri: lb://springbootdemo
          # 路由斷言,可以設定對映路徑
          predicates:
            - Path=/person/**
  1. 重寫轉發路徑

路由轉發是直接將匹配的路由path直接拼接到對映路徑(URI)之後,那麼往往沒有那麼便利。修改application.yaml

spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      routes:
          # 路由id,可以隨意寫
        - id: consume-server-route
          # 代理的服務地址
          uri: lb://springbootdemo
          # 路由斷言,可以設定對映路徑
          predicates:
            - Path=/springbootdemo/**
          filters:
          	- RewritePath=/springbootdemo/(?<segment>.*), /$\{segment}

請求http://localhost:8765/springbootdemo/person/180868 --》http://localhost:8765/person/180868--》http://localhost:8081/person/180868( 值得注意的是在yml檔案中 $ 要寫成 $\ )

  1. 基於服務發現的路由規則
spring:
  application:
    # 註冊到eureka上的應用名稱
    name: gateway_server
  cloud:
    gateway:
      discovery:
        locator:
          #設定路由存取方式:http://Gateway_HOST:Gateway_PORT/大寫的serviceId/**,其中微服務應用名預設大寫存取。
          enabled: true
          # 該設定可以將服務名改成小寫(預設為大寫)
          lower-case-service-id: true

這樣,就可以通過http://localhost:8765/springbootdemo/person?id=180868存取

過濾器
  1. 生命週期
  • pre:: 這種過濾器在請求被路由之前呼叫。
  • post : 這種過濾器在路由到微服務以後執行。
  1. 過濾器型別
  • 區域性過濾器(GatewayFilter),應用到單個路由或者一個分組的路由上,通過 spring.cloud.gateway.routes.filters 設定在具體路由下,只作用在當前路由上;
  • 全部過濾器(GlobalFilter),應用到所有的路由上,實現 GlobalFilter 介面即可
  1. 常見過濾器
過濾器名稱 說明
AddRequestHeader 對匹配上的請求加上Header
AddRequestParameters 對匹配上的請求路由新增引數
AddResponseHeader 對從閘道器返回的響應新增Header
StripPrefifix 對匹配上的請求路徑去除字首

設定全域性預設過濾器

spring:
  cloud:
    gateway:
      default-filters:
      	- AddResponseHeader=X-Response-Default-MyName, jyd0124

其他過濾器具體可參考GatewayFilterFactory類

  1. 自定義過濾器

    需求:模擬一個登入的校驗。基本邏輯:如果請求中有token引數,則認為請求有效,放行。

@Component
public class TokenFilter implements GlobalFilter, Ordered {
    private final Logger logger = LoggerFactory.getLogger(TokenFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //request,response都可以通過 ServerWebExchange 獲取
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isBlank(token)) {
            logger.info("token is empty ...");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //chain.filter 繼續向下遊執行
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //過濾器的優先順序,返回值越大級別越低
        return 0;
    }
}
跨域問題
@Configuration
public class GwCorsFilter {

    /**
     *  以下CorsWebFilter跨域處理也可以通過組態檔進行處理
     * spring:
     *   cloud:
     *     gateway:
     *       globalcors:
     *         cors-configurations:
     */
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true); // 允許cookies跨域
        config.addAllowedOrigin("*");// #允許向該伺服器提交請求的URI,*表示全部允許,在SpringMVC中,如果設成*,會自動轉成當前請求頭中的Origin
        config.addAllowedHeader("*");// #允許存取的頭資訊,*表示全部
        config.setMaxAge(18000L);// 預檢請求的快取時間(秒),即在這個時間段裡,對於相同的跨域請求不會再預檢了
        config.addAllowedMethod("OPTIONS");// 允許提交請求的方法型別,*表示全部允許
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");

        UrlBasedCorsConfigurationSource source =
                new  UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }

    /**
     *
     *如果使用了註冊中心(如:Eureka),進行控制則需要增加如下設定
     */
    @Bean
    public RouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient) {
        return new DiscoveryClientRouteDefinitionLocator(discoveryClient,new DiscoveryLocatorProperties());
    }

    /**
     * 以下是springboot2.0.5出現only one connection 的解決辦法
     * @return
     */
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
                return chain.filter(exchange);
            }
        };
    }
}
負載均衡和熔斷

Gateway中預設已經整合了Ribbon負載均衡和Hystrix熔斷機制。但是所有的策略都是走的預設值,建議根據Ribbon和Hystrix手動進行設定。

閘道器限流
  • 計數器限流演演算法
  • 漏桶演演算法
  • 令牌桶演演算法
  • 基於Filter的限流
  • 基於Sentinel的限流

SpringCloud Config設定中心

在gitee上建立遠端組態檔

構建config設定中心服務
  1. 構建Config-server服務,新增依賴
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 在config-server的啟動類新增@EnableConfigServer
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigServerApplication {

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

}
  1. 編寫config-server組態檔
server:
  port: 8888
spring:
  application:
    name: config_server
  cloud:
    config:
      server:
        git:
          #組態檔所在的git倉庫
          uri: https://gitee.com/jyd0124/springcloudconfig.git
          #組態檔分支
          default-label: master
          #組態檔所在根目錄
          search-paths: config
          #如果Git倉庫為公開倉庫,可以不填寫使用者名稱和密碼,如果是私有倉庫需要填寫
          username: xxx
          password: xxx
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka #服務註冊地址
  1. 可通過http://localhost:8888/consume-server.yml測試是否成功
獲取設定中心設定
  1. 改造其他隨便一個服務,比如我使用我自己的consume_server,新增依賴
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 修改設定

刪除consume_server的application.yml 檔案(因為該檔案從設定中心獲取)

建立consume_server 的bootstrap.yml 組態檔,其內容如下

spring:
  cloud:
    config:
      name: consume-server
      # 遠端倉庫中的版本保持一致
      label: master
      #profile: dev
      #通過ip直接存取設定中心
      #uri: http://localhost:8888/
      #通過eurka存取設定中心
      discovery:
        #設定中心服務
        service-id: config-server
        enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka #服務註冊地址

3.啟動consume_server專案發現獲取到組態檔將服務暴露在8081埠,測試介面可成功返回資料

補充:bootstrap.yml檔案也是Spring Boot的預設組態檔,而且其載入的時間相比於application.yml更早。bootstrap.yml檔案相當於專案啟動時的引導檔案,內容相對固定。application.yml檔案是微服務的一些常規設定引數,變化比較頻繁。

Spring Cloud Bus服務匯流排

問題:

前面已經完成了將微服務中的組態檔集中儲存在遠端Git倉庫,如果我們更新Git倉庫中的組態檔,那使用者微服務是否可以及時接收到新的設定資訊並更新呢?經過測試,對於Git倉庫中組態檔的修改並沒有及時更新到使用者微服務,只有重啟使用者微服務才能生效。如果想在不重啟微服務的情況下更新設定該如何實現呢? 可以使用Spring Cloud Bus來實現設定的自動更新。

介紹

Spring Cloud Bus是用輕量的訊息代理將分散式的節點連線起來,可以用於廣播組態檔的更改或者服務的監控管理。也就是訊息匯流排可以為微服務做監控,也可以實現應用程式之間相互通訊。 Spring Cloud Bus可選的訊息代理有兩種:RabbitMQ和Kafka。

具體實現可參考:https://www.fangzhipeng.com/springcloud/2018/08/08/sc-f8-bus.html
https://www.cnblogs.com/babycomeon/p/11141160.html

Spring Cloud 體系技術綜合應用概覽