如何在客戶端實現服務的負載均衡
這時,就需要在客戶端實現服務的負載均衡。而在Spring Cloud中推薦使用Ribbon來實現負載均衡。
1、Ribbon簡介
Ribbon是Netflix發布的負載均衡器。它有助于控制HTTP和TCP客戶端的行為。為Ribbon配置服務提供者地址列表后, Ribbon就可基于某種負載均衡算法,自動地幫助服務消費者去請求。Ribbon默認為我們提供了很多的負載均衡算法,例如輪詢、隨機等。當然,我們也可為 Ribbon實現自定義的負載均衡算法。
2、架構

3、開始使用Ribbon
3.1. 為microservice order增加ribbon依賴

其實,該依賴是可以省略的,因為spring-cloud-starter-netflix-eureka-client中已經包含了spring-cloud-starter-netflix-ribbon:

3.2. 為RestTemplate設置@LoadBalanced注解
@SpringBootApplication@EnableEurekaClient@EnableFeignClientspublic class OrderApp { public static void main(String[] args) { SpringApplication.run(OrderApp.class, args); } @Bean @LoadBalanced //使用負載均衡 public RestTemplate restTemplate() { return new RestTemplate(); }}
3.3. 改造ItemService的實現
@Servicepublic class ItemService { // Spring框架對RESTful方式的http請求做了封裝,來簡化操作 @Autowired private RestTemplate restTemplate; public Item queryItemById(Long id) { // 該方法走eureka注冊中心調用(去注冊中心根據app-item查找服務,這種方式必須先開啟負載均衡@LoadBalanced) String itemUrl = "http://app-item/item/{id}"; Item result = restTemplate.getForObject(itemUrl, Item.class, id); System.out.println("訂單系統調用商品服務,result:" + result); return result; }}
可以發現,實現更加簡化了。
這種方式關鍵在于獲取RestTemplat對象時要加上@LosdBalanced注解,否則restTemplate.getFor Object方法會報java.net.UnknownHostException: app-item,而前面一種方式是手動指定了獲取的服務實例,不需要加此注解。
提示: 如果這里使用了@FeignClient完成的Restful的調用同樣也適用。
3.4. 重啟訂單服務進行測試
測試結果:

3.5. 測試負載均衡
測試方法:
第一步,啟動2個microservice-item服務(多個也可以):

第二步,導入測試依賴,編寫單元測試用例:
第三步,編寫測試用例:
@RunWith(SpringJUnit4ClassRunner.class)@SpringBootTest@Import(OrderApp.class)public class ItemServiceTest { @Autowired private LoadBalancerClient loadBalancerClient;//自動注入 @Test public void test() { String serviceId = "app-item"; for (int i = 0; i < 100; i++) { ServiceInstance serviceInstance = this.loadBalancerClient.choose(serviceId); System.out.println("第" + (i + 1) + "次:" + serviceInstance.getHost() + ": " + serviceInstance.getPort()); } }}
4、設置負載均衡策略
只需要在配置文件中添加配置
serviceId.ribbon.NFLoadBalancerRuleClassName=自定義的負載均衡策略類,
例如在order微服務的yml配置文件中添加:
app-item: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
其中app-item是要訪問的服務id。
測試:
第1次:127.0.0.1: 8081
第2次:127.0.0.1: 9081
第3次:127.0.0.1: 9081
第4次:127.0.0.1: 8081
第5次:127.0.0.1: 9081
第6次:127.0.0.1: 8081
第7次:127.0.0.1: 9081
第8次:127.0.0.1: 9081
第9次:127.0.0.1: 8081
第10次:127.0.0.1: 8081
...
5、其它策略
接口:com.netflix.loadbalancer.IRule,其實現類:
策略描述:
AbstractLoadBalancerRule
負載均衡的抽象類,負責獲得負載均衡器并保存在內部,通過負載均衡器維護的信息作為分配的依據,并以此設計一些算法來實現針對特定場景的高效策略。
RoundRobinRule
Ribbon默認的負載均衡機制,該策略實現了按照線性輪詢的方式以此選擇每個服務實例的功能。輪詢index,選擇index對應位置的server。
RandomRule
該策略實現了從服務實例清單中隨機選擇一個服務實例的功能。通過在index上隨機,選擇index對應位置的server。
RetryRule
該策略實現了一個具備重試機制的實例選擇功能。該策略下在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server。

