負載均衡Ribbon《六》
RestTemplate簡介:
RestTemplate 是spring resources 中一個訪問第三方restful api介面的網路請求框架。resttemplate 的設計原則和其他spring template [jdbc template,jms template]類似,都是為執行復雜任務提供了一個具有預設行為的簡單方法。
RestTemplate是用來消費REST 服務的,所以RestTemplate的主要方法都與REST的http 協議的一些方法緊密相連,例如head,get,post,put,delete , options等方法,這些方法在RestTimplate類對應的方法為headForHeaders(),getForObject(),postForObject(),put(),delete()方法等。
例項:獲取https://www.baidu.com 的網頁html 程式碼:
@ApiOperation("獲取百度html 網頁程式碼")
@GetMapping("baidu")
public String getBaidu(){
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject("https://www.baidu.com/",String.class);
}
RestTemplate支援常見的http 協議的請求方法,例如post ,put ,delete 等,所以用RestTimplate 很容易構建restful api 。RestTemplate支援xml ,json 資料格式,預設實現了序列化,可以自動將json 字串轉換為實體。例項:
UserInfo user = restTimplate.getForObject("https://xxx.xxx.com/",User.class);
Ribbon 簡介:
負載均衡是指將負載分攤到多個執行單元上,常見的負載均衡有兩種方式:
一種是獨立程序單元,通過附加均衡策略,將請求轉發到不同的執行單元上,例如ngnix 。
另一種是將負載均衡邏輯以程式碼的形式封裝到服務消費者的客戶端上,服務消費者客戶端維護了一份提供者的資訊列表,有了資訊列表,通過負載均衡策略將請求分攤給多個服務提供者,從而達到了負載均衡的目的。
Ribbon 是netflix 公司開源的一個負載均衡的元件,它屬於第二種方式,是將負載均衡邏輯封裝到客戶端中,並且執行在客戶端的程序裡。ribbon 是一個經過了雲端測試的IPC庫,可以很好的控制http 和tcp 客戶端的負載均衡行為。
在spring cloud 構建的微服務系統種,ribbon作為服務消費者的負載均衡器,有兩種使用方式:
1.和RestTemplate 相結合
2.和feign 相結合。feign 已經預設集成了ribbon。
ribbon-loadbalancer: | 可以獨立使用或與其他模組一起使用的負載均衡器API |
ribbon-eureka: | ribbon 結合eureka 客戶端的API,為負載均衡提供動態服務註冊列表資訊 |
ribbon-core | ribbon 的核心API |
依次啟動:
java -jar eureka.server.jar --spring.profiles.active=peer1
java -jar eureka.server.jar --spring.profiles.active=peer2
啟動eureka client ----啟動 eureka-ribbon-client
訪問:http://localhost:8764/hi?name=jie
LoadBalancerClient 簡介:
負載均衡的核心類為LoanBalancerClient ,LoanBalancerClient可以獲取負載均衡的服務提供者的例項資訊。LoanBalancerClient是從eureka client 獲取服務註冊列表資訊的,並將服務註冊列表資訊快取了一份。再LoanBalancerClient 呼叫choose()方法的時候,根據負載均衡選擇一個服務例項的資訊,從而進行了負載均衡。LoanBalancerClient 也可以不從eureka client 獲取註冊列表資訊,但是需要自己維護一份服務註冊列表資訊。
choose()方法用於選擇具體服務例項。該方法通過getServer()方法去獲取例項,最終交給ILoadBalancer類去選擇服務例項。
ILoadBalancer 在ribbon-loadbalancer的jar 包下,ILoadBalancer 是一個介面,該介面定義了一系列例項負載均衡的方法:
public interface ILoadBalancer {
void addServers(List<Server> var1);
Server chooseServer(Object var1);
void markServerDown(Server var1);
/** @deprecated */
@Deprecated
List<Server> getServerList(boolean var1);
List<Server> getReachableServers();
cList<Server> getAllServers();
}
addServer() | 新增一個server 方法 |
chooseServer() | 根據key去獲取server |
markServerDown | 標記某個服務下線 |
getReachableServers | 獲取可用的server集合 |
getAllServers | 獲取所有的server集合 |
DynamicServerListLoadBalancer 需要配置 IClientConfig,IRule,IPing,ServerList,ServerListFilter和 ILoadBalancer。
IClientConfig 用於配置負載均衡的客戶端,IClientConfig的預設實現類為DefaultClientConfigImpl.
IRule用於配置負載均衡的策略,有三個方法,其中choose()是根據key來獲取server例項,setLoadBalancer()方法和getLoadBalancer()是用來設定和獲取ILoadBalancer的。
IRule 有很多預設的實現類,這些實現類根據不同的演算法和邏輯來處理負載均衡的策略。IRule的預設實現類有以下7種:
BestAvailableRule | 選擇最小請求數 |
ClientConfigEnabledRoundRobinRule | 輪詢 |
RandomRule | 隨機選擇一個server |
RoundRobinRule | 輪詢選擇server |
RetryRule | 根據輪詢的方式重試 |
weightedResponseTimeRule | 根據響應時間去分配一個weight,weight越低,被選擇的可能性就越低 |
ZoneAvoidanceRule | 根據server的zone區域和可用性來輪詢選擇 |
IPing 的實現類有PingUrl,PingConstant,NoOpPing, DummyPing 和NIWSDiscoveryPing。
PingUrl | 真實的去ping 某個url ,判斷其是否可用 |
PingConstant | 固定返回某服務是否可用,預設返回true,即可用 |
NoOpPing | 不去ping,直接返回true,即可用 |
DummyPing | 直接返回true,並實現了initWithNiwsConfig方法 |
NIWSDiscoveryPing | 根據DiscoveryEnabledServer 的InstanceInfo 的InstanceStatus去判斷,如果InstanceStatus.UP ,則可用,否則不可用。 |
蓋棺定論:
ribbon 的負載均衡主要是通過LoadBalancerClient 來實現的,而LoadBalancerClient 具體交給了ILoadBalancer來處理,ILoadBalancer 同故宮配置IRule,IPing 等,而eureka client 獲取註冊列表的資訊,預設每10秒向 eureka client 傳送一次ping,進而檢查是否需要更新服務的註冊列表資訊,最後,在得到服務註冊列表資訊後,ILoadBalancer 根據IRule的策略進行負載均衡。
而RestTemplate 加上@LoadBalancer 註解後,在遠端排程時能夠負載均衡,主要是維護了一個被@LoadBalance註解的RestTemplate列表,並給該列表種的RestTemplate物件添加了攔截器,在攔截器的方法中,將遠端排程方法交給了ribbon的負載均衡器LoadBalancerClient 去處理,從而實現了負載均衡的目的。