前言
最近項目組拿了友商的springcloud alibaba項目來進行改造,在翻閱他們的代碼時候,發現他們把@FeignClient寫在服務提供方的API上,他們這樣的寫法成功的引起我的注意,於是抱着好學的心態請教友商的開發人員,於是一篇水文就這么誕生了
友商開發人員解惑
友商服務提供方的API形如下
@FeignClient(name = "feign-provider",path = UserService.INTER_NAME,contextId = "user")
public interface UserService {
String INTER_NAME = "user";
@GetMapping(value = "/{id}")
UserDTO getUserById(@PathVariable("id") Long id);
}
我過往的經歷是@FeignClient是寫在消費端上,就是在消費端上會寫一個接口繼承服務端API接口,再打上@FeignClient,並指明fallback,形如下
@FeignClient(name = "feign-provider",path = UserService.INTER_NAME,contextId = "user",fallback = UserServiceClientFallBack.class)
public interface UserServiceClient extends UserService {
}
我將我過往的寫法告訴友商開發人員,友商的開發人員對我說,你消費端還要自己寫接口啊,那么麻煩。我們這種寫法,消費端僅需pom文件引入API包,在調用方上打個 @Autowired標注,就可以調用服務提供方的接口。額,他們的說法真的很有道理,可惜沒說服我,於是我拋出第二個問題,你們直接把@FeignClient寫在服務提供方的API上,那如果消費端要進行熔斷降級,要怎么做?
友商給我答案是用sentinel啊,直接在sentinel的控制面板上配置熔斷降級策略,形如下
觸發的結果形如下
看着已經實現了熔斷的效果,但是我這種效果還不是我想要的,於是我又問,如果在面板上進行熔斷后,我要記錄熔斷日志,該怎么做?友商給我的答案是這時候你就得采用分布式鏈路追蹤組件啊比如skywalking,反正你記錄日志,不也是為了排查問題方便,要懂得變通。額,好吧,最后我再拋出一個問題,既然你們直接把@FeignClient寫在服務提供方的API上,那如果消費端想直連某台服務提供方進行本地聯調,那要怎么做?友商的回答是他們開發的時候不會有這種場景,大家都是直連開發環境聯調
如果是我來實現,我會把@FeignClient寫在哪里?
毋庸置疑的,我會把@FeignClient寫在消費端上,因為從職責上,只有消費端才能明確知道自己要調用哪個服務提供方,比如直連哪個服務提供方進行調試,如果直接把@FeignClient寫在服務提供方的API上,消費端就很難按需定制。其次因為自己對sentinel也停留在聽說過,也沒實際用過,也是因為這次友商的項目了用springcloud alibaba的全家桶,才接觸了下。后面在和友商討論@FeignClient的放置問題后,回來在嘗試了一把,發現友商說的在sentinel配置熔斷降級不全面,因為我后邊嘗試讓服務提供方超時或者報錯,此時訪問頁面就會出現
和
后邊我就按自己的想法,在消費端上會寫一個接口繼承服務端API接口,再打上@FeignClient,並指明fallback,形如下
@FeignClient(name = "feign-provider",path = UserService.INTER_NAME,contextId = "user",fallback = UserServiceClientFallBack.class)
public interface UserServiceClient extends UserService {
}
@Component
@Slf4j
public class UserServiceClientFallBack implements UserServiceClient{
@Override
public UserDTO getUserById(Long id) {
log.info("id:{} fallback",id);
return UserDTO.builder().id(id).userName("fallback").build();
}
}
在application.yml激活sentinel對feign的支持
feign:
sentinel:
enabled: true
此時讓服務提供方超時或者報錯,再訪問頁面
同時控制台打印出熔斷日志
總結
寫這篇文章的目的,並不是要反駁說@FeignClient寫在服務提供方API的就是錯的,個人是覺得脫離業務場景,來談技術就是在耍流氓,畢竟友商他們自己那么用,也沒出大問題,就說明他們當前的寫法是滿足他們業務需求。最后我來回答一下,springcloud中feign的@FeignClient應該寫在哪里,就我個人而言,我還是傾向寫在消費端上,而非服務提供方的API上