Feign-解決遠程調用問題

問題引入

在前面的學習中,我們使用了Ribbon的負載均衡功能,大大簡化了遠程調用時的代碼:

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

但是可能以後需要編寫類似的大量重複代碼,格式基本相同,無非參數不一樣而已,而且例如這裏的user-service服務名稱我們可以通過eureka獲取,但是user這個路徑怎麼知道呢?
Feign就能很好的解決這個遠程調用的問題。

Feign

  • 較爲官方的解釋:
    Feign是一個聲明性的Web服務客戶端。它使編寫Web服務客戶端變得更容易。feigin是一種模板化,聲明式的http客戶端,feign可以通過註解綁定到接口上來簡化Http請求訪問。與當我們訪問別的服務端口的時候 大部分使用httpclient等請求進行調用不同,在eureka註冊的服務,我們可以使用Feign 聲明接口的形式來進行相關服務的調用,並提供了失敗回退(其實是Hystrix組件的使用)。Feign只是一個便利的rest框架,簡化調用,最後還是通過ribbon在註冊服務器中找到服務實例,然後對請求進行分配。
  • 我的理解:
    Feign可以把例如上面這樣的遠程請求給隱藏起來,讓別人看不到,看起來好像是在訪問本地服務一樣,有一種僞裝功能。Feign替我們解決這件事的時候,我們也應該去告訴他 請求路徑、請求參數、請求方式、返回結果,仔細想想這四個東西springmvc的註解就可以搞定,我們的controller方法,有@RequestMapping(method屬性)、@PathVariable、return返回值。所以Feign就可以利用springmvc的註解識別這些信息,幫我們遠程調用,不用我們寫。

Feign的使用

引入依賴並啓動

<!--feign-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@EnableFeignClients
@SpringCloudApplication
public class ConsumerApplication {
    /*這個也不需要了,註釋掉
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }*/

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

編寫註解類

這個註解類,其實就是Feign的一個客戶端
@FeignClient("user-service"):這個註解時指定服務名,去eureka拉取服務列表,然後底層利用ribben進行負載均衡挑選任意一個服務。訪問@GetMapping(“user/findById/{id}”)路徑,參數爲id,返回一個User對象的json字符串,全部自動完成。

@FeignClient("user-service")
public interface UserClient {
    @GetMapping("user/findById/{id}")
    User findByid(@PathVariable("id")Integer id);
}

修改ConsumerController類

ConsumerController是服務調用端的一個controller類。

@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "findByIdFallback")
public class ConsumerController {
    @Autowired//注入UserClient 
    private UserClient userClient;

    @GetMapping("{id}")
    public User findById(@PathVariable("id")Integer id){
        return userClient.findByid(id);
    }
    //默認fallback方法,不需要再有參數了
    public String findByIdFallback(){
        return "不好意思!服務器正忙!!!!";
    }
}

userClient.findByid(id):這樣的調用,是不是像在調用本地的一個方法一樣,但是本質是進行了遠程調用,很優雅。

Feign與負載均衡與服務降級

思考:在上面的代碼中,我們只告訴了服務調用者服務名稱是user-service,並沒有告訴他ip地址,但是他卻能實現訪問服務並調用功能,說明他內部是有負載均衡處理的。
在這裏插入圖片描述
我們看看feign的包依賴,他內部是有ribbon的實現了負載均衡、hystrix實現了服務熔斷和降級的,而且此時我們如果引入了這個Feign,那麼這兩個依賴就不需要在去單獨引入依賴了。

feign與ribbon負載均衡

而且ribbon的負載均衡和以前使用方式是一樣的,Feign還內置了一個超時時長默認1秒鐘。我們可以在application.yml中進行配置。

ribbon:
  ConnectionTimeOut: 1000 # 建立連接的超時時長(1秒未建立就超時)
  ReadTimeOut: 1000 # 讀取數據超時時長(1秒未讀取就超時)

feign與hystrix熔斷

注意Hystrix在feign中默認是關閉的,我們應該在application.yml中進行開啓。

# 開啓feign的hystrix功能
feign:
  hystrix:
    enabled: true

需要注意的是,Feign底層在實現熔斷時,沒有走Springcloud提供的方式,之前我們的配置的值是可用的,但是寫法變了,我們需要自己去寫一個熔斷類。
這個類必須實現我們的UserClient接口,並且要注入到容器中。

@Component
public class UserClientFallBack implements UserClient {
    @Override
    public User findByid(Integer id) {
        User user=new User();
        user.setId(id);
        user.setUsername("用戶查詢異常!!");
        return user;
    }
}

UserClient類的@FeignClient(value = "user-service",fallback =UserClientFallBack.class )指定自定義熔斷類。

@FeignClient(value = "user-service",fallback =UserClientFallBack.class )
public interface UserClient {

    @GetMapping("user/findById/{id}")
    User findByid(@PathVariable("id")Integer id);
}

測試

啓動服務器,測試一下在這裏插入圖片描述
未關閉前,一切正常。可以查出數據。
在這裏插入圖片描述

關閉服務提供者UserApplication服務器,肯定會出現遠程連接異常,此時就會得到我們自定義的那個熔斷類對應方法返回的信息了。
在這裏插入圖片描述
在這裏插入圖片描述

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