@Configuration public class ConfigRestTemplate { @Bean // @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
※新增一個類別,因為要使用到 @LoadBananced 這個註解,只好放棄使用 @Import,但在使用前先註解,確保之前的程式是可以跑的
// @Import(RestTemplate.class) public class consumerController { // private static final String PROVIDER_URI = "http://localhost:9001"; private static final String PROVIDER_URI = "http://"+ "provider1".toUpperCase(); // ... }
※確保之前的程式能跑後,使用 ribbon 要三步
1.打開 @LoadBananced
2.訪問路徑改成 provider 的 spring.application.name 名稱,大小寫都可以,但 eureka 是大寫,最好都用一樣的
※以上缺一都會報錯
※不需要 ribbon 的 jar 包,eureka-client 已經有依賴了,這個 eureka-client 在第一篇已經加過了
※遇到的問題:
如果出現 Request URI does not contain a valid hostname 的錯,表示 spring.application.name 的名字找不到,不要忘了要加 http://另外一個是 name 名稱不能有「_」,都會報這樣的錯
這個專案在隔天 run 時,居然出現找不到 PROVIDER1 的錯,結果 mvn clean install 就解決了
※測試 ribbon 預設的模式
新增兩個專案:1.複製 pom.xml
2.複製 啟動類別和 controller,為了測試區別,/xxx 的內容三支都修改 ab.setName("xxx9002"); // 9001-9003
3.instance.instance-id 修改不同的名稱,但 spring.application.name 一樣
4.http://localhost/xxx 每重整一次會發現是有順序性的,如第一次循環是 132,就會一直按 132 的方式循環
畫面如下:
可看見 PROVIDER1 有三個實例
※改變預設模式
@Configuration public class ConfigRestTemplate { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } @Bean public IRule myRibbonRule() { // return new RoundRobinRule(); // return new RandomRule(); return new RetryRule(); } }
※在自訂的 ConfigRestTemplate 增加 IRule 的回傳 Bean,RoundRobinRule 是預設的、
RandomRule 是隨機的、RetryRule 和預設的很像,差在如果其中有 provider 掛了就不一樣了,假設是 132 一直循環,然後 2 掛了,那就會是 13掛、13掛、經過幾次之後,就只會有13而已,可以將三個 provider 啟好後,關閉其中一個測試
※也可以寫個 class,然後回傳 IRule
※自定義規則
@Configuration public class MyCustomRibbonRule { @Bean public IRule myRibbonRule() { // return new RandomRule(); return new CalcRibbonRule(); } }
※改變預設模式的 @Bean 要註解或改名,不然會有 2 個 IRule
public class CalcRibbonRule extends AbstractLoadBalancerRule { private int currentIndex = 1; // PROVIDER1 的機器號碼 private 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(); // 到的有幾台機器 List<Server> allList = lb.getAllServers(); // 全部有幾台機器 int serverCount = allList.size(); if (serverCount == 0) { return null; } // 主要邏輯在這 if (upList.size() % 2 == 1) { server = upList.get(currentIndex); currentIndex++; System.out.println("size==>" + upList.size()); System.out.println("currentIndex==>" + currentIndex); if (currentIndex >= serverCount) { currentIndex = 1; } } if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) {} }
※我想不到什麼好規則,所以就是奇數的機器才去訪問,但並不是 9051 和 9053 這兩台機器的意思,機器的順序不是我們決定的,假設是 132,那就是 1 和 2
※本來是將 CalcRibbonRule 寫在 MyCustomRibbonRule 裡面,成為內部類別,但訪問的時候報錯了,NoSuchMethodException: controller.MyCustomRibbonRule$CalcRibbonRule.
※最後 consumer 的 main 方法要加上 @RibbonClient(value = "PROVIDER1", configuration = MyCustomRibbonRule.class) 即可
沒有留言:
張貼留言