日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
服務容錯:項目整合Sentinel實現限流與容錯

章節(jié)概述

今天,我們就使用Sentinel實現接口的限流,并使用Feign整合Sentinel實現服務容錯的功能,讓小伙伴們體驗下微服務使用了服務容錯功能的效果。因為我們整個專欄的內容僅僅圍繞著SpringCloud Alibaba技術棧展開,所以,這里我們使用的服務容錯組件是阿里開源的Sentinel。

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名注冊、網絡空間、營銷軟件、網站建設、鄂溫克網站維護、網站推廣。

當然,能夠實現服務容錯功能的組件不僅僅有Sentinel,比如:Hystrix和Resilience4J也能夠實現服務容錯的目的,關于Hystrix和Resilience4J不是本專欄的重點,冰河就不再贅述了,小伙伴們可以自行了解。

關于Sentinel

隨著微服務的流行,服務和服務之間的穩(wěn)定性變得越來越重要。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩(wěn)定性。

Sentinel的特征

  • 豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發(fā)流量控制在系統容量可以承受的范圍)、消息削峰填谷、集群流量控制、實時熔斷下游不可用應用等。
  • 完備的實時監(jiān)控:Sentinel 同時提供實時的監(jiān)控功能。您可以在控制臺中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規(guī)模的集群的匯總運行情況。
  • 廣泛的開源生態(tài):Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。同時 Sentinel 提供 Java/Go/C++ 等多語言的原生實現。
  • 完善的 SPI 擴展機制:Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定制邏輯。例如定制規(guī)則管理、適配動態(tài)數據源等。

Sentinel的主要特性

Sentinel的開源生態(tài)

Sentinel 分為兩個部分:

  • 核心庫(Java 客戶端)不依賴任何框架/庫,能夠運行于所有 Java 運行時環(huán)境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持。
  • 控制臺(Dashboard)基于 Spring Boot 開發(fā),打包后可以直接運行,不需要額外的 Tomcat 等應用容器

注意:上述內容來自Sentinel官方文檔,鏈接地址為:

https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

項目整合Sentinel

在微服務項目中整合Sentinel是非常簡單的,只需要在項目的pom.xml文件中引入Sentinel的依賴即可,不過在使用Sentinel時,需要安裝Sentinel的控制臺。

安裝Sentinel控制臺

Sentinel 提供一個輕量級的控制臺, 它提供機器發(fā)現、單機資源實時監(jiān)控以及規(guī)則管理等功能。

(1)到鏈接

https://github.com/alibaba/Sentinel/releases

下載Sentinel控制臺,如下所示,我這里下載的Sentinel控制臺是1.8.4版本。

(2)Sentinel控制臺下載完成后,在本地啟動Sentinel控制臺,如下所示。

java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 
-Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.4.jar

小伙伴們如果想在CentOS服務器上以后臺進程方式啟動Sentinel控制臺,可以使用如下命令

nohup java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.4.jar >> /dev/null &

啟動后在瀏覽器中輸入 http://localhost:8888 訪問Sentinel控制臺,如下所示。

輸入默認的用戶名sentinel和密碼sentinel,登錄Sentinel控制臺,如下所示。

至此,Sentinel控制臺下載并啟動成功。

項目集成Sentinel

(1)在訂單微服務的shop-order的pom.xml文件中添加Sentinel的相關依賴,如下所示。


com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel

(2)在訂單微服務的shop-order的application.yml文中加入Sentinel相關的配置,如下所示。

spring:
cloud:
sentinel:
transport:
port: 9999 #指定和Sentinel控制臺交互的端口,任意指定一個未使用的端口即可
dashboard: 127.0.0.1:8888 #Sentinel控制臺服務地址

(3)為了讓大家直觀的感受到Sentinel的功能,這里我們先在訂單微服務的io.binghe.shop.order.controller.OrderController類中新增一個測試接口,如下所示。

@GetMapping(value = "/test_sentinel")
public String testSentinel(){
log.info("測試Sentinel");
return "sentinel";
}

(4)啟動訂單微服務,在瀏覽器中輸入http://localhost:8080/order/test_sentinel訪問在訂單微服務中新增的接口,如下所示。

(5)刷新Sentinel頁面,會發(fā)現已經顯示了訂單微服務的菜單,如下所示。

