consumer
的CenterFeign.java
,把返回值所有設置爲String
/** * 是consumer調用provider(須要指定provider的名字) * 請求的清單列表:規定調用地址、參數、返回值 * 在正常走通的時候不走CenterFeignFallBack,當provider down的時候走熔斷器,至關因而類的try-catch */ @FeignClient(name = "provider",fallback = CenterFeignFallBack.class) public interface CenterFeign { @GetMapping("/optionData.do") public String optionData(); @PostMapping("/showEmpData.do") //Feign:不支持對象傳參,因此要用@RequestBody public String showEmpData(@RequestBody Emp emp); @PostMapping("/add.do") public String add(@RequestBody Emp emp); @PostMapping("/edit.do") public String edit(@RequestBody Emp emp); @GetMapping("/del.do") public String del(@RequestParam("empno") Integer empno); }
CenterFeign.java
的同包下建立實現了CenterFeign
接口的CenterFeignFallBack.java
做爲熔斷器@Component public class CenterFeignFallBack implements CenterFeign { @Override public String optionData() { return "provider-optionData-error"; } @Override public String showEmpData(Emp emp) { return "provider-showEmpData-error"; } @Override public String add(Emp emp) { return "provider-add-error"; } @Override public String edit(Emp emp) { return "provider-edit-error"; } @Override public String del(Integer empno) { return "provider-del-error"; } }
consumer
的CenterController.java
,返回值全改成String@RestController public class CenterController{ @Resource private CenterFeign centerFeign; @GetMapping("/optionData-consumer.do") public String optionData() { return centerFeign.optionData(); } @PostMapping("/showEmpData-consumer.do") public String showEmpData(@RequestBody Emp emp) { return centerFeign.showEmpData(emp); } @PostMapping("/add-consumer.do") public String add(@RequestBody Emp emp) { return centerFeign.add(emp); } @PostMapping("/edit-consumer.do") public String edit(@RequestBody Emp emp) { return centerFeign.edit(emp); } @GetMapping("/del-consumer.do") public String del(@RequestParam("empno") Integer empno) { return centerFeign.del(empno); } }
consumer
中的配置文件application.properties
中有沒有開啓熔斷feign.hystrix.enabled=true
,沒有的話加上#端口號 server.port=8764 #應用名 spring.application.name=consumer #eureka客戶端服務url默認區域 eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ #開啓熔斷器 feign.hystrix.enabled=true #下線名稱.ribbon.NF加載平衡規則類名,這裏先註釋 provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
訪問http://localhost:8761/
html
發現全部服務已經註冊java
正常走provider沒有問題mysql
走consumer也沒有問題,只是返回的格式是字符串類型,不是json類型,可是不要緊,格式仍是json的格式,前臺該怎麼轉還能怎麼轉,不影響redis
那怎麼走容錯?spring
如今手動中止一個providersql
由於這裏我開了負載均衡策略(在consumer中的配置文件中provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
),因此有必定概率觸發熔斷器,數據庫
這就至關於類之間的try-catch,沒有熔斷器的話這裏百分百是報錯誤代碼.那這裏我先把負載均衡關掉,在測試有沒有走容錯,(猜一下,會走嗎?)json
這裏我測了這麼屢次,都沒有走熔斷,因此顯然不走,爲什麼?緩存
由於沒有手動設置負載均衡策略的話,默認走的是輪詢.機制,啥是Ribbon輪詢機制?服務器
簡單的說就是有abc三臺服務器,正常的狀況下走a->b->c,在有一臺down了的時候,那臺就自動跳過,好比b down了,那麼就是a->c
以上,我的理解,如有誤請指正,よろしくお願いします~
如今,既然一臺服務器工做是沒有問題 那我兩臺provider所有中止呢?
那答案是確定的,絕壁走容錯~~
新建模塊(Spring initializr)zuul-client
application.properties
#網關端口 server.port=8765 #應用名 spring.application.name=zuul #網關路徑提供者,後面的**表示:xxx.do zuul.routes.provider=/pro/**/ #網關路徑消費者,後面的**表示:xxx.do zuul.routes.consumer=/con/**/
//開啓網關代理 @EnableZuulProxy //開啓eureka客戶端 @EnableEurekaClient @SpringBootApplication public class ZuulClientApplication { public static void main(String[] args) { SpringApplication.run(ZuulClientApplication.class, args); } }
測試provider
測試consumer
統一了全部客戶端的ip地址和端口號,咱們只要給不一樣層級的應用起別名就ok了(就是這裏的)
provider-one
模塊的pom文件中加入redis依賴<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
provider-one
模塊的DeptServiceImpl
文件,加入@Autowired private RedisTemplate redisTemplate;
@Service public class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Autowired private RedisTemplate redisTemplate; @Override public Map<String, Object> optionData() { Map<String, Object> map=new HashMap<>(); List<Map<String, Object>> list = deptMapper.selAllDeptData(); // 定義Redis存儲集合的對象 ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList(); //拼接Redis中存儲數據對應的key String key = "depts"; //判斷Redis中是否有key,沒有就說明是第一次訪問,將數據放入Redis if(!redisTemplate.hasKey(key)){ //直接將數據庫查詢出來的值放入Redis System.out.println("provider-one-optionData的值已經放入Redis"); redisList.leftPushAll(key,list); } map.put("data",list); return map; } }
DeptService
,返回值變成mappublic interface DeptService { Map<String,Object> optionData(); }
CenterController
,把返回值類型改成Mappublic Map<String, Object> optionData() { return deptService.optionData(); }
provider-two
的pom.xml中加入redis依賴<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
provider-two
模塊的DeptServiceImpl
文件,加入@Autowired private RedisTemplate redisTemplate;
@Service public class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Autowired private RedisTemplate redisTemplate; @Override public Map<String, Object> optionData() { Map<String, Object> map=new HashMap<>(); List<Map<String, Object>> list = deptMapper.selAllDeptData(); // 定義Redis存儲集合的對象 ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList(); //拼接Redis中存儲數據對應的key String key = "depts"; //判斷Redis中是否有key,沒有就說明是第一次訪問,將數據放入Redis if(!redisTemplate.hasKey(key)){ //直接將數據庫查詢出來的值放入Redis System.out.println("provider-two-optionData的值已經放入Redis"); redisList.leftPushAll(key,list); } map.put("data",list); return map; } }
DeptService
,返回值變成mappublic interface DeptService { Map<String,Object> optionData(); }
CenterController
,把返回值類型改成Mappublic Map<String, Object> optionData() { return deptService.optionData(); }
provider-one
模塊的配置文件application.properties
,加入Redis配置#服務端口號 server.port=8762 #應用名 spring.application.name=provider #eureka客戶端服務url默認區域 eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ #數據源驅動類名 spring.datasource.driver-class-name=com.mysql.jdbc.Driver #數據源url spring.datasource.url=jdbc:mysql:///kh75 #數據源用戶名 spring.datasource.username=root #數據源密碼 spring.datasource.password=admin #後期會寫mapper.xml,這裏先註釋 #mybatis.mapper-locations=classpath:mapper/*.xml #給實體類起別名,一樣這裏先註釋 #mybatis.type-aliases-package=cn.kgc.vo #配置Redis spring.redis.port=6379 #redis所在的主機地址 spring.redis.host=xxx.xxx.xxx spring.redis.database=0
provider-two
模塊的配置文件application.properties
,加入Redis配置#服務端口號 server.port=8763 #應用名 spring.application.name=provider #eureka客戶端服務url默認區域 eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ #數據源驅動類名 spring.datasource.driver-class-name=com.mysql.jdbc.Driver #數據源url spring.datasource.url=jdbc:mysql:///kh75 #數據源用戶名 spring.datasource.username=root #數據源密碼 spring.datasource.password=admin #後期會寫mapper.xml,這裏先註釋 #mybatis.mapper-locations=classpath:mapper/*.xml #給實體類起別名,一樣這裏先註釋 #mybatis.type-aliases-package=cn.kgc.vo #配置Redis spring.redis.port=6379 #redis所在的主機地址 spring.redis.host=xxx.xxx.xx spring.redis.database=0
consumer
的CenterFeign,全部返回值都是map@FeignClient(name = "provider",fallback = CenterFeignFallBack.class) public interface CenterFeign { @GetMapping("/optionData.do") Map<String,Object> optionData(); @PostMapping("/showEmpData.do") //Feign:不支持對象傳參,因此要用@RequestBody Map<String,Object> showEmpData(@RequestBody Emp emp); @PostMapping("/add.do") Map<String,Object> add(@RequestBody Emp emp); @PostMapping("/edit.do") Map<String,Object> edit(@RequestBody Emp emp); @GetMapping("/del.do") Map<String,Object> del(@RequestParam("empno") Integer empno); }
CenterFeignFallBack
@Component public class CenterFeignFallBack implements CenterFeign { private Map<String, Object> map = new HashMap<> (); @Autowired private RedisTemplate redisTemplate; @Override public Map<String,Object> optionData() { ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList(); map.put("msg","provider-optionData-error"); map.put("feign-data",redisList.range("depts",0,-1)); return map; } @Override public Map<String,Object> showEmpData(Emp emp) { ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList(); map.put("msg","provider-showEmpData-error"); //這裏對應的serviceImp裏面還沒修改爲Redis,先放着 map.put("feign-data",redisList.range("emps",0,-1)); return map; } @Override public Map<String,Object> add(Emp emp) { map.put("msg","provider-add-error"); return map; } @Override public Map<String,Object> edit(Emp emp) { map.put("msg","provider-edit-error"); return map; } @Override public Map<String,Object> del(Integer empno) { map.put("msg","provider-del-error"); return map; } }
@RestController public class CenterController{ @Resource private CenterFeign centerFeign; @GetMapping("/optionData-consumer.do") public Map<String,Object> optionData() { return centerFeign.optionData(); } @PostMapping("/showEmpData-consumer.do") public Map<String,Object> showEmpData(@RequestBody Emp emp) { return centerFeign.showEmpData(emp); } @PostMapping("/add-consumer.do") public Map<String,Object> add(@RequestBody Emp emp) { return centerFeign.add(emp); } @PostMapping("/edit-consumer.do") public Map<String,Object> edit(@RequestBody Emp emp) { return centerFeign.edit(emp); } @GetMapping("/del-consumer.do") public Map<String,Object> del(@RequestParam("empno") Integer empno) { return centerFeign.del(empno); } }
把提供者斷掉,理論上走熔斷和redis數據
以上....