SpringCloud

springcloudæ¶æå¾.png

 

Eureka配置

eureka注å中å¿

Eureka Server 的配置

① pom引入依賴

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

② yml文件配置

server:
  port: 7001
spring:
  application:
    name: registry  # 將來會作爲微服務名稱注入到eureka容器中
eureka:
  client:
    service-url:                  # ${server.port} 也可寫死成7001,這麼寫更靈活一些
      defaultZone: http://localhost:${server.port}/eureka  # eureka客戶端的服務地址
      # 以下兩項一定要是false,表明自己是服務器,而不需要從其他主機發現服務
    register-with-eureka: false   # false表示不向註冊中心註冊自己。
    fetch-registry: false         # false表示自己就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務
  server:
    enable-self-preservation: false   # 關閉自我保護模式
    eviction-interval-timer-in-ms: 10000   # 每隔10秒鐘,進行一次服務列表的清理

③ 啓動類

@SpringBootApplication
@EnableEurekaServer //啓用Eureka服務端
public class registryApplication {
    public static void main(String[] args) {
        SpringApplication.run(registryApplication.class);
    }
}

Eureka Client 的配置

① pom引入依賴

<!--將微服務provider註冊進eureka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

② yml 文件配置

server:
  port: 8001
spring:
  application:
    name: registry  # 將來會作爲微服務名稱注入到eureka容器中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka  # 註冊進對應此地址的eureka服務中心
    registry-fetch-interval-seconds: 5  # 設置拉取服務的間隔時間5秒
  instance:
    lease-renewal-interval-in-seconds: 5  # 心跳時間:5秒鐘發送一次心跳
    lease-expiration-duration-in-seconds: 15  # 過期時間:15秒不發送就過期

③ 啓動類

@SpringBootApplication
@EnableDiscoveryClient //啓用Eureka客戶端,@EnableEurekaClient只適用於Eureka作爲註冊中心,@EnableDiscoveryClient可以是其他註冊中心。
public class leyouGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(leyouGatewayApplication.class);
    }
}

④ 註冊成功,在7001的Eureka服務站中會顯示8001微服務

eureka注åæå

actuator與註冊微服務信息完善

actuator:在springboot中主管監控和配置

  • 主機名稱、服務名稱修改

① 修改8001的yml配置

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
   #服務實例名稱修改
  instance:
    instance-id: study-springcloud-dept8001
  • 訪問信息有ip信息提示

② 修改8001yml配置

#客戶端註冊進eureka服務列表
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    #服務實例名稱修改
    instance-id: study-springcloud-dept8001
    #訪問路徑顯示IP地址
    prefer-ip-address: true

Eureka自我保護機制

eurekaèªæä¿æ¤æºå¶

  • Netflix在設置Eureka時,遵循AP原則
  • 某時刻某一微服務不可用時,eureka不會立刻清理,依舊會對改微服務的信息進行保存。服務失去心跳、名稱變更、網絡擁堵
  • **自我保護機制:**應對網絡異常的安全措施

默認情況下,如果EurekaServer在一定時間內沒有接收到某個微服務實例的心跳,EurekaServer將會註銷實例(默認90秒)。但是當網絡分區故障發生時,微服務與EurekaServer之間無法正常通信,以上行爲可能變得非常危險——因爲微服務本身其實是健康的,此時本不應該註銷這個服務。Eureka通過“自我保護模式”來解決這個問題——當EurekaServer節點再短時間內丟失過多客戶端時(可能發生網絡故障),那麼這個節點就會進入自我保護模式。一旦進去該模式,EurekaServer就會保護服務註冊表中的信息,不再刪除服務註冊表中的數據(也即不會註銷任何微服務)。當網絡故障恢復後,改EurekaServer節點會自動退出自我保護模式。

寧可保護錯誤的註冊信息,也不盲目註銷任何可能健康的微服務實例。

禁用自我保護機制
可以使用eureka.server.enable-self-preservation=false

Eureka服務發現

對於註冊進eureka裏面的服務,可以通過服務發現獲得該服務的信息。

