一、分佈式系統面臨的問題spring
(1)服務雪崩後端
多個微服務之間調用的時候,假設微服務A調用微服務B和C,微服務B和C又調用其它的微服務,這就是所謂的「扇出」。若是扇出的鏈路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會佔用愈來愈多的系統資源,進而引發系統崩潰,引發所謂的「雪崩效應」。服務器
對於高流量的應用來講,單一的後端依賴可能會致使全部服務器上的全部資源都在幾秒鐘內飽和。比失敗更糟糕的是,這些應用程序還可能致使服務之間的延遲增長,備份隊列,線程和其餘系統資源緊張,致使整個系統發生更多的級聯故障。這些都表示須要對故障和延遲進行隔離和管理,以便單個依賴關係的失敗,不能取消整個應用程序或系統。app
(2)解決方案框架
這種模式主要是參考電路熔斷,若是一條線路電壓太高,保險絲會熔斷,防止火災。放到咱們的系統中,若是某個目標服務調用慢或者有大量超時,此時,熔斷該服務的調用,對於後續調用請求,不在繼續調用目標服務,直接返回,快速釋放資源。若是目標服務狀況好轉則恢復調用。分佈式
這種模式就像對系統請求按類型劃分紅一個個小島的同樣,當某個小島被火燒光了,不會影響到其餘的小島。例如:能夠對不一樣類型的請求使用線程池來資源隔離,每種類型的請求互不影響,若是一種類型的請求線程資源耗盡,則對後續的該類型請求直接返回,再也不調用後續資源。這種模式使用場景很是多,例如將一個服務拆開,對於重要的服務使用單獨服務器來部署,再或者公司最近推廣的多中心。ide
上述的熔斷模式和隔離模式都屬於出錯後的容錯處理機制,而限流模式則能夠稱爲預防模式。限流模式主要是提早對各個類型的請求設置最高的QPS閾值,若高於設置的閾值則對該請求直接返回,再也不調用後續資源。這種模式不能解決服務依賴的問題,只能解決系統總體資源分配問題,由於沒有被限流的請求依然有可能形成雪崩效應。微服務
二、服務熔斷測試
(1)概念ui
當扇出鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速返回"錯誤"的響應信息。當檢測到該節點微服務調用響應正常後恢復調用鏈路。在SpringCloud框架裏熔斷機制經過Hystrix實現。Hystrix會監控微服務間調用的情況,當失敗的調用到必定閾值,缺省是5秒內20次調用失敗就會啓動熔斷機制。
(2)實現
添加依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
配置文件中修改服務的名稱:
instance: instance-id: my8001-hystrix prefer-ip-address: true
定義Controller:
一旦調用GET方法失敗並拋出了錯誤信息後,會自動調用@HystrixCommand標註好的fallbackMethod調用類中的指定方法。可是,此種方式會存在一個問題就是每個方法都須要一個處理
@RestController public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value="/dept/get/{id}",method= RequestMethod.GET) @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if(null == dept) { throw new RuntimeException("該ID:"+id+"沒有沒有對應的信息"); } return dept; } public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id) .setDname("該ID:"+id+"沒有沒有對應的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
在啓動類中添加對hystrixR熔斷機制的支持
@EnableCircuitBreaker
三、服務降級
(1)概念
總體資源不足,將某些服務先關掉,待渡過難關,再從新開啓,服務降級是在客戶端完成的。
(2)實現
新建一個實現了FallbackFactory接口的類DeptClientServiceFallbackFactory,該接口是專門處理異常的,與上面的服務熔斷處理異常的方式相比,此種方式實現了邏輯與異常處理業務的分離
@Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id) .setDname("該ID:" + id + "沒有沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
在API模塊中的業務接口的註解中添加屬性:
@FeignClient(value = "PROVIDER",fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
feign: hystrix: enabled: true
(3)測試
在只啓動一個服務的提供者(8001)的狀況下,可以正常訪問,當講該服務關閉的時候可以給出提示信息。也就是說在服務端不可用的時候客戶端可以獲得提示,而不是掛起。