@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) 即可

沒有留言:
張貼留言