一、Eureka
1、服務(wù)提供者與消費(fèi)者
服務(wù)提供者:一次業(yè)務(wù)中,被其它微服務(wù)調(diào)用的服務(wù)。(提供接口給其它微服務(wù))
服務(wù)消費(fèi)者:一次業(yè)務(wù)中,調(diào)用其它微服務(wù)的服務(wù)。(調(diào)用其它微服務(wù)提供的接口)
很明顯,這是一個(gè)相對的概念。
2、Eureka原理分析
上一篇中,遠(yuǎn)程調(diào)用時(shí),url參數(shù)是寫死在代碼中的,而不同的測試、生產(chǎn)、開發(fā)環(huán)境IP不同,有集群時(shí),端口也不能固定。
很明顯,硬編碼肯定行不通。Eureka就是來解決這個(gè)問題的。
- 每個(gè)服務(wù)啟動的時(shí)候,將自己的信息注冊到eureka中
- 某個(gè)服務(wù)需要調(diào)用其他服務(wù)時(shí),向eureka拉取對應(yīng)的服務(wù)信息
- 負(fù)載均衡到其中一臺(如圖中的localhost:8081)
- 進(jìn)行遠(yuǎn)程調(diào)用
- 服務(wù)實(shí)例向eureka心跳續(xù)約,每30秒一次,eureka監(jiān)控到某個(gè)服務(wù)實(shí)例不再心跳時(shí),就從其注冊信息中剔除這條信息。服務(wù)消費(fèi)者拉取時(shí)當(dāng)然也就拉取不到這個(gè)宕掉的服務(wù)實(shí)例
- 新啟動一個(gè)服務(wù),服務(wù)信息注冊到了eureka中…以此類推
接下來開始搭建Eureka,并進(jìn)行服務(wù)注冊和服務(wù)發(fā)現(xiàn)
3、搭建Eureka
- 在父工程下新建eureka模塊,選擇Maven,點(diǎn)擊Finish
- 給該模塊引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--版本在父工程中統(tǒng)一管理,這里不用寫-->
- 編寫啟動類,添加@EnableEurekaServer注解(自動裝配的開關(guān))
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
- 添加application.yaml文件
server:
port: 10086 # 服務(wù)端口
spring:
application:
name: eurekaserver # eureka的服務(wù)名稱,eureka自身也是個(gè)微服務(wù),也要注冊自己的信息到eureka注冊中心
eureka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
# eureka自身也是個(gè)微服務(wù),也要注冊自己的信息到eureka注冊中心
# 王思聰住萬達(dá)酒店也得身份證登記一下,雖然那就是他家的產(chǎn)業(yè)
- 啟動eureka模塊
- 注冊成功
4、服務(wù)注冊
接下來將user和order服務(wù)注冊到eureka中:
- 在user模塊的pom文件中引入eureka客戶端依賴
<!--eureka客戶端依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 在application.yaml文件中增加注冊中心地址的配置
server:
port: 8081
spring:
application:
name: userservice
eyreka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
- 重啟user模塊(order模塊操作步驟相同),注冊成功
5、模擬多服務(wù)實(shí)例啟動
上面完成的注冊都是單服務(wù)實(shí)例的,接下來在IDEA中模擬啟動多個(gè)服務(wù)實(shí)例:
- 右鍵選擇拷貝
- -Dserver.port覆蓋yaml文件中的端口,從而換個(gè)新端口
- 啟動這個(gè)新服務(wù)實(shí)例,注冊成功
6、服務(wù)的發(fā)現(xiàn)
接下來實(shí)現(xiàn):在order服務(wù)中完成服務(wù)信息的拉取,然后通過負(fù)載均衡挑選一個(gè)user服務(wù),實(shí)現(xiàn)遠(yuǎn)程調(diào)用
服務(wù)拉取是基于服務(wù)名稱獲取服務(wù)列表,然后在對服務(wù)列表做負(fù)載均衡
- 修改order代碼,將服務(wù)IP和端口改為服務(wù)名
String url ="http://userservice/user/" + order.getUserId();
- 在order啟動類OrderApplication中的RestTemplate添加負(fù)載均衡注解
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
- 分別調(diào)用order接口兩次,傳參101和102,看它遠(yuǎn)程調(diào)用了哪個(gè)user服務(wù)實(shí)例
- 可以看到兩個(gè)服務(wù)實(shí)例均有對應(yīng)的日志,成功!
二、Ribbon
1、負(fù)載均衡的原理
分析:
我在瀏覽器中直接訪問http://userservice/user/,訪問失敗,這是因?yàn)閡serservice既不是可用域名,也不是IP。那order調(diào)用到user服務(wù)的過程中經(jīng)歷了什么呢?
- order發(fā)起請求
- Ribbon攔截請求,拿到服務(wù)名,向eureka拉取信息
- eureka返回服務(wù)列表信息給Ribbon
- Ribbon將請求輪詢到相應(yīng)的服務(wù)地址上去
具體信息,在源碼中打斷點(diǎn)來調(diào)試看看。
2、源碼分析
@LoadBalanced注解,就標(biāo)識了調(diào)用方當(dāng)前這個(gè)restTemplate這個(gè)對象發(fā)起的請求,要被Ribbon攔截
LoadBalancerInterceptor實(shí)現(xiàn)了ClientHttpRequestInterceptor接口:
在LoadBalancerInterceptor接口重寫的intercent方法上打斷點(diǎn),調(diào)用order接口(中途會對user服務(wù)發(fā)起遠(yuǎn)程調(diào)用),斷點(diǎn)進(jìn)入到了這里:
繼續(xù)往下,看到了Ribbon對象
繼續(xù)往下:成功從eureka拿到服務(wù)列表信息
繼續(xù)往下調(diào)試,看到了IRule這個(gè)接口,決定了負(fù)載均衡的策略
以上,調(diào)用接口http://localhost:8080/order/102后發(fā)生的事情如圖:
- 接口中途通過restTemple遠(yuǎn)程調(diào)用http://userservice/user/1
- 被負(fù)載均衡攔截器攔截
- 獲取url中的服務(wù)id,即userservice
- 動態(tài)服務(wù)列表均衡器向eureka拉取userservice的信息
- eureka返回服務(wù)列表給DynamicServiceListLoadBalancer
- 通過IRule挑選出某個(gè)服務(wù),返回給RibbonLoadBalancerClient
- 請求被轉(zhuǎn)發(fā)到了某個(gè)一具體的實(shí)例上
3、負(fù)載均衡策略
Ribbon的負(fù)載均衡策略是由IRule接口來定義的,它的每一個(gè)子接口就是一種策略。
具體的含義為:
以上策略中,Ribbon默認(rèn)的是ZoneAvoidanceRule。想修改負(fù)載均衡策略有這兩種方法:
代碼方式:在order-service中的OrderApplication類中,定義一個(gè)新的IRule:
@Bean
public IRule randomRule(){
return new RandomRule(); //改為隨機(jī)
}
配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改規(guī)則
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #負(fù)載均衡規(guī)則
此時(shí),多次調(diào)用order接口(代碼中途遠(yuǎn)程調(diào)用user):
http://localhost:8080/order/102
可以看到轉(zhuǎn)發(fā)到user實(shí)例上的請求不再有明顯規(guī)律。
4、饑餓加載
重啟order服務(wù),然后兩次訪問order接口,發(fā)現(xiàn)耗時(shí)相差巨大:
Ribbon默認(rèn)是采用懶加載,即第一次訪問時(shí)才會去創(chuàng)建LoadBalanceClient,因此請求時(shí)間會很長。
饑餓加載則會在項(xiàng)目啟動時(shí)創(chuàng)建,降低第一次訪問的耗時(shí),通過下配置開啟饑餓加載:文章來源:http://www.zghlxwxcb.cn/news/detail-455838.html
ribbon:
eager-load:
enabled: true #開啟饑餓加載
clients: userservice # 指定對userservice這個(gè)服務(wù)饑餓加載
# clients為list,可添加多個(gè)
文章來源地址http://www.zghlxwxcb.cn/news/detail-455838.html
到了這里,關(guān)于【SpringCloud】二、服務(wù)注冊發(fā)現(xiàn)Eureka與負(fù)載均衡Ribbon的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!