Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔斷的示例
Feign的使用
Feign也是網(wǎng)飛開(kāi)發(fā)的,SpringCloud 使用 Feign 非常簡(jiǎn)單,我下邊演示一下:
首先 服務(wù)消費(fèi)者這邊肯定需要一個(gè)對(duì)應(yīng)的依賴:
compile("org.springframework.cloud:spring-cloud-starter-openfeign")
需要啟用Feign的話,也得在啟動(dòng)類上面加個(gè)注解 @EnableFeignClients
然后,創(chuàng)建一個(gè) 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 注解里邊的默認(rèn)屬性,也就是name屬性是一個(gè)客戶端的名字,如果使用了Eureka的話,會(huì)給他自動(dòng)解析為 Eureka Server 服務(wù)注冊(cè)表中的服務(wù)。
要是配了Ribbon,也會(huì)使用默認(rèn)的負(fù)載均衡策略來(lái)執(zhí)行請(qǐng)求。
Feign默認(rèn)使用SpringMVC的注解聲明請(qǐng)求,當(dāng)然也可以用Feign自帶的注解。不過(guò)沒(méi)啥必要,還需要配置東西。
我上邊這個(gè)例子寫(xiě)完了,實(shí)際使用的話只需要注入該類然后調(diào)用對(duì)應(yīng)的方法就完事了。非常簡(jiǎn)便。
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);
}
}
不過(guò)有幾個(gè)點(diǎn)需要注意
在使用@FeignClient 聲明的Feign偽裝類中:
使用 @PathVariable 注解,必須加上參數(shù)!
GET請(qǐng)求無(wú)法使用對(duì)象作為入?yún)ⅲ?要不有多少參數(shù)寫(xiě)多少參數(shù)(每個(gè)都要加@RequestParam(“參數(shù)名”) 注解),要不就用接受一個(gè)Map對(duì)象,也得加@RequestParam
POST請(qǐng)求可以接收對(duì)象,需要加上@RequestBody注解
Feign論使用的話,其實(shí)已經(jīng)差不多了。
但是還有一些相關(guān)的操作也比較重要。
Feign 的請(qǐng)求都是使用的默認(rèn)配置,我們其實(shí)可以實(shí)現(xiàn)自己的配置供 Feign 使用以實(shí)現(xiàn)編碼、解碼、日志記錄、驗(yàn)證 等等等等。
比如我可以這么定義一個(gè)配置類:
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;
}
/**
* 使用指定的用戶名和密碼驗(yàn)證所有請(qǐng)求
* @return
*/
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new BasicAuthRequestInterceptor("user","614");
}
}
該類配置了對(duì)應(yīng)的日志記錄器,和一個(gè)簡(jiǎn)單的效驗(yàn),以應(yīng)對(duì)請(qǐng)求的驗(yàn)證。
在對(duì)應(yīng)的Feign偽裝類中,上邊的@FeignClient注解改一下,就可以使用自己寫(xiě)的配置:
@FeignClient(name = "sc-demo-microservice-user", configuration = FeignConfiguration.class)
之所以在 @FeignClient 注解中指定配置,是因?yàn)槲业呐渲妙愂菦](méi)有加 @Configuration 注解的,我想要實(shí)現(xiàn)細(xì)粒度的控制。 推薦這樣做。
如果加了@Configuration 注解,則 Spring 會(huì)將其自動(dòng)解析自動(dòng)應(yīng)用到全局,這樣子就不方便為每個(gè)請(qǐng)求進(jìn)行細(xì)粒度調(diào)整。
Alibaba的使用
首先肯定是要上pom.xml配置起來(lái)。加上對(duì)應(yīng)的依賴。
<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>
接著寫(xiě)個(gè)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客戶端
* 指定調(diào)用 sc-demo-alibaba-provider 的服務(wù)
*/
@FeignClient(value = "sc-demo-alibaba-provider",fallback = HelloServiceFallback.class)
public interface NacosHelloFeign {
@RequestMapping(value = "/provider/hello/{msg}")
String hello(@PathVariable("msg") String msg);
}
調(diào)用的話就是這樣子調(diào)用:
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 結(jié)合的方式來(lái)訪問(wèn)
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類,這里可以看到,我這用了一個(gè)fallback回退,這個(gè)回退指定的就是Sentinel 的實(shí)現(xiàn),其實(shí)寫(xiě)起來(lái)和特么的Hystrix一模一樣。不得不說(shuō)SpringCloud這一點(diǎn)是真的做得好。
package com.skypyb.provider.fallback;
import com.skypyb.provider.feign.NacosHelloFeign;
import org.springframework.stereotype.Component;
/**
* 熔斷類
* 要是 Feign 的接口調(diào)用失敗(或者被快速失敗)就會(huì)走這個(gè)類的方法進(jìn)行處理
*/
@Component
public class HelloServiceFallback implements NacosHelloFeign {
@Override
public String hello(String msg) {
return "觸發(fā)熔斷機(jī)制~";
}
}
哎,觀察我的NacosHelloFeign類,這里可以看到,我這用了一個(gè)fallback回退,這個(gè)回退指定的就是Sentinel 的實(shí)現(xiàn),其實(shí)寫(xiě)起來(lái)和特么的Hystrix一模一樣。不得不說(shuō)SpringCloud這一點(diǎn)是真的做得好。
package com.skypyb.provider.fallback;
import com.skypyb.provider.feign.NacosHelloFeign;
import org.springframework.stereotype.Component;
/**
* 熔斷類
* 要是 Feign 的接口調(diào)用失敗(或者被快速失敗)就會(huì)走這個(gè)類的方法進(jìn)行處理
*/
@Component
public class HelloServiceFallback implements NacosHelloFeign {
@Override
public String hello(String msg) {
return "觸發(fā)熔斷機(jī)制~";
}
}
當(dāng)然,配置肯定是得配置的,他也不會(huì)直接就給你用了。
Sentinel 雖說(shuō)是適配了 Feign 組件。但默認(rèn)是關(guān)閉的。需要在配置文件中配置打開(kāi)它,在配置文件增加以下代碼:
feign: sentinel: enabled: true
其實(shí)到現(xiàn)在,整個(gè)Feign的使用+熔斷限流機(jī)制就已經(jīng)配完了。
不過(guò)Sentinel 比起Hystrix真正優(yōu)越的地方還沒(méi)來(lái)呢。
那就是: 控制臺(tái)。
這個(gè)控制臺(tái)功能豐富、UI好看,比Hystrix那是高到不知道哪里去了。
要是用控制臺(tái),又不得不下載代碼、打包、編譯、運(yùn)行。
所幸,我們有神器docker。我在docker hub 上找了個(gè)鏡像,直接用就可以了,鏡像地址:https://hub.docker.com/r/bladex/sentinel-dashboard
直接執(zhí)以下命令,將sentinel控制臺(tái)起開(kāi)綁到8858端口
docker pull bladex/sentinel-dashboard docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard
然后自己的yml文件也得改一下,畢竟都上控制臺(tái)了,也得把自己這個(gè)服務(wù)給注冊(cè)進(jìn)去。
全部的yml文件如下所示:
spring: application: name: sc-demo-alibaba-consumer cloud: nacos: discovery: server-addr: 192.168.1.14:8848 #注冊(cè)進(jìn) nacos sentinel: transport: port: 18081 #這個(gè)端口的意思是自己這個(gè)服務(wù)開(kāi)個(gè)端口和 sentinel 控制臺(tái)交互 dashboard: 192.168.1.14:8858 # sentinel 控制臺(tái)的端口 server: port: 8081 feign: sentinel: enabled: true management: endpoints: web: exposure: include: "*"
可以看到配置里有一個(gè) sentinel.transport.port屬性,這個(gè)屬性的意思是在自己本體這個(gè)服務(wù)里邊,在開(kāi)個(gè)新的端口專門(mén)用來(lái)和 Sentinel 控制臺(tái)交互
Sentinel 控制臺(tái)自身也有,默認(rèn)端口則是8719
到這里就差不多了,所有東西打開(kāi),然后就可以訪問(wèn) http://ip:8858 進(jìn)入Sentinel 控制臺(tái),默認(rèn)賬號(hào)密碼都是sentinel
有一點(diǎn)還需要注意,那就是為了確??蛻舳擞性L問(wèn)量,Sentinel 會(huì)在客戶端首次調(diào)用的時(shí)候進(jìn)行初始化,開(kāi)始向控制臺(tái)發(fā)送心跳包。意思就是說(shuō)你一個(gè)服務(wù)注冊(cè)進(jìn)我這來(lái),首先還是看不到的。
你得先經(jīng)過(guò)別人的請(qǐng)求,我才會(huì)去監(jiān)控你,所以在服務(wù)剛啟動(dòng)的時(shí)候進(jìn)入Sentinel 控制臺(tái)找不到自己的服務(wù)是很正常的,只要啟動(dòng)時(shí)沒(méi)有報(bào)錯(cuò)就不會(huì)有問(wèn)題。
以上就是Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔斷的示例的詳細(xì)內(nèi)容,更多關(guān)于Spring Cloud Alibaba 使用Feign+Sentinel 完成熔斷的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot全局異常處理機(jī)制和配置攔截器方式
這篇文章主要介紹了SpringBoot全局異常處理機(jī)制和配置攔截器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
springboot如何通過(guò)不同的策略動(dòng)態(tài)調(diào)用不同的實(shí)現(xiàn)類
這篇文章主要介紹了springboot如何通過(guò)不同的策略動(dòng)態(tài)調(diào)用不同的實(shí)現(xiàn)類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
如何對(duì)?Excel?表格中提取的數(shù)據(jù)進(jìn)行批量更新
這篇文章主要介紹了如何對(duì)Excel表格中提取的數(shù)據(jù)進(jìn)行批量更新操作,本文通過(guò)示例代碼介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-06-06
將RestTemplate的編碼格式改為UTF-8,防止亂碼問(wèn)題
這篇文章主要介紹了將RestTemplate的編碼格式改為UTF-8,防止亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
通過(guò)實(shí)例解析傳統(tǒng)jar包引用方式
這篇文章主要介紹了通過(guò)實(shí)例解析傳統(tǒng)jar包引用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Java Springboot之Spring家族的技術(shù)體系
今天帶大家來(lái)學(xué)習(xí)Spring家族的技術(shù)體系,文中有非常詳細(xì)的圖文介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05
Springboot整合MongoDB進(jìn)行CRUD操作的兩種方式(實(shí)例代碼詳解)
這篇文章主要介紹了Springboot整合MongoDB進(jìn)行CRUD操作的兩種方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