① 添加服務發現接口

在8001工程的Controller類中增加DiscoveryClient。

@Autowired
private DiscoveryClient discoveryClient;

② 增加自己服務描述的接口

@RequestMapping(value = "/dept/discovery",method = RequestMethod.GET)
public Object discovery(){
    List<String> list = discoveryClient.getServices();
    List<ServiceInstance> instances = discoveryClient.getInstances("STUDY-SPRINGCLOUD-DEPT");

    for (ServiceInstance element : instances){
        System.out.println(element.getServiceId());
        System.out.println(element.getHost());
        System.out.println(element.getPort());
        System.out.println(element.getUri());
    }
    return this.discoveryClient;
}

③ 8001主啓動類中增加 @EnableDiscoveryClient 註解

④ 啓動,調用 http://localhost:8001/dept/discovery

 

Ribbon負載均衡

概述:

基於Netflix ribbon實現的一套 客戶端、負載均衡的工具。

重要功能是提供客戶端的軟件負載均衡算法,Ribbon客戶端組件提供一系列的配置項如鏈接超時、重試等。

(æ¶æå¾.png

通過Spring Cloud Ribbon的封裝,我們在微服務架構中使用客戶端負載均衡調用非常簡單,只需要如下兩步:

  • 服務提供者只需要啓動多個服務實例並註冊到一個註冊中心或是多個相關聯的服務註冊中心。
  • 服務消費者直接通過調用被@LoadBalanced註解修飾過的RestTemplate來實現面向服務的接口調用。

這樣,我們就可以將服務提供者的高可用以及服務消費者的負載均衡調用一起實現了。

Ribbon配置:

① 修改pom配置,增加相關引用

<!--Ribbon相關引用,與eureka有關-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

② 修改application.yml ,追加Eureka的註冊服務地址

eureka:
  client:
    service-url:
      defaultZone: eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
# 將Ribbon的負載均衡策略修改爲隨機
service_provider: #採用Ribbon的服務實例
  ribbon:
    NFLoadBalanceRuleClassName:com.netflix.loadbalancer.RandomRule

③ 主啓動類中增加註解@EnableEurekaClient

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

④ 主啓動類中增加getRestTemplate方法,並增加@LoadBalance註解,開啓客戶端負載均衡

    /**
     * 配置RestTemplate
     * 通過RestTemplate調用提供者服務 ,發送rest請求
     * 提供了多種訪問http服務的方法,
     * 針對於訪問rest服務客戶端的調用的模板類
     */
    @Bean
    @LoadBalanced //ribbon實現的一套 客戶端、負載均衡的工具
    public  RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

⑤ 將地址改爲註冊在EurekaServer中的微服務名稱

// 註冊在EurekaServer中的微服務名稱
@GetMapping
@ResponseBody
public User queryUserById(Long id){
    return this.restTemplate.getForObject("http://service-provider/user/"+id,User.class);
}

Ribbon核心組件IRule

IRule:根據特定算法中從服務列表中選取一個要訪問的服務。

 

Feign 負載均衡

簡介:

Feign是Netflix開發的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優雅地調用HTTP API。

在Spring Cloud中,使用Feign非常簡單——創建一個接口,並在接口上添加一些註解,代碼就完成了。Feign支持多種註解,例如Feign自帶的註解或者JAX-RS註解等。

Spring Cloud對Feign進行了增強,使Feign支持了Spring MVC註解,並整合了Ribbon和Eureka,從而讓Feign的使用更加方便。

Spring Cloud Feign是基於Netflix feign實現,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供這兩者的強大功能外,還提供了一種聲明式的Web服務客戶端定義的方式。

Spring Cloud Feign幫助我們定義和實現依賴服務接口的定義。在Spring Cloud feign的實現下,只需要創建一個接口並用註解方式配置它,即可完成服務提供方的接口綁定,簡化了在使用Spring Cloud Ribbon時自行封裝服務調用客戶端的開發量。

Spring Cloud Feign具備可插拔的註解支持,支持Feign註解、JAX-RS註解和Spring MVC的註解。

① 引入Feign 依賴

<!--增加Feign的依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

② 創建一個Feign接口,並添加@FeignClient註解,定義Feign客戶端,並指定微服務id。

/**
 *Feign通過接口的方法調用Rest服務(之前是Ribbon+RestTemplate)
 */
@FeignClient("service-provider")
//@RequestMapping("user") //不建議寫在這
public interface UserClient{

    @GetMapping("{user/id}")
    public User queryUserById(@PathVariable("id")Long id);

}

③ 主啓動類添加 @EnableFeignClients註解,啓用Feign客戶端

 

 

Feign集成了Ribbon

利用Ribbon維護了微服務列表,並且通過輪詢實現了客戶端的負載均衡。而與Ribbon不同的是,通過Feign只需要定義服務綁定接口且以聲明式的方法,優雅的而簡單的實現了服務調用。

 

 

Hystrix 熔斷

簡介:

分佈式面臨的問題:

複雜分佈式體系結構複雜的依賴關係,不可避免的存在服務宕機,網絡中斷的問題。

服務雪崩:

多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其他的服務,這就是所謂的扇出。如果扇出的鏈路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會佔用越來越多的系統資源,進而引起系統崩潰,所謂的雪崩效應。

對於高流量的應用來說,單一的後端依賴可能會導致所有服務器上的所有資源都在幾秒鐘內飽和。比失敗更糟糕的是,這些應用程序還可能導致服務之間的延遲增加,備份隊列,線程和其他系統資源的緊張,導致整個系統發生更多的級聯故障。這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關係的失敗,不能取消整個應用程序或系統。

Hystrix介紹:

Hystrix是Netflix開源的一個延遲和容錯庫,通過添加延遲容忍和容錯邏輯,幫助你控制這些分佈式服務之間的交互。Hystrix通過隔離服務之間的訪問點、停止級聯失敗和提供回退選項來實現這一點,所有這些都可以提高系統的整體彈性。

Hystrix解決雪崩問題的手段有兩個:

  • 線程隔斷
  • 服務熔斷

Hystrix爲每個依賴服務調用分配一個小的線程池,如果線程池已滿調用將被立即拒絕,默認不採用排隊,加速失敗判斷時間。

用戶的請求將不再直接訪問服務,而是通過線程池中的空閒線程來訪問服務,如果線程池已滿,或者請求超時,則會進行降級處理——優先保證核心服務,而非核心服務不可用或弱可用。

用戶的請求故障時,不會被立即阻塞,更不會無休止的等待或者看到系統崩潰,至少可以看到一個執行結果(例如返回一個提示信息)。

服務降級雖然會導致請求失敗,但是不會導致阻塞,而且最多會影響這個以來服務對應的線程池中的資源,對其他服務沒有響應。

觸發Hystrix服務降級的情況:

  • 線程池已滿
  • 請求超時

服務降級:

整體資源不夠了,忍痛將某些服務先關掉,待度過難關後再開啓。

資源的搶佔和分配

所謂降級,一般是從整體負荷考慮,當某個服務熔斷後,服務器將不再被調用,此時客戶端可以自己準備一個本地的fallback回調,返回一個缺省值,這樣做,雖然服務水平下降,好歹能用,比直接改掉要強。

服務降級是在客戶端(消費者)處理完成的,與服務端沒關係。

① 引入Hystrix依賴

<!--Hystrix依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

② 主啓動類上添加 @EnableCircuitBreaker 註解開啓熔斷

//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker
@SpringCloudApplication //組合註解,相當於上面三個註解的組合
public class ItcastServiceConsumerApplication {

③ 定義一個局部熔斷方法(要和被熔斷的方法返回值和參數列表一致)

public String queryUserByIdFallback(Long id){
    return "服務正忙,請稍後再試!";
}

④ @HystrixCommand 聲明被熔斷的方法

一旦服務調用失敗並拋出錯誤信息後,被熔斷方法會自動調用@HystrixCommand標註好的fallBackMethod調用類中知道的方法

@GetMapping
@ResponseBody
@HystrixCommand(fallbackMethod="queryUserByIdFallback")
public String queryUserById(Long id){
    return this.restTemplate.getForObject("http://service-provider/user/"+id,User.class);
}

⑤ 也可以在類上定義一個全局的熔斷方法(返回值類型要和被熔斷的方法一致,參數列表必須爲空)

@DefaultProperties(defaultFallback = queryUserByIdFallback )
@Controller
public class UserController{

    @HystrixCommand  //哪個方法需要熔斷就加在哪個方法上面
    public String queryUserById(Long id){
}
}

設置超時

在之前的案例中,請求在超過1秒後都會返回錯誤信息,這是因爲Hystrix的默認超時時長爲1,我們可以通過設置修改這個值:

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds:6000 # 設置hystrix的超時時間爲6000ms

服務熔斷

熔斷原理:

熔斷器,也叫斷路器,其英文單詞爲:Circult Breaker。

不同於電路熔斷只能斷不能自動重連,Hystrix可以實現彈性容錯,當情況好轉之後,可以自動重連。通過短路的方式,可以將後續請求直接拒絕掉,一段時間之後允許部分請求通過,如果調用成功則回到電路閉合狀態,否則繼續斷開。

熔斷機制3個狀態:

  • Closed:關閉狀態,所有請求都正常訪問。
  • Open:打開狀態,所有請求都會被降級。Hystrix會對請求情況計數,當一定時間內失敗請求百分比達到閾值,則觸發熔        斷,斷路器會完全打開。默認失敗的閾值是50%,請求次數最少不低於20次。
  • Half Open:半開狀態,open狀態不是永久的,打開後會進入休眠時間(默認是5秒)。隨後斷路器會自動進入半開狀態。此時會釋放部分請求通過,若這些請求都是健康的,則會完全關閉斷路器,否則繼續保持斷開,再次進行休眠計時。

通過配置修改熔斷策略:

circuitBreaker.requestVolumThreshold=20  # 觸發熔斷的最小請求次數,默認20
circuitBreaker.sleepWindowInMillisseconds=50000  # 休眠時長,默認是5000毫秒
circuitBreaker.errorThresholdPercentage=50  # 出發熔斷的失敗請求最小佔比,默認50%

zuul路由網關

概述:

服務網關是微服務架構中一個不可或缺的部分。通過服務網關統一向外系統提供REST API的過程中,除了具備服務路由、均衡負載功能之外,它還具備了權限控制等功能。Spring Cloud Neflix中的Zuul就擔任了這樣的一個角色,爲微服務架構提供了前門保護的作用,同時將權限控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集羣主體能夠具備更高的可複用性和可測試性。

① 引入Zuul依賴

<!--zuul依賴-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

② yml文件配置

server:
  port: 10010
spring:
  application:
    name: itcast-zuul
eureka:
  client:
    service-url:
      defaultZone:http://localhost:10086/eureka

① 通過路徑路由
zuul:
  routes:
    service-provider: # 路由名稱,可以隨便寫,習慣上寫服務名
      path:/service-provider/**  # 這裏是映射路徑
      url:http://localhost:8082  # 映射路徑對應的實際url地址
      # 我們將符合path規則的一切請求,都代理到url參數指定的地址。
      # 本例中我們將/service-provider/** 開頭的請求,代理到http://localhost:8082


② 通過服務id路由
zuul:
  routes:
    service-provider:/service-provider/**
      serviceId:service-provider  # 路由到對應serviceId

③ 簡化參數
zuul:
  routes: # 由於路由名稱默認就是服務名,乾脆就把它看成服務id,對/service-provider/**的請求路由到service-provider
  prefix: /api  # 路由前綴,完整訪問路徑變爲 /api/service-provider/**
    service-provider:/service-provider/**

④ 不配置,默認就是服務id開頭的路徑路由到對應服務

③ 主啓動類添加註解@EnableZuulProxy,啓用Zuul組件

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章