注意:直接啟動訂單微服務和Sentinel,會發(fā)現Sentinel中沒有訂單微服務的數據,因為Sentinel是懶加載機制,所以需要訪問一下接口,再去訪問Sentinel 就有數據了。

至此,訂單微服務成功集成了Sentinel。

集成Sentinel限流功能

這里,我們使用Sentinel為http://localhost:8080/order/test_sentinel接口限流,步驟如下所示。

(1)在Sentinel控制臺找到server-order下的簇點鏈路菜單,如下所示。

(2)在簇點鏈路列表中找到/test_sentinel,在右側的操作中選擇流控,如下所示。

點擊流控按鈕會顯示 新增流控規(guī)則 的彈出框,如下所示。

這里,我們在單機閾值后直接填寫1,如下所示。

配置好之后點擊新增按鈕。上述配置表示http://localhost:8080/order/test_sentinel接口的QPS為1,每秒訪問1次。如果每秒訪問的次數超過1次,則會被Sentinel限流。

(3)在瀏覽器上不斷刷新http://localhost:8080/order/test_sentinel接口,當每秒中訪問的次數超過1次時,會被Sentinel限流,如下所示。

對提交訂單的接口限流

在提交訂單的接口 http://localhost:8080/order/submit_order上實現限流,步驟如下。

(1)首先訪問下提交訂單的接口 http://localhost:8080/order/submit_order,使得Sentinel中能夠捕獲到提交訂單的接口,并點擊操作中的流控按鈕,如下所示。

這里的注意點還是:直接啟動訂單微服務和Sentinel,會發(fā)現Sentinel中沒有訂單微服務的數據,因為Sentinel是懶加載機制,所以需要訪問一下接口,再去訪問Sentinel 就有數據了。

(2)在新增流控規(guī)則顯示框中的QPS單機閾值設置為1,點擊新增按鈕,如下所示。

(3)在瀏覽器中不斷刷新 http://localhost:8080/order/submit_order?userId=1001&productId=1001&count=1 使得每秒訪問的頻率超過1次,會被Sentinel限流,如下所示。

至此,項目中集成了Sentinel并使用Sentinel實現了接口的限流。

Feign整合Sentinel實現容錯

我們之前在項目中集成了Sentinel,并使用Sentinel實現了限流,如果訂單微服務的下游服務,比如用戶微服務和商品微服務出現故障,無法訪問時,那訂單微服務該如何實現服務容錯呢?使用Sentinel就可以輕松實現。

添加依賴并開啟支持

(1)在訂單微服務的shop-order的pom.xml文件中添加Sentinel的相關依賴,如下所示。


com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel

注意:這一步是為了整個案例的完整性加上的,如果小伙伴們按照文章實現了項目整合Sentinel,并在訂單微服務的shop-order的pom.xml文件中添加了上述配置,則可忽略此步驟。

(2)在訂單微服務的application.yml文件中添加如下配置開啟Feign對Sentinel的支持。

feign:
sentinel:
enabled: true

為遠程調用實現容錯

(1)需要在訂單微服務shop-order中,為遠程調用接口實現容錯方法。這里,先為用戶微服務實現容錯。在訂單微服務中新建io.binghe.shop.order.Feign.fallback 包,并在 io.binghe.shop.order.Feign.fallback包下創(chuàng)建UserServiceFallBack類實現UserService接口,用于調用用戶微服務的容錯類,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 用戶服務容錯類
*/
@Component
public class UserServiceFallBack implements UserService {
@Override
public User getUser(Long uid) {
User user = new User();
user.setId(-1L);
return user;
}
}

注意:容錯類需要實現一個被容錯的接口,并實現這個接口的方法。

接下來,在訂單微服務的io.binghe.shop.order.Feign.UserService接口上的@FeignClient注解上指定容錯類,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 調用用戶微服務的接口
*/
@FeignClient(value = "server-user", fallback = UserServiceFallBack.class)
public interface UserService {

@GetMapping(value = "/user/get/{uid}")
User getUser(@PathVariable("uid") Long uid);
}

