上篇文章我們已經完成了Ribbon負載均衡的功能。做法很簡單,隻需要在RestTemplate添加@LoanBalanced 的注解。預設情況下,Ribbon的負載均衡政策是RoundRobbin(輪訓)的方式,可很多時候在特定場景下需要不同的政策,這個時候就需要自定義Ribbon政策了。看下面代碼:
[java] view plain copy
- package com.zhuyang.cloud.controller;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cloud.client.loadbalancer.LoadBalanced;
- import org.springframework.cloud.netflix.ribbon.RibbonClient;
- import org.springframework.context.annotation.Bean;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.client.RestTemplate;
- import com.zhuyang.cloud.entity.User;
- import com.zhuyang.config.RibbonConfiguration;
- @RestController
- @RibbonClient(name = "microservice-provider", configuration = RibbonConfiguration.class)//name是provider的服務名 <span style="font-family: Arial, Helvetica, sans-serif;">RibbonConfiguration為自定義配置</span>
- public class MovieController {
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate() { // equals to RestTemplate
- // restTemplate=new RestTemplate();
- return new RestTemplate();
- }
- @Autowired
- private RestTemplate restTemplate;
- @RequestMapping(value = "/movie/{id}", method = RequestMethod.GET)
- public User findById(@PathVariable Long id) {
- // return restTemplate.getForEntity("http://localhost:8000/service/"+id,
- // User.class).getBody();
- return restTemplate.getForEntity("http://microservice-provider/provider/service/" + id, User.class).getBody();
- }
- }
[html] view plain copy
- server:
- port: 8001
- eureka:
- client:
- serviceUrl:
- defaultZone: http://user:[email protected]:8761/eureka/ # 指定注冊中心的位址
- instance:
- preferIpAddress: true
- spring:
- application:
- name: microservice-consumer
- microservice-provider: ##config ribbon
- ribbon:
- eureka:
- enabled: false
- listOfServers: localhost:8000, localhost:8002,localhost:8003 ##假設provider有3台instance端口分别是8000 8002 8003
- ServerListRefreshInterval: 15000
[java] view plain copy
- package com.zhuyang.config;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import com.netflix.client.config.IClientConfig;
- import com.netflix.loadbalancer.IPing;
- import com.netflix.loadbalancer.IRule;
- import com.netflix.loadbalancer.PingUrl;
- import com.netflix.loadbalancer.ZoneAvoidanceRule;
- public class RibbonConfiguration {
- @Autowired
- private IClientConfig ribbonClientConfig;
- @Bean
- public IPing ribbonPing(IClientConfig config) {
- // ping url will try to access http://microservice-provider/provider/ to
- // see if reponse code is 200 . check PingUrl.isAlive()
- // param /provider/ is the context-path of provider service
- return new PingUrl(false, "/provider/");
- }
- @Bean
- public IRule ribbonRule(IClientConfig config) {
- // return new AvailabilityFilteringRule();
- return new RandomRule();//
- // return new BestAvailableRule();
- // return new RoundRobinRule();//輪詢
- // return new WeightedResponseTimeRule();
- // return new RetryRule();
- // return new ZoneAvoidanceRule();
- }
- }
在RibbonConfiguration中的ribbonRule方法就是用來定義不用的政策,每種政策所對應的實作類和描述 都已經添加了注釋。例如我們傳回的是RandomRule政策,那麼我們在多次請求provider的時候就不再是輪訓的方式進行命中,而是随機方式。。下面是RandomRule的代碼實作
[java] view plain copy
- public Server choose(ILoadBalancer lb, Object key) {
- if (lb == null) {
- return null;
- }
- Server server = null;
- while (server == null) {
- if (Thread.interrupted()) {
- return null;
- }
- List<Server> upList = lb.getReachableServers();//get all reachable server .list listOfServers: localhost:8000, localhost:8002,localhost:8003
- List<Server> allList = lb.getAllServers();
- int serverCount = allList.size();
- if (serverCount == 0) {
- return null;
- }
- int index = rand.nextInt(serverCount);//get random index
- server = upList.get(index);//get specified server eg:<span style="font-family: Arial, Helvetica, sans-serif;">localhost:8000</span>
- if (server == null) {
- Thread.yield();
- continue;
- }
- if (server.isAlive()) {
- return (server);
- }
- // Shouldn't actually happen.. but must be transient or a bug.
- server = null;
- Thread.yield();
- }
- return server;//return selected server
- }