Spring Cloud 純乾貨,從入門到實戰
阿新 • • 發佈:2020-11-10
導讀
之前寫過一篇SpringCloud從入門到精通的點我直達,微服務基礎知識點我直達,今天我們使用Spring Cloud模擬一個電商專案。分別有以下2個服務,商品、訂單。下面我們開始叭
技術棧
- SpringBoot整合SpringCloud
- 通訊方式:http restful
- 註冊中心:eruka
- 斷路器:hystrix
- 閘道器:zuul
商品服務
功能點
- 商品列表
- 商品詳情
訂單服務
功能點
- 我的訂單
- 下單介面
搭建Eureka Server
建立專案
專案結構
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>eureka_server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka_server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
啟動類上加註解
application.properties
# 服務埠號 server.port=8761 # eureka主機名 eureka.instance.hostname=localhost # 指定當前主機是否需要向註冊中心註冊(不用,因為當前主機是Server,不是Client) eureka.client.register-with-eureka=false # 指定當前主機是否需要獲取註冊資訊(不用,因為當前主機是Server,不是Client) eureka.client.fetch-registry=false # 註冊中心地址 eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
啟動服務並檢視監控臺
搭建Eureka Client商品服務
建立專案
專案結構
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>product_service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>product_service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
# 服務埠號 server.port=8771 # 服務名稱 spring.application.name=product_service # 將服務註冊到註冊中心,eureka_service的地址 eureka.client.service-url.defaultZone:http://localhost:8761/eureka/
ProductController.java
package com.ybchen.product_service.controller; import com.ybchen.product_service.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @ClassName:ProductController * @Description:商品 * @Author:chenyb * @Date:2020/11/1 8:42 下午 * @Versiion:1.0 */ @RestController @RequestMapping("/api/v1/product") public class ProductController { @Autowired private ProductService productService; /** * 商品列表 * * @return */ @PostMapping("list") public Object list() { return productService.listProduct(); } /** * 根據id查詢商品 * * @param id * @return */ @GetMapping("findById") public Object findById(@RequestParam("id") int id) { return productService.findById(id); } }
Product.java
package com.ybchen.product_service.domain; import java.io.Serializable; /** * @ClassName:Product * @Description:商品實體類 * @Author:chenyb * @Date:2020/11/1 8:43 下午 * @Versiion:1.0 */ public class Product implements Serializable { /** * 內碼 */ private String id; /** * 商品名稱 */ private String name; /** * 價格,分為單位 */ private int price; /** * 庫存 */ private int store; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public int getStore() { return store; } public void setStore(int store) { this.store = store; } public Product() { } public Product(String id, String name, int price, int store) { this.id = id; this.name = name; this.price = price; this.store = store; } @Override public String toString() { return "product{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + ", store=" + store + '}'; } }View Code
ProductService.java
package com.ybchen.product_service.service; import com.ybchen.product_service.domain.Product; import java.util.List; /** * @ClassName:ProductService * @Description:商品service * @Author:chenyb * @Date:2020/11/1 8:45 下午 * @Versiion:1.0 */ public interface ProductService { /** * 商品列表 * @return */ List<Product> listProduct(); /** * 根據id查詢商品 * @param id * @return */ Product findById(int id); }
ProductServiceImpl.java
package com.ybchen.product_service.service.impl; import com.ybchen.product_service.domain.Product; import com.ybchen.product_service.service.ProductService; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.*; /** * @ClassName:ProductServiceImpl * @Description:ProductService實現類 * @Author:chenyb * @Date:2020/11/1 8:47 下午 * @Versiion:1.0 */ @Service public class ProductServiceImpl implements ProductService { //初始化記憶體商品資料。模擬資料庫中儲存的商品 private static final Map<Integer, Product> daoMap = new HashMap<>(); @Value("${server.port}") private String port; static { for (int i = 0; i < 5; i++) { daoMap.put(i, new Product(i + "", "iphone_" + i, 1000 * i, 10)); } } @Override public List<Product> listProduct() { Collection<Product> values = daoMap.values(); return new ArrayList<>(values); } @Override public Product findById(int id) { Product product = daoMap.get(id); product.setName(product.getName()+"_"+port); return product; } }
ProductServiceApplication.java
package com.ybchen.product_service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } }
啟動並檢視監控臺
啟動2個服務,並檢視監控臺
搭建Eureka Client訂單服務
建立專案
專案結構
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>order_service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>order_service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
# 服務埠號 server.port=8781 # 服務名稱 spring.application.name=order-service # 將服務註冊到註冊中心,eureka_service的地址 eureka.client.service-url.defaultZone:http://localhost:8761/eureka/
OrderServiceApplication.java
啟動類新增Ribbon註解
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
package com.ybchen.order_service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication public class OrderServiceApplication { /** * 負載均衡Ribbon * @return */ @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
OrderController.java
package com.ybchen.order_service.controller; import com.ybchen.order_service.service.ProductOrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("api/v1/order") public class OrderController { @Autowired private ProductOrderService productOrderService; @RequestMapping("save") public Object save(@RequestParam("user_id")int userId,@RequestParam("product_id")int productId){ return productOrderService.save(userId,productId); } }
ProductOrder.java
package com.ybchen.order_service.domain; import java.util.Date; /** * 商品訂單實體類 */ public class ProductOrder { /** * 主鍵 */ private int id; /** * 商品名稱 */ private String productName; /** * 訂單流水號 */ private String tradeNo; /** * 價格,以分位單位 */ private int price; /** * 建立時間 */ private Date createTime; /** * 使用者id */ private String userId; /** * 使用者名稱稱 */ private String userName; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Override public String toString() { return "ProductOrder{" + "id=" + id + ", productName='" + productName + '\'' + ", tradeNo='" + tradeNo + '\'' + ", price=" + price + ", createTime=" + createTime + ", userId='" + userId + '\'' + ", userName='" + userName + '\'' + '}'; } }View Code
ProductOrderService.java
package com.ybchen.order_service.service; import com.ybchen.order_service.domain.ProductOrder; public interface ProductOrderService { ProductOrder save(int userId, int productId); }
ProductOrderServiceImpl.java
package com.ybchen.order_service.service.impl; import com.ybchen.order_service.domain.ProductOrder; import com.ybchen.order_service.service.ProductOrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @ClassName:ProductOrderServiceImpl * @Description:產品訂單實現類 * @Author:chenyb * @Date:2020/11/2 11:34 下午 * @Versiion:1.0 */ @Service public class ProductOrderServiceImpl implements ProductOrderService { @Autowired private RestTemplate restTemplate; /** * 下單介面 * @param userId 使用者id * @param productId 產品id * @return */ @Override public ProductOrder save(int userId, int productId) { Object obj=productId; //get方式 Object forObject = restTemplate.getForObject("http://product-service/api/v1/product/findById?id=" + productId, Object.class); //post方式 // Map<String,String> map=new HashMap<>(); // map.put("id","1"); // String s = restTemplate.postForObject("http://product-service/api/v1/product/test", map, String.class); // System.out.println(s); System.out.println(forObject); //獲取商品詳情 ProductOrder productOrder=new ProductOrder(); productOrder.setTradeNo(UUID.randomUUID().toString()); productOrder.setCreateTime(new Date()); productOrder.setUserId(userId+""); return productOrder; } }
測試負載均衡
feign實戰
簡介
改造訂單服務,呼叫商品服務獲取商品資訊
官網例子
點我直達
改造訂單服務
新增feign依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>order_service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>order_service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--openfeign依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
啟動類上添加註解
啟動類上新增:@EnableFeignClients
新增一個介面
ProductClient.java
package com.ybchen.order_service.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; /** * 商品服務客戶端 */ // name=商品服務的服務名==========》spring.application.name=product-service @FeignClient(name = "product-service") @RequestMapping("/api/v1/product") public interface ProductClient { @GetMapping("findById") String findById(@RequestParam("id") int id); }
修改ProductOrderServiceImpl.java
原先
package com.ybchen.order_service.service.impl; import com.ybchen.order_service.domain.ProductOrder; import com.ybchen.order_service.service.ProductOrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @ClassName:ProductOrderServiceImpl * @Description:產品訂單實現類 * @Author:chenyb * @Date:2020/11/2 11:34 下午 * @Versiion:1.0 */ @Service public class ProductOrderServiceImpl implements ProductOrderService { @Autowired private RestTemplate restTemplate; /** * 下單介面 * @param userId 使用者id * @param productId 產品id * @return */ @Override public ProductOrder save(int userId, int productId) { Object obj=productId; //get方式 Object forObject = restTemplate.getForObject("http://product-service/api/v1/product/findById?id=" + productId, Object.class); //post方式 // Map<String,String> map=new HashMap<>(); // map.put("id","1"); // String s = restTemplate.postForObject("http://product-service/api/v1/product/test", map, String.class); // System.out.println(s); System.out.println(forObject); //獲取商品詳情 ProductOrder productOrder=new ProductOrder(); productOrder.setTradeNo(UUID.randomUUID().toString()); productOrder.setCreateTime(new Date()); productOrder.setUserId(userId+""); return productOrder; } }
修改為
package com.ybchen.order_service.service.impl; import com.ybchen.order_service.domain.ProductOrder; import com.ybchen.order_service.service.ProductClient; import com.ybchen.order_service.service.ProductOrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.UUID; /** * @ClassName:ProductOrderServiceImpl * @Description:產品訂單實現類 * @Author:chenyb * @Date:2020/11/2 11:34 下午 * @Versiion:1.0 */ @Service public class ProductOrderServiceImpl implements ProductOrderService { @Autowired private ProductClient productClient; /** * 下單介面 * * @param userId 使用者id * @param productId 產品id * @return */ @Override public ProductOrder save(int userId, int productId) { //-----------呼叫商品服務開始------------ String byId = productClient.findById(productId); System.out.println(byId); //-----------呼叫商品服務結束------------ //獲取商品詳情 ProductOrder productOrder = new ProductOrder(); productOrder.setTradeNo(UUID.randomUUID().toString()); productOrder.setCreateTime(new Date()); productOrder.setUserId(userId + ""); return productOrder; } }
測試商品服務
補充(設定服務呼叫超時時間)
預設連線10秒,讀取60秒,但是由於hystrix預設是1秒超時
官網案例,點我直達
application.properties
# 設定連線和讀取超時時間 feign.client.config.default.connect-timeout=5000 feign.client.config.default.read-timeout=1100
服務降級熔斷(Hystrix)
為什麼要用?
在一個分散式系統裡,一個服務依賴多個服務,可能存在某個服務呼叫失敗,比如超時、異常等,如何能保證在一個依賴出問題的情況下,不會導致整體服務故障,可以通過Hystrix來解決。
官網例子
點我直達
修改訂單服務
新增依賴
<!--hystrix依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>order_service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>order_service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--openfeign依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--hystrix依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>View Code
啟動類加註解
@EnableCircuitBreaker
修改控制層
添加註解,@HystrixCommand,並定義回撥方法,返回值、入參必須一致!!!!
入參、返回值,不一致會報錯
feign結合Hystrix
修改訂單服務
開啟hystrix
# 開啟hystrix feign.hystrix.enabled=true
ProductClient.java
package com.ybchen.order_service.service; import com.ybchen.order_service.fallback.ProductClientFallBack; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; /** * 商品服務客戶端 */ // name=商品服務的服務名==========》spring.application.name=product-service @FeignClient(name = "product-service",fallback = ProductClientFallBack.class) //@RequestMapping("/api/v1/product") public interface ProductClient { @GetMapping("/api/v1/product/findById") String findById(@RequestParam("id") int id); }
ProductClientFallBack.java
package com.ybchen.order_service.fallback; import com.ybchen.order_service.service.ProductClient; import org.springframework.stereotype.Component; /** * 針對商品服務,做降級處理 */ @Component public class ProductClientFallBack implements ProductClient { @Override public String findById(int id) { System.out.println("商品服務被降級了~~~~~~~"); return null; } }
驗證商品服務熔斷
為什麼對商品服務做了熔斷,還返回這個結果呢,那是因為service實現類,內部發生了錯誤
熔斷降級服務報警通知(重要)
下面寫一些虛擬碼,比如:xxx微服務掛了,然後通過簡訊、郵件的方式,通知相應的開發人員,緊急處理事故等。
修改訂單服務
修改hystrix超時時間
禁用超時時間(不推薦)
hystrix.command.default.execution.timeout.enabled=false
設定超時時間(推薦)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=4000
原始碼位置講解
通過這種方法,還可以設定更多的hystrix預設值
斷路器Dashboard監控儀表盤
修改訂單服務
新增依賴
<!--hystrix儀表盤--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ybchen</groupId> <artifactId>order_service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>order_service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--openfeign依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--hystrix依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!--hystrix儀表盤--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>pom.xml
啟動類上加註解
新增:@EnableHystrixDashboard
修改配置檔案
# 暴露全部的監控資訊 management.endpoints.web.exposure.include=*
訪問儀表盤
http://127.0.0.1:8781/hystrix http://127.0.0.1:8781/actuator/hystrix.stream
儀表盤實際工作中用處不大(仁者見仁智者見智),純屬學習用,具體引數,請自行百度,只要把微服務熔斷/降級報警通知處理好,比啥都好