SpringCloud-服務(wù)間通信方式
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
? 作者?|??山丘i?
來源 |? urlify.cn/FNbUvi
66套java從入門到精通實(shí)戰(zhàn)課程分享
接下來在整個(gè)微服務(wù)架構(gòu)中,我們比較關(guān)心的就是服務(wù)間的服務(wù)改如何調(diào)用,有哪些調(diào)用方式?

總結(jié):
在springcloud中服務(wù)間調(diào)用方式主要是使用 http restful方式進(jìn)行服務(wù)間調(diào)用
1. 1基于RestTemplate的服務(wù)調(diào)用
在上面的基礎(chǔ)上,使用的是consul注冊,pom.xml文件
"1.0"?encoding="UTF-8"?>
"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">
????4.0.0
????
????????org.springframework.boot
????????spring-boot-starter-parent
????????2.2.5.RELEASE
???????? ?
????
????com.md
????04-products9998
????0.0.1-SNAPSHOT
????04-products9998
????Demo?project?for?Spring?Boot
????
????????1.8
????????Hoxton.SR6
????
????
????????
????????????org.springframework.boot
????????????spring-boot-starter-web
????????
????????
????????????org.springframework.boot
????????????spring-boot-devtools
????????????runtime
????????????true
????????
????????
????????????org.projectlombok
????????????lombok
????????????true
????????
????????
????????????org.springframework.boot
????????????spring-boot-starter-test
????????????test
????????
????????
????????
????????????org.springframework.cloud
????????????spring-cloud-starter-consul-discovery
????????
????????
????????
????????????org.springframework.boot
????????????spring-boot-starter-actuator
????????
????
????
????
????????
????????????
????????????????org.springframework.cloud
????????????????spring-cloud-dependencies
????????????????${spring-cloud.version}
????????????????<type>pomtype>
????????????????import
????????????
????????
????
????
????????
????????????
????????????????org.springframework.boot
????????????????spring-boot-maven-plugin
????????????
????????
????
1. 說明
spring框架提供的RestTemplate類可用于在應(yīng)用中調(diào)用rest服務(wù),它簡化了與http服務(wù)的通信方式,統(tǒng)一了RESTful的標(biāo)準(zhǔn),封裝了http鏈接, 我們只需要傳入url及返回值類型即可。相較于之前常用的HttpClient,RestTemplate是一種更優(yōu)雅的調(diào)用RESTful服務(wù)的方式。
1.2RestTemplate 服務(wù)調(diào)用
創(chuàng)建兩個(gè)服務(wù)并注冊到consul注冊中心中
users 代表用戶服務(wù) 端口為 9999
products 代表商品服務(wù) 端口為 9998
`注意:這里服務(wù)僅僅用來測試,沒有實(shí)際業(yè)務(wù)意義


1.3 在商品服務(wù)中提供服務(wù)方法
@RestController
@Slf4j
public?class?ProductController?{
????@Value("${server.port}")
????private?int?port;
????@GetMapping("/product/findAll")
????public?Map?findAll(){
????????log.info("商品服務(wù)查詢所有調(diào)用成功,當(dāng)前服務(wù)端口:[{}]",port);
????????Map?map?=?new?HashMap();
????????map.put("msg","服務(wù)調(diào)用成功,服務(wù)提供端口為:?"+port);
????????map.put("status",true);
????????return?map;
????}
}

1.4在用戶服務(wù)中使用restTemplate進(jìn)行調(diào)用

@RestController
@Slf4j
public?class?UserController?{
????@GetMapping("/user/findAll")
????public?String?findAll(){
????????log.info("調(diào)用用戶服務(wù)...");
????????//1.?使用restTemplate調(diào)用商品服務(wù)
????????RestTemplate?restTemplate?=?new?RestTemplate();
????????//?get請求getxxx,post請求postxxx
????????//?參數(shù)1:請求路徑,參數(shù)2:返回的類型是String的
????????String?forObject?=?restTemplate.getForObject("http://localhost:9998/product/findAll",?
?????????????????????????????????????????????????????String.class);
????????return?forObject;
????}
}
1.5啟動(dòng)服務(wù)


1.6測試服務(wù)調(diào)用
瀏覽器訪問用戶服務(wù)?http://localhost:9999/user/findAll


1.7 總結(jié)
rest Template是直接基于服務(wù)地址調(diào)用沒有在服務(wù)注冊中心獲取服務(wù),也沒有辦法完成服務(wù)的負(fù)載均衡如果需要實(shí)現(xiàn)服務(wù)的負(fù)載均衡需要自己書寫服務(wù)負(fù)載均衡策略。
restTemplate直接調(diào)用存在問題1.直接使用restTemplate方式調(diào)用沒有經(jīng)過服務(wù)注冊中心獲取服務(wù)地址,代碼寫死不利于維護(hù),當(dāng)服務(wù)宕機(jī)時(shí)不能高效剔除
2.調(diào)用服務(wù)時(shí)沒有負(fù)載均衡需要自己實(shí)現(xiàn)負(fù)載均衡策略
2. 基于Ribbon的服務(wù)調(diào)用
2.0說明
官方網(wǎng)址:?https://github.com/Netflix/ribbon
Spring Cloud Ribbon是一個(gè)基于HTTP和TCP的客戶端負(fù)載均衡工具,它基于Netflix Ribbon實(shí)現(xiàn)。通過Spring Cloud的封裝,可以讓我們輕松地將面向服務(wù)的REST模版請求自動(dòng)轉(zhuǎn)換成客戶端負(fù)載均衡的服務(wù)調(diào)用。
再創(chuàng)建一個(gè)服務(wù)類,和上面的服務(wù)類一樣,只有端口不同
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?findAll(){
????????log.info("商品服務(wù)查詢所有調(diào)用成功,當(dāng)前服務(wù)端口:[{}]",port);
????????Map?map?=?new?HashMap();
????????map.put("msg","服務(wù)調(diào)用成功,服務(wù)提供端口為:?"+port);
????????map.put("status",true);
????????return?map;
????}
}
2.1Ribbon 服務(wù)調(diào)用
#?1.項(xiàng)目中引入依賴
-?說明:?
?1.如果使用的是eureka?client?和?consul?client,無須引入依賴,因?yàn)樵趀ureka,consul中默認(rèn)集成了ribbon組件
?2.如果使用的client中沒有ribbon依賴需要顯式引入如下依賴
??org.springframework.cloud
??spring-cloud-starter-netflix-ribbon
#?2.查看consul?client中依賴的ribbon

#?3.使用restTemplate?+?ribbon進(jìn)行服務(wù)調(diào)用
-?使用discovery?client??進(jìn)行客戶端調(diào)用
-?使用loadBalanceClient?進(jìn)行客戶端調(diào)用
-?使用@loadBalanced?????進(jìn)行客戶端調(diào)用
#?3.1?使用discovery?Client形式調(diào)用
@Autowired
private?DiscoveryClient?discoveryClient;
//獲取服務(wù)列表,返回全部的,服務(wù)id,上面的products
List?products?=?discoveryClient.getInstances("服務(wù)ID");
for?(ServiceInstance?product?:?products)?{
??log.info("服務(wù)主機(jī):[{}]",product.getHost());
??log.info("服務(wù)端口:[{}]",product.getPort());
??log.info("服務(wù)地址:[{}]",product.getUri());
??log.info("====================================");
}
#?3.2?使用loadBalance?Client形式調(diào)用
@Autowired
private?LoadBalancerClient?loadBalancerClient;
//根據(jù)負(fù)載均衡策略選取某一個(gè)服務(wù)調(diào)用,服務(wù)id=products
ServiceInstance?product?=?loadBalancerClient.choose("服務(wù)ID");//地址??默認(rèn)輪詢策略
log.info("服務(wù)主機(jī):[{}]",product.getHost());
log.info("服務(wù)端口:[{}]",product.getPort());
log.info("服務(wù)地址:[{}]",product.getUri());
#?3.3?使用@loadBalanced(常用)
//1.整合restTemplate?+?ribbon
@Configuration
public?class?RestTemplateConfig?{
????//?在工廠中創(chuàng)建一個(gè)restTemplate對象
????@Bean
????//?加上這個(gè)注解代表當(dāng)前的restTemplate對象帶有ribbon負(fù)載均衡
????@LoadBalanced
????public?RestTemplate?getRestTemplate(){
????????return?new?RestTemplate();
????}
}
//2.調(diào)用controller服務(wù)位置注入RestTemplate
//?此時(shí)的restTemplate就具有了負(fù)載均衡的功能
@Autowired
private?RestTemplate?restTemplate;
//3.調(diào)用
@RestController
@Slf4j
public?class?UserController?{
????@Autowired
?private?RestTemplate?restTemplate;
????
????@GetMapping("/user/findAll")
????public?String?findAll(){
????????//?服務(wù)id就是在配置文件中的當(dāng)前服務(wù)名products
????????String?forObject?=?restTemplate.getForObject("http://服務(wù)ID/product/findAll",?
?????????????????????????????????????????????????????String.class);
????????return?forObject;
????}
}
默認(rèn)的輪訓(xùn)策略,也就是當(dāng)前訪問的9998,之后是9997,循環(huán)訪問
2.2Ribbon負(fù)載均衡策略
ribbon負(fù)載均衡算法
RoundRobinRule 輪訓(xùn)策略 按順序循環(huán)選擇 Server
RandomRule 隨機(jī)策略 隨機(jī)選擇 Server
AvailabilityFilteringRule 可用過濾策略
`會(huì)先過濾由于多次訪問故障而處于斷路器跳閘狀態(tài)的服務(wù),還有并發(fā)的連接數(shù)量超過閾值的服務(wù),然后對剩余的服務(wù)列表按照輪詢策略進(jìn)行訪問WeightedResponseTimeRule 響應(yīng)時(shí)間加權(quán)策略
`根據(jù)平均響應(yīng)的時(shí)間計(jì)算所有服務(wù)的權(quán)重,響應(yīng)時(shí)間越快服務(wù)權(quán)重越大被選中的概率越高,剛啟動(dòng)時(shí)如果統(tǒng)計(jì)信息不足,則使用RoundRobinRule策略,等統(tǒng)計(jì)信息足夠會(huì)切換到RetryRule 重試策略
`先按照RoundRobinRule的策略獲取服務(wù),如果獲取失敗則在制定時(shí)間內(nèi)進(jìn)行重試,獲取可用的服務(wù)。BestAviableRule 最低并發(fā)策略
`會(huì)先過濾掉由于多次訪問故障而處于斷路器跳閘狀態(tài)的服務(wù),然后選擇一個(gè)并發(fā)量最小的服務(wù)

2.3修改服務(wù)的默認(rèn)負(fù)載均衡策略
#?1.修改服務(wù)默認(rèn)隨機(jī)策略
-?服務(wù)id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
?`下面的products為服務(wù)的唯一標(biāo)識(shí)
products.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

2.4Ribbon停止維護(hù)
#?1.官方停止維護(hù)說明
-?https://github.com/Netflix/ribbon

粉絲福利:Java從入門到入土學(xué)習(xí)路線圖
???

?長按上方微信二維碼?2 秒
感謝點(diǎn)贊支持下哈?
