https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
NodeSelectorSlot
中記錄了資源之間的調用鏈路,這些資源通過調用關系,相互之間構成一棵調用樹。這棵樹的根節點是一個名字為 machine-root
的虛擬節點,調用鏈的入口都是這個虛節點的子節點。
一棵典型的調用樹如下圖所示:
machine-root
/ \
/ \
Entrance1 Entrance2
/ \
/ \
DefaultNode(nodeA) DefaultNode(nodeA)
上圖中來自入口 Entrance1
和 Entrance2
的請求都調用到了資源 NodeA
,Sentinel 允許只根據某個入口的統計信息對資源限流。比如我們可以設置 strategy
為 RuleConstant.STRATEGY_CHAIN
,同時設置 refResource
為 Entrance1
來表示只有從入口 Entrance1
的調用才會記錄到 NodeA
的限流統計當中,而不關心經 Entrance2
到來的調用。
調用鏈的入口(上下文)是通過 API 方法 ContextUtil.enter(contextName)
定義的,其中 contextName 即對應調用鏈路入口名稱。詳情可以參考 ContextUtil 文檔。
web-context-unify: false #默認將調用鏈路收斂
application.yml
server: port: 8052 #應用名稱 (sentinel 會將該名稱當作服務名稱) spring: application: name: order-sentinel cloud: sentinel: transport: dashboard: 127.0.0.1:8858 web-context-unify: false #默認將調用鏈路收斂
package com.wsm.order.service; public interface OrderService { public String getUser(); }
package com.wsm.order.service.impl; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.wsm.order.service.OrderService; import org.springframework.stereotype.Service; @Service public class OrderServiceImpl implements OrderService { @Override @SentinelResource(value = "getUser",blockHandler = "blockHandlerGetUser") public String getUser() { return "查詢用戶"; } public String blockHandlerGetUser(BlockException e){ return "流控用戶"; } }
package com.wsm.order.controller; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.wsm.order.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/order") public class OrderController { @Autowired OrderService orderService; @RequestMapping("/add") public String add(){ System.out.println("下單成功!"); return "生成訂單"; } @RequestMapping("/get") public String get(){ System.out.println("查詢訂單!"); return "查詢訂單"; } @RequestMapping("/test1") public String test1(){ return orderService.getUser(); } @RequestMapping("/test2") public String test2(){ return orderService.getUser(); } @RequestMapping("/flow") // @SentinelResource(value = "flow",blockHandler = "flowBlockHandler") public String flow(){ System.out.println("========flow===="); return "正常訪問"; } public String flowBlockHandler(BlockException e){ return "流控了"; } @RequestMapping("/flowThread") // @SentinelResource(value = "flowThread",blockHandler = "flowThreadBlockHandler") public String flowThread() throws InterruptedException { TimeUnit.SECONDS.sleep(5); System.out.println("========flowThread===="); return "正常訪問"; } public String flowThreadBlockHandler(BlockException e){ return "flowThread流控了"; } }