SpringCloud及其五大常用組件之Feign、Ribbon和Hystrix


1.Feign

我們已經將Eureka和Zuul開發完畢,而且上面注冊了兩個微服務,現在我們實現兩個微服務之間的調用。

String baseUrl = "http://127.0.0.1:10010/user-service/user/";
User user = this.restTemplate.getForObject(baseUrl + id, User.class)

這樣雖然能訪問到,但是這樣的代碼不太優雅,這里使用了spring提供的RestTemplate,已經簡化了操作,如果使用遠程的httpclient,那更是懷疑人生,怎么實現優雅的訪問呢?答案是Feign

Feign的英文含義假裝,偽裝

為什么叫偽裝?

Feign可以把Rest的請求進行隱藏,偽裝成類似SpringMVC的Controller一樣。你不用再自己拼接url,拼接參數等等操作,一切都交給Feign去做。

下面為我們的demo加上feign:

1.在consumer-demo中導入依賴

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

2.開發feign的客戶端,其實就是一個接口

@FeignClient("user-service") //聲明這是一個Feign客戶端,同時通過value屬性指定服務名稱
public interface UserClient {

    @GetMapping("/user/{id}")  //這里的返回結果和 url地址一定要和提供方保持一致
    User queryById(@PathVariable("id") Long id);
}

注意:訪問路徑和返回結果一定要與服務端的提供方一致,因為feign會根據這個路徑為我們生成代理對象

3.在啟動類上開啟feign的功能

@SpringCloudApplication
@EnableFeignClients // 開啟Feign功能
public class ConsumerDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerDemoApplication.class, args);
    }
}

4.現在就可以使用feign的方式進行訪問了

@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private UserClient userClient;

    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id){
        return userClient.queryById(id);
    }
}

到這里feign的功能就已經實現了,單獨看controller是看不出使用了遠程調用的,這就是feign的作用

最后強調:Feign中本身已經集成了Ribbon依賴和自動配置,不用再次引入依賴,就可以直接配置ribbon相關的參數

2.ribbon

說完了feign,可以知道,feign是通過服務在Eureka上的serviceId來找尋服務的,也就是user-service,那么如果我們現在有兩個user-service的服務:

user-service: 192.168.100.1

user-serivice: 192.168.100.2

那么feign怎么知道你要請求的是哪個服務器呢?

​ 這Ribbon就派上用場了。Ribbon就是專門解決這個問題的。它的作用是負載均衡,會幫你在每次請求時選擇一台機器,均勻的把請求分發到各個機器上

Ribbon的負載均衡默認使用的最經典的Round Robin輪詢算法。這是啥?簡單來說,就是如果訂單服務對庫存服務發起10次請求,那就先讓你請求第1台機器、然后是第2台機器、第3台機器、第4台機器、第5台機器,接着再來—個循環,第1台機器、第2台機器。。。以此類推

我們也可以通過配置文件更改它默認的負載均衡算法:

#這是將算法更改為了隨機
user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

3.Hystrix

首先我們來了解一下什么是雪崩問題

​ 服務器支持的線程和並發數有限,請求一直阻塞,會導致服務器資源耗盡,從而導致所有其它服務都不可用,形成雪崩效應。

解決這個問題,我們就需要來學習一下hystrix

3.1 線程隔離

Hystrix為每個依賴服務調用分配一個小的線程池,如果線程池已滿調用將被立即拒絕,

解釋一下,假如現在有兩個服務:user-serviceorder-service,現在hystrix會為這兩個服務分配兩個小的線程池,如果user-service宕機會導致它的線程池所有的線程都被卡着,但是並不會影響到order-service的線程池,這兩就不會出現雪崩問題了。

3.2 服務熔斷

在線程隔離中講到,如果user-service宕機會導致它的線程池所有的線程都被卡着,每次對user-service的訪問都會失敗,既然都會失敗,就不要再走網絡請求了,這就用到了Hystrix的服務熔斷機制

​ 假如5s中之內訪問一個服務20次都失敗了,那么這5s之內再去訪問這個服務就直接給熔斷了,也就是不再請求,直接判定失敗,5秒20次是Hystrix的默認值

​ 我們可以通知配置文件修改這些參數

circuitBreaker:
 requestVolumeThreshold: 10
 sleepWindowInMilliseconds: 10000
 errorThresholdPercentage: 50

解讀:

  • requestVolumeThreshold:觸發熔斷的最小請求次數,默認10
  • sleepWindowInMilliseconds:休眠時長,默認是10000毫秒
  • errorThresholdPercentage:觸發熔斷的失敗請求最小占比,默認50%

3.3 服務降級

熔斷之后直接判定失敗,直接返回時不太好的,總的做的什么操作吧,這就是降級服務,也就是失敗之后執行的一個方法,在這個方法中可以去記錄請求的信息,也可以返回一些友好的 提示

我們在consumer-demo中的試一下:

1.導入依賴

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

2.開啟熔斷

將啟動類上的注解換成@SpringCloudApplication

@SpringCloudApplication
public class ConsumerApplication {
    // ...
}

3.編寫降級邏輯

這里我們的降級邏輯,就返回一個提示好了

@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "queryByIdFallBack")
public String queryById(@PathVariable("id") Long id){
    @Autowired
    private UserClient userClient;

    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id){
        return userClient.queryById(id);
    }
}

public String queryByIdFallBack(Long id){
    log.error("查詢用戶信息失敗,id:{}", id);
    return "對不起,網絡太擁擠了!";
}

要注意,因為熔斷的降級邏輯方法必須跟正常邏輯方法保證:相同的參數列表和返回值聲明

這樣,這個服務降級功能就完成了


免責聲明!

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



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