springcloud子模塊之間的通信
1.搭建公共模塊common
2.在common層搭建domain層user
package cn.itsource.domain; public class User { private Long id; private String username; private String password; public User() { } public User(Long id, String username, String password) { this.id = id; this.username = username; this.password = password; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
3.服務層編寫接口
1.導入依賴:服務層依賴common層
<dependency>
<groupId>cn.itsource.springcloud</groupId>
<artifactId>springcloud-common-user</artifactId>
<version>...</version>
</dependency>
2.創建controller
/** * 用戶提供者服務 */ @RestController public class UserProviderController { /** * 提供者方法,orderServer消費者來調用 * @param id * @return */ // @RequestMapping(value = "/user/{id}",method = RequestMethod.GET) @GetMapping("/user/{id}") public User getUserById(@PathVariable("id")Long id){ System.out.println("UserProviderController.getUserById被調用了......"); return new User(id,"zs:"+id , "123"); } }
4.
1.依賴common模塊
<dependency>
<groupId>cn.itsource.springcloud</groupId>
<artifactId>springcloud-common-user</artifactId>
<version>...</version>
</dependency>
2.
/**
* SpringMvc提供的一個基於Rest風格的http調用工具
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
3.
/** * 訂單消費者服務 */ @RestController public class OrderConsumerController { @Autowired private RestTemplate restTemplate ; /** * 該方法是瀏覽器來調用 * @param id * @return */ @GetMapping("/order/user/{id}") public User getUserById(@PathVariable("id") Long id){ System.out.println("OrderConsumerController.getUserById被調用了......"); String url = "http://localhost:2000/user/"+id; User user = restTemplate.getForObject(url, User.class); return user; } }
一.單節點故障
1.什么是EurekaServer單節點故障
如果只有一個EurekaSever,如果EurekaSever掛了那么整個微服務都不可用
2.解決方案
EurekaServer高可用集群
二.EurekaServer集群
1.搭建EurekaServer集群
創建兩個本地域名 C:\Windows\System32\drivers\etc\hosts
127.0.0.1 peer1
127.0.0.1 peer2
修改注冊中心eureka-server-1000
server:
port: 1000
eureka:
instance:
hostname: peer1
client:
registerWithEureka: false #禁用注冊中心向自己注冊
fetchRegistry: false #不讓注冊中心獲取服務的注冊列表
serviceUrl:
defaultZone: http://peer2:1001/eureka/
#注冊中心的注冊地址 ,其他微服務需要向這個地址注冊
搭建第二個注冊中心eureka-server-1001 - 復制
server:
port: 1001
eureka:
instance:
hostname: peer2
client:
registerWithEureka: false #禁用注冊中心向自己注冊
fetchRegistry: false #不讓注冊中心獲取服務的注冊列表
serviceUrl:
defaultZone: http://peer1:1000/eureka/
#注冊中心的注冊地址 ,其他微服務需要向這個地址注冊
3.修改EurekaClient (UserServer ,OrderServer)
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #注冊中心地址
...
五.Ribbon
ribbon是負載均衡器,是基於RestTemplate ,它賦予了RestTemplate 負載均衡的能力
一.集群和負載均衡原理
二.提供者user-server集群
1.創建user-server服務2001 - 賦值
2.修改配置
eureka: client: serviceUrl: defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #注冊中心地址 instance: prefer-ip-address: true #使用ip地址注冊 instance-id: user-server1 #指定服務的id server: port: 2000 spring: application: name: user-server
注意:instance-id需要修改 , 而 spring.application.name 不需要修改 , 端口需要修改
3.修改主類名,pom中的名字,parent中的模塊增加
三.order-server集成Ribbon
1.導入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2.修改RestTemplate的Bean的定義
/** * SpringMvc提供的一個基於Rest風格的http調用工具 * @LoadBalanced :ribbon的負載均衡標簽,賦予RestTemplate有負債均衡的能力 */ @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
@LoadBalanced :ribbon的負載均衡標簽,賦予RestTemplate有負債均衡的能力
3.修改Controller調用方式
@GetMapping("/order/user/{id}")
public User getUserById(@PathVariable("id") Long id){
System.out.println("OrderConsumerController.getUserById被調用了......");
//String url = "http://localhost:2000/user/"+id;
String url = "http://user-server/user/"+id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
修改效果: String url = "http://user-server/user/"+id;
ribbon默認使用的輪詢策略
六.Feign
一.什么是Feign
基於Ribbon封裝的客戶端負載均衡器
二.Feign的集成 - springcloud-dept-server-4000
1.導入依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2.配置類開啟Feign
@SpringBootApplication @EnableFeignClients("cn.itsource.client") public class DeptServerApplication4000 ...
3.編寫Feign的接口
/** * @FeignClient(value="user-server") : 針對於用戶服務調用的 Fiegn的客戶端接口 * value屬性就是該接口要調用的目標服務的名字 * Feign是如何實現服務調用的: * 1.通過@FeignClient(value="user-server")標簽上的服務名字能夠找到要調用的目標服務 * 2.通過接口中的方法的 @GetMapping的url路徑找到目標服務的controller的方法 , * 所以要保證Feign客戶端接口的方法和目標服務的對應的方法要完全一致。 * */ @FeignClient(value="user-server") public interface UserFeignClient { @GetMapping("/user/{id}") User getUserById(@PathVariable("id")Long id); }
Feign客戶端接口的方法和目標服務的對應的方法要完全一致
4.調用
@RestController public class DeptConsumerController { @Autowired private UserFeignClient userFeignClient ; /** * 該方法是瀏覽器來調用 * @param id * @return */ @GetMapping("/dept/user/{id}") public User getUserById(@PathVariable("id") Long id){ User user = userFeignClient.getUserById(id); //使用Feign的接口調用 return user; } }
七.Hystrix
一.雪崩效應
一個微服務的故障導致整個微服務調用鏈全部癱瘓
二.Hystrix介紹
解決服務器故障(雪崩)的一個組件 ,它可以實現:隔離 ,熔斷 ,降級,緩存
-
隔離 :包括線程池隔離和信號量隔離,限制調用分布式服務的資源使用,某一個調用的服務出現問題不會影響其他服務調用。
-
熔斷 :當請求次數達到規定的閥值都出現服務故障(超時),Hystrix就把服務標記為短路狀態.
正常情況下,斷路器處於關閉狀態(Closed),如果調用持續出錯或者超時,電路被打開進入熔斷狀態(Open),后續一段時間內的所有調用都會被拒絕(Fail Fast),一段時間以后,保護器會嘗試進入半熔斷狀態(Half-Open),允許少量請求進來嘗試,
如果調用仍然失敗,則回到熔斷狀態
如果調用成功,則回到電路閉合狀態; -
降級 :高並發情況下 ,為了保證一些主要的服務有足夠的資源不出問題 ,會認為的關掉一些無關緊要的服務,然后返回一些托底的數據,給用戶一個友好的提示。
-
緩存 :Hystrix內部會把請求做緩存
三.Ribbon集成Hystrix - springcloud-order-server-3000
1.導入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.controller方法貼注解
/** * 該方法是瀏覽器來調用 * @HystrixCommand :開啟方法的短路功能 , 如果方法出現異常,會調用 fallbackMethod * 指向的方法 ,然后返回托底數據 */ @HystrixCommand(fallbackMethod = "getUserByIdFallback") @GetMapping("/order/user/{id}") public JsonResult getUserById(@PathVariable("id") Long id){ System.out.println("OrderConsumerController.getUserById被調用了......"); String url = "http://user-server/user/"+id; User user = restTemplate.getForObject(url, User.class); return JsonResult.me().setData(user); }
3.托底方法
public JsonResult getUserByIdFallback(@PathVariable("id") Long id){ return JsonResult.me().setSuccess(false) .setMessage("服務展示不可用,請騷后重試[服務降級]"); }
注意:托底方法的參數和返回結果要和原方法一致
四.Feign集成Hystrix - springcloud-dept-server-4000
1.開啟Hystrix
feign: hystrix: enabled: true #開啟熔斷支持 client: config: remote-service: #服務名,填寫default為所有服務 connectTimeout: 30000 readTimeout: 30000 hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 30000
2.修改Fiegn客戶端接口
@FeignClient(value="user-server" ,fallback = UserFeignClientFallback.class) public interface UserFeignClient { @GetMapping("/user/{id}") User getUserById(@PathVariable("id")Long id); }
fallback = UserFeignClientFallback.class : 該類是當前接口的實現類 ,也是托底數據所在的處理類
3.托底實現
@Component public class UserFeignClientFallback implements UserFeignClient { @Override public User getUserById(Long id) { System.out.println("托底數據執行...."); return new User(-1L,"托底數據",""); } }
