-java
一、在一些場景中,簡單的觸發在 FeignClient 加入 Fallback 屬性便可,而另外有一些場景須要訪問致使回退觸發的緣由,那麼這個時候能夠在 FeignClient 中加入 FallbackFactory 屬性便可; 二、而在使用 Fallback 和 FallbackFactory 時候,我僅僅表述我的觀點,發現兩者混合一塊兒用的話,會發生衝突狀況,因此你們用的時候注重考慮一下場景,兩者屬性用其一便可。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>springms-consumer-movie-feign-with-hystrix-factory</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>com.springms.cloud</groupId> <artifactId>springms-spring-cloud</artifactId> <version>1.0-SNAPSHOT</version> </parent> <dependencies> <!-- web模塊 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 客戶端發現模塊 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- Java HTTP 客戶端開發的工具的模塊 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <!-- Hystrix 模塊 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> </dependencies> </project>
spring: application: name: springms-consumer-movie-feign-with-hystrix-factory server: port: 8115 eureka: client: # healthcheck: # enabled: true serviceUrl: defaultZone: http://admin:admin@localhost:8761/eureka instance: prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}} # 解決第一次請求報超時異常的方案,由於 hystrix 的默認超時時間是 1 秒,所以請求超過該時間後,就會出現頁面超時顯示 : # # 這裏就介紹大概三種方式來解決超時的問題,解決方案以下: # # 第一種方式:將 hystrix 的超時時間設置成 5000 毫秒 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000 # # 或者: # 第二種方式:將 hystrix 的超時時間直接禁用掉,這樣就沒有超時的一說了,由於永遠也不會超時了 # hystrix.command.default.execution.timeout.enabled: false # # 或者: # 第三種方式:索性禁用feign的hystrix支持 # feign.hystrix.enabled: false ## 索性禁用feign的hystrix支持 # 超時的issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/768 # 超時的解決方案: http://stackoverflow.com/questions/27375557/hystrix-command-fails-with-timed-out-and-no-fallback-available # hystrix配置: https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds
package com.springms.cloud.entity; import java.math.BigDecimal; public class User { private Long id; private String username; private String name; private Short age; private BigDecimal balance; public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Short getAge() { return this.age; } public void setAge(Short age) { this.age = age; } public BigDecimal getBalance() { return this.balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } }
package com.springms.cloud.feign; import com.springms.cloud.entity.User; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.*; /** * 用戶Http請求的客戶端。 * * 註解FeignClient的傳參:表示的是註冊到 Eureka 服務上的模塊名稱。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/9/24 * */ @FeignClient(name = "springms-provider-user", /*fallback = HystrixClientFallback.class,*/ fallbackFactory = HystrixClientFallbackFactory.class) public interface UserFeignHystrixFactoryClient { /** * 這裏有兩個坑須要注意:<br/> * * <li>這裏須要設置請求的方式爲 RequestMapping 註解,用 GetMapping 註解是運行不成功的,即 GetMapping 不支持。</li> * <li>註解 PathVariable 裏面須要填充變量的名字,否則也是運行不成功的。</li> * * @param id * @return */ @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET) public User findById(@PathVariable("id") Long id); }
package com.springms.cloud.feign; import com.springms.cloud.entity.User; import org.springframework.stereotype.Component; /** * Hystrix 客戶端回退機制類。 * * 這裏加上註解 Component 的目的:就是由於沒有這個註解,運行時候會報錯,報錯會說沒有該類的這個實例,因此咱們就想到要實例化這個類,所以加了這個註解。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/9/24 * */ @Component public class HystrixClientFallback implements UserFeignHystrixFactoryClient { @Override public User findById(Long id) { System.out.println("======== findById Fallback " + Thread.currentThread().getThreadGroup() + " - " + Thread.currentThread().getId() + " - " + Thread.currentThread().getName()); User tmpUser = new User(); tmpUser.setId(0L); return tmpUser; } }
package com.springms.cloud.feign; import com.springms.cloud.entity.User; import feign.hystrix.FallbackFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * Hystrix 客戶端回退機制類。 * * 這裏加上註解 Component 的目的:就是由於沒有這個註解,運行時候會報錯,報錯會說沒有該類的這個實例,因此咱們就想到要實例化這個類,所以加了這個註解。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/9/24 * */ @Component public class HystrixClientFallbackFactory implements FallbackFactory<UserFeignHystrixFactoryClient> { private static final Logger Logger = LoggerFactory.getLogger(HystrixClientFallbackFactory.class); @Override public UserFeignHystrixFactoryClient create(Throwable e) { Logger.info("fallback; reason was: {}", e.getMessage()); System.out.println("======== UserFeignHystrixFactoryClient.create " + Thread.currentThread().getThreadGroup() + " - " + Thread.currentThread().getId() + " - " + Thread.currentThread().getName()); return new UserFeignWithFallBackFactoryClient(){ @Override public User findById(Long id) { System.out.println("======== findById FallBackFactory " + Thread.currentThread().getThreadGroup() + " - " + Thread.currentThread().getId() + " - " + Thread.currentThread().getName()); User tmpUser = new User(); tmpUser.setId(-1L); return tmpUser; } }; } } /**************************************************************************************** @FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class) protected interface HystrixClient { @RequestMapping(method = RequestMethod.GET, value = "/hello") Hello iFailSometimes(); } @Component static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> { @Override public HystrixClient create(Throwable cause) { return new HystrixClientWithFallBackFactory() { @Override public Hello iFailSometimes() { return new Hello("fallback; reason was: " + cause.getMessage()); } }; } } ****************************************************************************************/
package com.springms.cloud.feign; /** * 回退處理客戶端。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/9/24 * */ public interface UserFeignWithFallBackFactoryClient extends UserFeignHystrixFactoryClient{ }
package com.springms.cloud.controller; import com.springms.cloud.entity.User; import com.springms.cloud.feign.UserFeignHystrixFactoryClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class MovieFeignHystrixFactoryController { @Autowired private UserFeignHystrixFactoryClient userFeignHystrixFactoryClient; @GetMapping("/movie/{id}") public User findById(@PathVariable Long id) { System.out.println("======== findById Controller " + Thread.currentThread().getThreadGroup() + " - " + Thread.currentThread().getId() + " - " + Thread.currentThread().getName()); return userFeignHystrixFactoryClient.findById(id); } }
package com.springms.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; /** * 電影微服務接入Feign,添加 fallbackFactory 屬性來觸發請求進行容災降級。 * * Feign: Java HTTP 客戶端開發的工具。 * * 註解 EnableFeignClients 表示該電影微服務已經接入 Feign 模塊。 * * @author hmilyylimh * * @version 0.0.1 * * @date 2017/9/24 * */ @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class MsConsumerMovieFeignHystrixFactoryApplication { public static void main(String[] args) { SpringApplication.run(MsConsumerMovieFeignHystrixFactoryApplication.class, args); System.out.println("【【【【【【 電影Feign-HystrixFactory微服務 】】】】】】已啓動."); } }
/**************************************************************************************** 1、電影微服務接入Feign,添加 fallbackFactory 屬性來觸發請求進行容災降級(測試正常接入功能): 一、註解:EnableFeignClients; 二、編寫類 HystrixClientFallbackFactory 回退處理機制類,並給該類加上註解 Component ;加入 FeignClient 註解 // @FeignClient(name = "springms-provider-user", fallback = HystrixClientFallback.class ) 三、啓動 springms-discovery-eureka 模塊服務,啓動1個端口; 四、啓動 springms-provider-user 模塊服務,啓動1個端口; 五、啓動 springms-consumer-movie-feign-with-hystrix-factory 模塊服務; 六、在瀏覽器輸入地址 http://localhost:8115/movie/1 能夠看到具體的用戶信息(即用戶ID != 0 的用戶)成功的被打印出來; ****************************************************************************************/ /**************************************************************************************** 2、電影FeignHystrix-HystrixFactory微服務接入 HystrixFactory 功能模塊(測試斷路器功能): 一、註解:EnableFeignClients; 二、編寫類 HystrixClientFallbackFactory 回退處理機制類,並給該類加上註解 Component,UserFeignHystrixFactoryClient 加上 fallbackFactory 屬性; // @FeignClient(name = "springms-provider-user", fallback = HystrixClientFallback.class, fallbackFactory = HystrixClientFallbackFactory.class ) 三、啓動 springms-discovery-eureka 模塊服務,啓動1個端口; 四、啓動 springms-provider-user 模塊服務,啓動1個端口; 五、啓動 springms-consumer-movie-feign-with-hystrix-factory 模塊服務; 六、在瀏覽器輸入地址 http://localhost:8115/movie/1 能夠看到具體的用戶信息(即用戶ID != 0 的用戶)成功的被打印出來; 七、中止 springms-provider-user 模塊服務; 八、在瀏覽器輸入地址http://localhost:8115/movie/1 能夠看到用戶信息ID = 0 的用戶成功的被打印出來,但隨着問題也來了; 九、HystrixClientFallbackFactory 截獲的異常卻沒有被打印出來,原本用戶微服務中止的話,請求連接就已經連接超時了,可是爲啥異常沒有打印出來呢?請看下面第三中測試方法。 ****************************************************************************************/ /**************************************************************************************** 3、電影FeignHystrix-HystrixFactory微服務接入 HystrixFactory 功能模塊(測試斷路器功能): 一、註解:EnableFeignClients; 二、編寫類 HystrixClientFallbackFactory 回退處理機制類,並給該類加上註解 Component,UserFeignHystrixFactoryClient 去掉 fallback 屬性,而後加上 fallbackfactory 屬性; // @FeignClient(name = "springms-provider-user", fallbackFactory = HystrixClientFallbackFactory.class ) 三、啓動 springms-discovery-eureka 模塊服務,啓動1個端口; 四、啓動 springms-provider-user 模塊服務,啓動1個端口; 五、啓動 springms-consumer-movie-feign-with-hystrix-factory 模塊服務; 六、在瀏覽器輸入地址 http://localhost:8115/movie/1 能夠看到具體的用戶信息(即用戶ID != 0 的用戶)成功的被打印出來; 七、中止 springms-provider-user 模塊服務; 八、在瀏覽器輸入地址http://localhost:8115/movie/1 能夠看到用戶信息ID = -1 的用戶成功的被打印出來,並且異常信息日誌也被打印出來了,這就正常了; 注意:第2步驟:UserFeignHystrixFactoryClient 去掉 fallback 屬性,而後加上 fallbackfactory 屬性; 因此這裏目前暫時謹記,fallback 和 fallbackfactory 屬性會有衝突,因此只要其一就好了; ****************************************************************************************/
https://gitee.com/ylimhhmily/SpringCloudTutorial.gitgit
SpringCloudTutorial交流QQ羣: 235322432github
SpringCloudTutorial交流微信羣: 微信溝通羣二維碼圖片連接web
歡迎關注,您的確定是對我最大的支持!!!spring