(2)在訂單微服務中的 io.binghe.shop.order.Feign.fallback包下創(chuàng)建ProductServiceFallBack類實現ProductService接口,用于調用商品微服務的容錯類,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 商品微服務的容錯類
*/
@Component
public class ProductServiceFallBack implements ProductService {
@Override
public Product getProduct(Long pid) {
Product product = new Product();
product.setId(-1L);
return product;
}

@Override
public Result updateCount(Long pid, Integer count) {
Result result = new Result<>();
result.setCode(1001);
result.setCodeMsg("觸發(fā)了容錯邏輯");
return result;
}
}

接下來,在訂單微服務的io.binghe.shop.order.fegin.ProductService接口的@FeignClient注解上指定容錯類,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 調用商品微服務的接口
*/
@FeignClient(value = "server-product", fallback = ProductServiceFallBack.class)
public interface ProductService {

/**
* 獲取商品信息
*/
@GetMapping(value = "/product/get/{pid}")
Product getProduct(@PathVariable("pid") Long pid);

/**
* 更新庫存數量
*/
@GetMapping(value = "/product/update_count/{pid}/{count}")
Result updateCount(@PathVariable("pid") Long pid, @PathVariable("count") Integer count);
}

(3)修改訂單微服務的業(yè)務實現類中提交訂單的業(yè)務方法,這里修改的方法位于io.binghe.shop.order.service.impl.OrderServiceV6Impl類中,同時需要將類上的@Service注解中指定bean的名稱為orderServiceV6。

@Slf4j
@Service("orderServiceV6")
public class OrderServiceV6Impl implements OrderService {
//省略所有代碼
}

在提交訂單的業(yè)務方法中,修改前的代碼片段如下所示。

User user = userService.getUser(orderParams.getUserId());
if (user == null){
throw new RuntimeException("未獲取到用戶信息: " + JSONObject.toJSONString(orderParams));
}
Product product = productService.getProduct(orderParams.getProductId());
if (product == null){
throw new RuntimeException("未獲取到商品信息: " + JSONObject.toJSONString(orderParams));
}
//#####################省略N行代碼##########################
Result result = productService.updateCount(orderParams.getProductId(), orderParams.getCount());
if (result.getCode() != HttpCode.SUCCESS){
throw new RuntimeException("庫存扣減失敗");
}

修改后的代碼片段如下所示。

User user = userService.getUser(orderParams.getUserId());
if (user == null){
throw new RuntimeException("未獲取到用戶信息: " + JSONObject.toJSONString(orderParams));
}
if (user.getId() == -1){
throw new RuntimeException("觸發(fā)了用戶微服務的容錯邏輯: " + JSONObject.toJSONString(orderParams));
}
Product product = productService.getProduct(orderParams.getProductId());
if (product == null){
throw new RuntimeException("未獲取到商品信息: " + JSONObject.toJSONString(orderParams));
}
if (product.getId() == -1){
throw new RuntimeException("觸發(fā)了商品微服務的容錯邏輯: " + JSONObject.toJSONString(orderParams));
}
//#####################省略N行代碼##########################
Result result = productService.updateCount(orderParams.getProductId(), orderParams.getCount());
if (result.getCode() == 1001){
throw new RuntimeException("觸發(fā)了商品微服務的容錯邏輯: " + JSONObject.toJSONString(orderParams));
}
if (result.getCode() != HttpCode.SUCCESS){
throw new RuntimeException("庫存扣減失敗");
}

可以看到,修改后的提交訂單的業(yè)務方法主要增加了服務容錯的判斷邏輯。

(4)在io.binghe.shop.order.controller.OrderController中注入bean名稱為orderServiceV6的OrderService對象,如下所示。

@Autowired
@Qualifier(value = "orderServiceV6")
private OrderService orderService;

至此,我們在項目中使用Sentinel實現了服務容錯的功能。

測試服務容錯

(1)停掉所有的商品微服務(也就是只啟動用戶微服務和訂單微服務),在瀏覽器中訪問http://localhost:8080/order/submit_order?userId=1001&productId=1001&count=1,結果如下所示。

返回的原始數據如下所示。

{"code":500,"codeMsg":"執(zhí)行失敗","data":"觸發(fā)了商品微服務的容錯邏輯: {\"count\":1,\"empty\":false,\"productId\":1001,\"userId\":1001}"}

說明停掉所有的商品微服務后,觸發(fā)了商品微服務的容錯邏輯。

