SpringCloud微服務基礎2:Robbin負載均衡
spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。它是一個基於HTTP和TCP的客戶端負載均衡器。它可以通過在客戶端中配置ribbonServerList來設定服務端列表去輪詢訪問以達到均衡負載的作用。
當Ribbon與Eureka聯合使用時,ribbonServerList會被DiscoveryEnabledNIWSServerList重寫,擴充套件成從Eureka註冊中心中獲取服務例項列表。同時它也會用NIWSDiscoveryPing來取代IPing,它將職責委託給Eureka來確定服務端是否已經啟動。
而當Ribbon與Consul聯合使用時,ribbonServerList會被ConsulServerList來擴充套件成從Consul獲取服務例項列表。同時由ConsulPing來作為IPing介面的實現。
我們在使用Spring Cloud Ribbon的時候,不論是與Eureka還是Consul結合,都會在引入Spring Cloud Eureka或Spring Cloud Consul依賴的時候通過自動化配置來載入上述所說的配置內容,所以我們可以快速在Spring Cloud中實現服務間呼叫的負載均衡。
我們這裡的例子講解時按照SpringCloud微服務基礎1中高可用基礎上繼續使用的。因為Eureka中已經集成了Ribbon,所以我們無需引入新的依賴。
1、開啟負載均衡Ribbon
1.1、消費者上配置@LoadBalanced
在RestTemplate的配置方法上新增@LoadBalanced
註解
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(new OkHttp3ClientHttpRequestFactory()); }
1.2、消費者上修改呼叫方式
修改呼叫方式,不再手動獲取ip和埠,而是直接通過服務名稱呼叫:
@Service public class UserService { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; public List<User> queryUserByIds(List<Long> ids) { List<User> users = new ArrayList<>(); // 地址直接寫服務名稱即可 String baseUrl = "http://user-service/user/"; ids.forEach(id -> { // 我們測試多次查詢, users.add(this.restTemplate.getForObject(baseUrl + id, User.class)); // 每次間隔500毫秒 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } }); return users; } }
2、負載均衡策略
Robbin的負載均衡策略都是在介面IRule上。
格式是:{服務名稱}.ribbon.NFLoadBalancerRuleClassName
,值就是IRule的實現類 。並且springboot提供了配置負載均衡策略的:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
3、Ribbon重試機制
Eureka的服務治理強調了CAP原則中的AP,即可用性和可靠性。它與Zookeeper這一類強調CP(一致性,可靠性)的服務治理框架最大的區別在於:Eureka為了實現更高的服務可用性,犧牲了一定的一致性,極端情況下它寧願接收故障例項也不願丟掉健康例項,正如我們上面所說的自我保護機制。
因此Spring Cloud 整合了Spring Retry 來增強RestTemplate的重試能力,當一次服務呼叫失敗後,不會立即丟擲一次,而是再次重試另一個服務。只需要簡單配置即可實現Ribbon的重試:
spring:
cloud:
loadbalancer:
retry:
enabled: true # 開啟Spring Cloud的重試功能
user-service:
ribbon:
ConnectTimeout: 250 # Ribbon的連線超時時間
ReadTimeout: 1000 # Ribbon的資料讀取超時時間
OkToRetryOnAllOperations: true # 是否對所有操作都進行重試
MaxAutoRetriesNextServer: 1 # 切換例項的重試次數
MaxAutoRetries: 1 # 對當前例項的重試次數
根據如上application.yml配置,當訪問到某個服務超時後,它會再次嘗試訪問下一個服務例項,如果不行就再換一個例項,如果不行,則返回失敗。切換次數取決於MaxAutoRetriesNextServer引數的值。
引入spring-retry依賴
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>