Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔斷的示例
Feign的使用
Feign也是網飛開發的,SpringCloud 使用 Feign 非常簡單,我下邊演示一下:
首先 服務消費者這邊肯定需要一個對應的依賴:
compile("org.springframework.cloud:spring-cloud-starter-openfeign")
需要啟用Feign的話,也得在啟動類上面加個註解 @EnableFeignClients
然後,創建一個 Feign 的接口,像這樣子
package com.skypyb.sc.feign; import com.skypyb.sc.entity.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient("sc-demo-microservice-user") public interface UserFeignClient { @RequestMapping(value = "/user/{id}",method = RequestMethod.GET) public User getUser(@PathVariable("id") Long id); }
@FeignClient 註解裡邊的默認屬性,也就是name屬性是一個客戶端的名字,如果使用瞭Eureka的話,會給他自動解析為 Eureka Server 服務註冊表中的服務。
要是配瞭Ribbon,也會使用默認的負載均衡策略來執行請求。
Feign默認使用SpringMVC的註解聲明請求,當然也可以用Feign自帶的註解。不過沒啥必要,還需要配置東西。
我上邊這個例子寫完瞭,實際使用的話隻需要註入該類然後調用對應的方法就完事瞭。非常簡便。
package com.skypyb.sc.controller; import com.skypyb.sc.entity.User; import com.skypyb.sc.feign.UserFeignClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping("/movie") public class MovieController { private Logger logger = LoggerFactory.getLogger(MovieController.class); @Autowired private UserFeignClient userFeignClient; @GetMapping("/user/{id}") public User getUser(@PathVariable("id") Long id) { return userFeignClient.getUser(id); } }
不過有幾個點需要註意
在使用@FeignClient 聲明的Feign偽裝類中:
使用 @PathVariable 註解,必須加上參數!
GET請求無法使用對象作為入參! 要不有多少參數寫多少參數(每個都要加@RequestParam(“參數名”) 註解),要不就用接受一個Map對象,也得加@RequestParam
POST請求可以接收對象,需要加上@RequestBody註解
Feign論使用的話,其實已經差不多瞭。
但是還有一些相關的操作也比較重要。
Feign 的請求都是使用的默認配置,我們其實可以實現自己的配置供 Feign 使用以實現編碼、解碼、日志記錄、驗證 等等等等。
比如我可以這麼定義一個配置類:
package com.skypyb.sc.config; import feign.Logger; import feign.auth.BasicAuthRequestInterceptor; import org.springframework.context.annotation.Bean; public class FeignConfiguration { @Bean public Logger.Level feignLog() { return Logger.Level.FULL; } /** * 使用指定的用戶名和密碼驗證所有請求 * @return */ @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){ return new BasicAuthRequestInterceptor("user","614"); } }
該類配置瞭對應的日志記錄器,和一個簡單的效驗,以應對請求的驗證。
在對應的Feign偽裝類中,上邊的@FeignClient註解改一下,就可以使用自己寫的配置:
@FeignClient(name = "sc-demo-microservice-user", configuration = FeignConfiguration.class)
之所以在 @FeignClient 註解中指定配置,是因為我的配置類是沒有加 @Configuration 註解的,我想要實現細粒度的控制。 推薦這樣做。
如果加瞭@Configuration 註解,則 Spring 會將其自動解析自動應用到全局,這樣子就不方便為每個請求進行細粒度調整。
Alibaba的使用
首先肯定是要上pom.xml配置起來。加上對應的依賴。
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
接著寫個Feign接口
package com.skypyb.provider.feign; import com.skypyb.provider.fallback.HelloServiceFallback; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; /** * Feign客戶端 * 指定調用 sc-demo-alibaba-provider 的服務 */ @FeignClient(value = "sc-demo-alibaba-provider",fallback = HelloServiceFallback.class) public interface NacosHelloFeign { @RequestMapping(value = "/provider/hello/{msg}") String hello(@PathVariable("msg") String msg); }
調用的話就是這樣子調用:
package com.skypyb.provider.controller; import com.skypyb.provider.feign.NacosHelloFeign; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; @RequestMapping("/consumer") @RestController public class NacosConsumerController { @Autowired private LoadBalancerClient loadBalancerClient; @Autowired private RestTemplate restTemplate; @Resource private NacosHelloFeign nacosHelloFeign; @GetMapping(value = "/hello/{msg}") public String hello(@PathVariable("msg") String msg) { //使用 LoadBalanceClient 和 RestTemplate 結合的方式來訪問 ServiceInstance serviceInstance = loadBalancerClient.choose("sc-demo-alibaba-provider"); String url = String.format("http://%s:%s/provider/hello/%s", serviceInstance.getHost(), serviceInstance.getPort(), msg); return restTemplate.getForObject(url, String.class); } @GetMapping(value = "/hello/feign/{msg}") public String helloFeign(@PathVariable("msg") String msg) { return nacosHelloFeign.hello(msg); } }
哎,觀察我的NacosHelloFeign類,這裡可以看到,我這用瞭一個fallback回退,這個回退指定的就是Sentinel 的實現,其實寫起來和特麼的Hystrix一模一樣。不得不說SpringCloud這一點是真的做得好。
package com.skypyb.provider.fallback; import com.skypyb.provider.feign.NacosHelloFeign; import org.springframework.stereotype.Component; /** * 熔斷類 * 要是 Feign 的接口調用失敗(或者被快速失敗)就會走這個類的方法進行處理 */ @Component public class HelloServiceFallback implements NacosHelloFeign { @Override public String hello(String msg) { return "觸發熔斷機制~"; } }
哎,觀察我的NacosHelloFeign類,這裡可以看到,我這用瞭一個fallback回退,這個回退指定的就是Sentinel 的實現,其實寫起來和特麼的Hystrix一模一樣。不得不說SpringCloud這一點是真的做得好。
package com.skypyb.provider.fallback; import com.skypyb.provider.feign.NacosHelloFeign; import org.springframework.stereotype.Component; /** * 熔斷類 * 要是 Feign 的接口調用失敗(或者被快速失敗)就會走這個類的方法進行處理 */ @Component public class HelloServiceFallback implements NacosHelloFeign { @Override public String hello(String msg) { return "觸發熔斷機制~"; } }
當然,配置肯定是得配置的,他也不會直接就給你用瞭。
Sentinel 雖說是適配瞭 Feign 組件。但默認是關閉的。需要在配置文件中配置打開它,在配置文件增加以下代碼:
feign: sentinel: enabled: true
其實到現在,整個Feign的使用+熔斷限流機制就已經配完瞭。
不過Sentinel 比起Hystrix真正優越的地方還沒來呢。
那就是: 控制臺。
這個控制臺功能豐富、UI好看,比Hystrix那是高到不知道哪裡去瞭。
要是用控制臺,又不得不下載代碼、打包、編譯、運行。
所幸,我們有神器docker。我在docker hub 上找瞭個鏡像,直接用就可以瞭,鏡像地址:https://hub.docker.com/r/bladex/sentinel-dashboard
直接執以下命令,將sentinel控制臺起開綁到8858端口
docker pull bladex/sentinel-dashboard docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard
然後自己的yml文件也得改一下,畢竟都上控制臺瞭,也得把自己這個服務給註冊進去。
全部的yml文件如下所示:
spring: application: name: sc-demo-alibaba-consumer cloud: nacos: discovery: server-addr: 192.168.1.14:8848 #註冊進 nacos sentinel: transport: port: 18081 #這個端口的意思是自己這個服務開個端口和 sentinel 控制臺交互 dashboard: 192.168.1.14:8858 # sentinel 控制臺的端口 server: port: 8081 feign: sentinel: enabled: true management: endpoints: web: exposure: include: "*"
可以看到配置裡有一個 sentinel.transport.port屬性,這個屬性的意思是在自己本體這個服務裡邊,在開個新的端口專門用來和 Sentinel 控制臺交互
Sentinel 控制臺自身也有,默認端口則是8719
到這裡就差不多瞭,所有東西打開,然後就可以訪問 http://ip:8858 進入Sentinel 控制臺,默認賬號密碼都是sentinel
有一點還需要註意,那就是為瞭確保客戶端有訪問量,Sentinel 會在客戶端首次調用的時候進行初始化,開始向控制臺發送心跳包。意思就是說你一個服務註冊進我這來,首先還是看不到的。
你得先經過別人的請求,我才會去監控你,所以在服務剛啟動的時候進入Sentinel 控制臺找不到自己的服務是很正常的,隻要啟動時沒有報錯就不會有問題。
以上就是Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔斷的示例的詳細內容,更多關於Spring Cloud Alibaba 使用Feign+Sentinel 完成熔斷的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Spring Cloud-Feign服務調用的問題及處理方法
- 一篇文章教你如何在SpringCloud項目中使用OpenFeign
- SpringBoot使用Feign調用其他服務接口
- Spring Cloud超詳細i講解Feign自定義配置與使用
- Sentinel 整合SpringCloud的詳細教程