(2)停掉所有的用戶微服務(也就是只啟動商品微服務和訂單微服務)在瀏覽器中訪問http://localhost:8080/order/submit_order?userId=1001&productId=1001&count=1,結果如下所示。

返回的原始數據如下所示。

{"code":500,"codeMsg":"執(zhí)行失敗","data":"觸發(fā)了用戶微服務的容錯邏輯: {\"count\":1,\"empty\":false,\"productId\":1001,\"userId\":1001}"}

(3)停掉所有的用戶微服務和商品微服務(也就是只啟動訂單微服務),在瀏覽器中訪問http://localhost:8080/order/submit_order?userId=1001&productId=1001&count=1,結果如下所示。

返回的原始數據如下所示。

{"code":500,"codeMsg":"執(zhí)行失敗","data":"觸發(fā)了用戶微服務的容錯邏輯: {\"count\":1,\"empty\":false,\"productId\":1001,\"userId\":1001}"}

說明項目集成Sentinel成功實現了服務的容錯功能。

容錯擴展

如果想要在訂單微服務中獲取到容錯時的具體信息時,可以按照如下方式實現容錯方案。

實現容錯時獲取異常

(1)在訂單微服務shop-order中新建io.binghe.shop.order.fegin.fallback.factory包,在io.binghe.shop.order.fegin.fallback.factory包中新建UserServiceFallBackFactory類,并實現FallbackFactory接口,FallbackFactory接口的泛型指定為UserService,源碼如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 用戶微服務容錯Factory
*/
@Component
public class UserServiceFallBackFactory implements FallbackFactory {
@Override
public UserService create(Throwable cause) {
return new UserService() {
@Override
public User getUser(Long uid) {
User user = new User();
user.setId(-1L);
return user;
}
};
}
}

(2)在訂單微服務的 io.binghe.shop.order.fegin.UserService 接口上的@FeignClient注解上指定fallbackFactory屬性,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 調用用戶微服務的接口
*/
//@FeignClient(value = "server-user", fallback = UserServiceFallBack.class)
@FeignClient(value = "server-user", fallbackFactory = UserServiceFallBackFactory.class)
public interface UserService {
@GetMapping(value = "/user/get/{uid}")
User getUser(@PathVariable("uid") Long uid);
}

(3)在io.binghe.shop.order.fegin.fallback.factory包中新建ProductServiceFallBackFactory類,并實現FallbackFactory接口,FallbackFactory接口的泛型指定為ProductService,源碼如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 商品微服務容錯Factory
*/
@Component
public class ProductServiceFallBackFactory implements FallbackFactory {
@Override
public ProductService create(Throwable cause) {
return new ProductService() {
@Override
public Product getProduct(Long pid) {
Product product = new Product();
product.setId(-1L);
return product;
}

@Override
public Result updateCount(Long pid, Integer count) {
Result result = new Result<>();
result.setCode(1001);
result.setCodeMsg("觸發(fā)了容錯邏輯");
return result;
}
};
}
}

(4)在訂單微服務的 io.binghe.shop.order.fegin.ProductService 接口上的@FeignClient注解上指定fallbackFactory屬性,如下所示。

/**
* @author binghe (公眾號:冰河技術)
* @version 1.0.0
* @description 調用商品微服務的接口
*/
//@FeignClient(value = "server-product", fallback = ProductServiceFallBack.class)
@FeignClient(value = "server-product", fallbackFactory = ProductServiceFallBackFactory.class)
public interface ProductService {

/**
* 獲取商品信息
*/
@GetMapping(value = "/product/get/{pid}")
Product getProduct(@PathVariable("pid") Long pid);

/**
* 更新庫存數量
*/
@GetMapping(value = "/product/update_count/{pid}/{count}")
Result updateCount(@PathVariable("pid") Long pid, @PathVariable("count") Integer count);
}

測試服務容錯

與“Feign整合Sentinel實現容錯-測試服務容錯”中的測試方法相同,這里不再贅述。

至此,使用Sentinel實現限流和容錯的功能就完成了。

最后,需要注意的是:使用Sentinel實現服務容錯時,fallback和fallbackFactory只能使用其中一種方式實現服務容錯,二者不能同時使用。


網頁標題:服務容錯:項目整合Sentinel實現限流與容錯
文章起源:http://m.5511xx.com/article/dpggjip.html