接下來在整個微服務架構中,咱們比較關心的就是服務間的服務改如何調用,有哪些調用方式?java
總結:
在springcloud中服務間調用方式主要是使用 http restful方式進行服務間調用
git
在上面的基礎上,使用的是consul註冊,pom.xml文件github
<?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.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.md</groupId> <artifactId>04-products9998</artifactId> <version>0.0.1-SNAPSHOT</version> <name>04-products9998</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR6</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--引入consul依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <!-- 這個包是用作健康度監控的--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <!--全局管理springcloud版本,並不會引入具體依賴--> <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>
@RestController @Slf4j public class ProductController { @Value("${server.port}") private int port; @GetMapping("/product/findAll") public Map<String,Object> findAll(){ log.info("商品服務查詢全部調用成功,當前服務端口:[{}]",port); Map<String, Object> map = new HashMap<String,Object>(); map.put("msg","服務調用成功,服務提供端口爲: "+port); map.put("status",true); return map; } }
@RestController @Slf4j public class UserController { @GetMapping("/user/findAll") public String findAll(){ log.info("調用用戶服務..."); //1. 使用restTemplate調用商品服務 RestTemplate restTemplate = new RestTemplate(); // get請求getxxx,post請求postxxx // 參數1:請求路徑,參數2:返回的類型是String的 String forObject = restTemplate.getForObject("http://localhost:9998/product/findAll", String.class); return forObject; } }
再建立一個服務類,和上面的服務類同樣,只有端口不一樣web
server.port=9997 spring.application.name=products spring.cloud.consul.port=8500 spring.cloud.consul.host=localhost
其餘同樣算法
@RestController @Slf4j public class ProductController { @Value("${server.port}") private int port; @GetMapping("/product/findAll") public Map<String,Object> findAll(){ log.info("商品服務查詢全部調用成功,當前服務端口:[{}]",port); Map<String, Object> map = new HashMap<String,Object>(); map.put("msg","服務調用成功,服務提供端口爲: "+port); map.put("status",true); return map; } }
# 1.項目中引入依賴 - 說明: 1.若是使用的是eureka client 和 consul client,無須引入依賴,由於在eureka,consul中默認集成了ribbon組件 2.若是使用的client中沒有ribbon依賴須要顯式引入以下依賴
<!--引入ribbon依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
# 2.查看consul client中依賴的ribbon
# 3.使用restTemplate + ribbon進行服務調用 - 使用discovery client 進行客戶端調用 - 使用loadBalanceClient 進行客戶端調用 - 使用@loadBalanced 進行客戶端調用
# 3.1 使用discovery Client形式調用
@Autowired private DiscoveryClient discoveryClient; //獲取服務列表,返回所有的,服務id,上面的products List<ServiceInstance> products = discoveryClient.getInstances("服務ID"); for (ServiceInstance product : products) { log.info("服務主機:[{}]",product.getHost()); log.info("服務端口:[{}]",product.getPort()); log.info("服務地址:[{}]",product.getUri()); log.info("===================================="); }
# 3.2 使用loadBalance Client形式調用
@Autowired private LoadBalancerClient loadBalancerClient; //根據負載均衡策略選取某一個服務調用,服務id=products ServiceInstance product = loadBalancerClient.choose("服務ID");//地址 默認輪詢策略 log.info("服務主機:[{}]",product.getHost()); log.info("服務端口:[{}]",product.getPort()); log.info("服務地址:[{}]",product.getUri());
# 3.3 使用@loadBalanced(經常使用)
//1.整合restTemplate + ribbon @Configuration public class RestTemplateConfig { // 在工廠中建立一個restTemplate對象 @Bean // 加上這個註解表明當前的restTemplate對象帶有ribbon負載均衡 @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } } //2.調用controller服務位置注入RestTemplate // 此時的restTemplate就具備了負載均衡的功能 @Autowired private RestTemplate restTemplate; //3.調用 @RestController @Slf4j public class UserController { @Autowired private RestTemplate restTemplate; @GetMapping("/user/findAll") public String findAll(){ // 服務id就是在配置文件中的當前服務名products String forObject = restTemplate.getForObject("http://服務ID/product/findAll", String.class); return forObject; } }
默認的輪訓策略,也就是當前訪問的9998,以後是9997,循環訪問spring
ribbon負載均衡算法apache
RoundRobinRule 輪訓策略 按順序循環選擇 Server瀏覽器
RandomRule 隨機策略 隨機選擇 Serverrestful
AvailabilityFilteringRule 可用過濾策略
`會先過濾因爲屢次訪問故障而處於斷路器跳閘狀態的服務,還有併發的鏈接數量超過閾值的服務,而後對剩餘的服務列表按照輪詢策略進行訪問markdown
WeightedResponseTimeRule 響應時間加權策略
`根據平均響應的時間計算全部服務的權重,響應時間越快服務權重越大被選中的機率越高,剛啓動時若是統計信息不足,則使用RoundRobinRule策略,等統計信息足夠會切換到
RetryRule 重試策略
`先按照RoundRobinRule的策略獲取服務,若是獲取失敗則在制定時間內進行重試,獲取可用的服務。
BestAviableRule 最低併發策略
`會先過濾掉因爲屢次訪問故障而處於斷路器跳閘狀態的服務,而後選擇一個併發量最小的服務
# 1.修改服務默認隨機策略 - 服務id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule `下面的products爲服務的惟一標識
products.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
# 1.官方中止維護說明 - https://github.com/Netflix/ribbon