簡介
最近都在弄微服務的東西,現在來記錄下收穫。我從一知半解到現在能從0搭建使用最大的感觸有兩點
1.微服務各大元件的版本很多,網上很多部落格內容不一定適合你的版本,很多時候苦苦琢磨都是無用功
2.網上部落格參差不齊,有些甚至錯誤的。更離譜的是,好的文章閱讀量除非高出天際,不然就都很低,比那些複製貼上,隨便應付的都低(這個搜尋推薦演算法不知道基於什麼的)
通過這段時間學習,我覺得最重要是從好的部落格入手,先不要著急怎麼元件怎麼使用,而是先了解元件的作用,大概的原理,然後才是使用,這樣搭建和嘗試的過程中才能更好的定位問題,最後再次回到原理和一些實際問題的處理(不知道實際問題怎樣的,直接搜那個元件的面試題往往效果最好)
接下來的內容,都以導航的形式展現給大家(畢竟優秀的輪子很多,直接看大佬寫的不香嘛),再順帶提些自己的理解
傳送門
更多微服務的介紹可點選下方連結
微服務介紹、Nginx導航、Nacos導航、Gateway導航、Ribbon導航、Feign導航、Sentinel導航
博主微服務git練手專案:https://github.com/NiceJason/SpringCloudDemo
Ribbon簡介
ribbon簡介:https://blog.csdn.net/f641385712/article/details/104761814
說到負載均衡,常指兩個地方:Ng負載均衡和服務負載均衡。服務負載均衡指SpringCloudGateWay閘道器開始,到裡面的各種Server服務,都是基於Ribbon進行負載均衡的。
SpringCloud下的Ribbon
參考資料:https://louluan.blog.csdn.net/article/details/83060310
文章講了Ribbon幾大核心元件的作用和負載均衡的過程,當然總的流程是這樣的,但是和具體的元件結合時候會有點變化,例如和Nacos結合時,Nacos並沒有實現自己的IPing,而是把這個定時檢測都去掉了,換成了定時重新整理服務列表(自身每10秒重新整理),外部Ribbon沒變,一樣是每30秒重新整理一次
在文章開頭也講了Feign和Ribbon結合,所以重試機制預設Feign是關閉的(具體程式碼裡可以看到),呼叫的是Ribbon。同理可以推測出,和Ribbon整合的元件(如SpringCloudGateaWay)他們的重試機制應該都是基於Ribbon,因此Ribbon的配置十分重要
Ribbon的重試機制
參考資料:https://blog.csdn.net/east123321/article/details/82385816(這篇文章的評論也能看看)
想要Ribbon開啟重試,需要匯入SpringRetry包,因為Ribbon重試先關的類和攔截器都依賴RetryTemplate.class,程式碼裡寫著ConditionOnClass(RetryTemplate.class)。
這個太重要了,不知道為什麼很多部落格都沒提及,沒有依賴此包Ribbon並不會報錯和提示,所以找了很久沒不知道什麼問題
<!--重試依賴-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
這裡的版本應該依賴於Springboot而不是自己去指定
ribbon:
ReadTimeout: 15000
ConnectTimeout: 5000
MaxAutoRetries: 1 #同一臺例項最大重試次數,不包括首次呼叫
MaxAutoRetriesNextServer: 1 #重試負載均衡其他的例項最大重試次數,不包括首次呼叫
OkToRetryOnAllOperations: false #是否所有操作都重試,改為true要注意介面是否實現了冪等性
Ribbon的配置
############## ribbon配置 ##############
#想要更好的理解Nacos和Ribbon的結合,關閉飢餓載入,打斷點
ribbon.eager-load.enabled=true
## 從註冊中心重新整理servelist的時間 預設30秒,單位ms
ribbon.ServerListRefreshInterval=15000
## 請求連線的超時時間 預設1秒,單位ms。更改這個值時,需要考慮熔斷時間是否要重新計算
ribbon.ConnectTimeout=1000
## 請求處理的超時時間 預設1秒,單位ms。更改這個值時,需要考慮熔斷時間是否要重新計算
ribbon.ReadTimeout=10000
#同一臺例項最大重試次數,不包括首次呼叫。更改這個值時,需要考慮熔斷時間是否要重新計算
ribbon.MaxAutoRetries=2
#重試負載均衡其他的例項最大重試次數,不包括首次呼叫。更改這個值時,需要考慮熔斷時間是否要重新計算
ribbon.MaxAutoRetriesNextServer=2
#是否所有操作都重試 可能存在冪等性問題,在冪等性未解決之前設定為false,只有get請求會進行重試
ribbon.OkToRetryOnAllOperations=false
@LoadBalance的使用
將@LoadBalance註解放在RestTemplate上便能賦予RestTemplate負載均衡的能力
1 @LoadBalanced
2 @Autowired
3 RestTemplate restTemplate;
為什麼這麼神奇,這其實涉及到Spring註解的使用,詳情看:https://fangshixiang.blog.csdn.net/article/details/100890879
@Qualifier+@Autowired可以載入指定型別的類,這樣在系統啟動的時候就可以獲得這部分特殊的類進行加強
我們可以學習這種設計模式,對一些老舊的工具類(自己建的或者第三方的)進行升級而不影響原來的業務邏輯
@LoadBalanced
的RestTemplate
只能書寫serviceId
而不能再寫IP地址/域名
去傳送請求了。若你的專案中兩種case都有需要,請定義多個RestTemplate
分別應對不同的使用場景~自定義Rule
1 /**
2 * @Author DiaoJianBin
3 * @Description Ribbon的自定義規則
4 * 仿照NacosRule進行書寫
5 * 如果直接加@Compoment,將會成為user-service裡的全域性規則
6 * 無論請求哪個服務,都會用此規則,這樣不好,所以在配置檔案中指定
7 * @Date 2021/3/10 14:51
8 */
9 public class CustomRuleA extends AbstractLoadBalancerRule {
10
11 @Autowired
12 private NacosDiscoveryProperties nacosDiscoveryProperties;
13 @Autowired
14 private NacosServiceManager nacosServiceManager;
15
16 @Override
17 public void initWithNiwsConfig(IClientConfig clientConfig) {
18 System.out.println("CustomRuleA初始化,這裡有各種配置資訊可以獲得,可以debug此處檢視clientConfig裡面的資訊");
19 }
20
21 @SneakyThrows
22 @Override
23 public Server choose(Object key) {
24
25 //獲取服務配置的叢集名
26 String clusterName = nacosDiscoveryProperties.getClusterName();
27 //當前的版本號 配置檔案配置的metadata資訊
28 String currentVersion = nacosDiscoveryProperties.getMetadata().get("version");
29 System.out.println("當前服務叢集名稱="+clusterName+" 版本號="+currentVersion);
30 //獲得當前服務分組
31 String group = nacosDiscoveryProperties.getGroup();
32 //獲取負載均衡器
33 ZoneAwareLoadBalancer baseLoadBalancer = (ZoneAwareLoadBalancer) getLoadBalancer();
34 //呼叫服務的名字
35 String invokedServerName = baseLoadBalancer.getName();
36 //獲取namingServer(包含nacos註冊發現相關api)
37 NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
38 //獲取被呼叫的服務的所有例項
39 List<Instance> invokedAllInstanceList = namingService.getAllInstances(invokedServerName,group);
40
41 Instance instance = null;
42 if(invokedAllInstanceList.size()>0){
43 //預設獲取最後一個
44 instance = invokedAllInstanceList.get(invokedAllInstanceList.size()-1);
45 System.out.println("CustomRuleA 選擇好服務的埠="+instance.getPort());
46 return new NacosServer(instance);
47 }
48
49 return null;
50 }
51 }
user-service的配置檔案
#指定當請求該服務時,所用的特定規則
blank-service.ribbon.NFLoadBalancerRuleClassName=com.nicebin.user.ribbon.rule.CustomRuleA
小結
本篇部落格講的都是比較零碎的Ribbon知識,具體的體系知識大家可以自己搜尋,基本都是大同小異。看完了再結合部落格進行補充也是不錯的。Ribbon作為微服務的核心,很多元件能跟其結合(如Feign,閘道器等等底層都是呼叫Ribbon),所以瞭解Ribbon大致的原理就能讓很多傳送問題有了解決的頭緒,希望能幫到大家啦。