Spring Cloud入門項目實戰(三)--Ribbon

前言

我自己建了個博客網站,歡迎大家來訪問,閱讀體驗更佳點擊進入
正在入門SpringCloud中,在學習的過程中也正好做個項目練手。這個項目是想做成一個模板,這樣之後遇到同規模項目的時候可以拿來就用,版本也好控制。涉及到的中間件會有Eureka、Ribbon、Feign、HyStrix、Zuul、ConfigServer。這一節項目將改寫Ribbon。
版本
SpringBoot:2.2.1.RELEASE
Spring Cloud:Finchley.RS1
spring-cloud-starter-netflix-eureka-client:2.2.1.RELEASE

  • Eureka:2.2.1.RELEASE
  • Ribbon:2.2.1.RELEASE

目錄結構
在這裏插入圖片描述

如果爲同一個的提供者在Eureka中註冊了多個服務,那麼客戶端該如何選擇服務呢?
這時,就需要在客戶端實現服務的負載均衡。

Ribbon是Netflixⅸx發佈的負載均衡器,它有助於控制HTTP和TCP客戶端的行爲。爲Ribbon配置服務提供者地址列表後, Ribbon就可基於某種負載均衡算法,自動地幫助服務消費者去請求。 Ribbon默認爲我們提供了很多的負載均衡算法,例如輪詢、隨機等。當然,我們也可爲 Ribbon實現自定義的負載均衡算法。

一、簡單的負載均衡程序

從consume-user複製粘貼出一個新的consume-user-ribbon,也可以不重新創建,直接修改consume-user,需要修改的是Controller和啓動程序。

修改入口函數

@SpringBootApplication
@EnableEurekaClient
@RibbonClient("PROVIDER-USER")  // 啓用Ribbon並對PROVIDER-USER負載均衡
public class ConsumeUserRibbonApplication {
    public static void main( String[] args ) {
        SpringApplication.run(ConsumeUserRibbonApplication.class, args);
    }
}

修改消費者Controller

修改獲取url的方式

	private EurekaClient eurekaClient;
	@LoadBalanced
    private RestTemplate restTemplate = new RestTemplate();

    @GetMapping("getUserByEureka/{id}")
    public User getUser(@PathVariable Long id){
        
        User user = restTemplate.getForObject("http://PROVIDER-USER/user/"+id, User.class);
        return user;
    }

開啓兩個生產者,注意端口不同
在這裏插入圖片描述
在這裏插入圖片描述
但我通過消費者7901獲取用戶時,出現錯誤

I/O error on GET request for "http://PROVIDER-USER/user/1": PROVIDER-USER; nested exception is java.net.UnknownHostException: PROVIDER-USER

這是因爲獲取RestTemplat對象時要加上@LoadBalanced註解 ,否則restTemplate.getForObject方法會報java.net.UnknownHostException。
在這裏插入圖片描述
要解決這個問題還有一點要改,就是Controller中的restTemplete要交由Spring容器來管理。我原先是直接new RestTtemplete(),在負載均衡的場景下不可用
在這裏插入圖片描述
在這裏插入圖片描述

二、修改負載均衡策略

修改消費者的application.yml
PROVIDER-USER爲生產者中配置的應用名,指定其策略爲隨機,這樣就會隨機使用兩個生產者

PROVIDER-USER:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

修改消費者Controller方便查看輸出

@RestController
public class UserController {

    /* 使用eureka動態獲取url */
    @Autowired
    private EurekaClient eurekaClient;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("getUserByEureka/{id}")
    public User getUser(@PathVariable Long id){
        ServiceInstance instance = loadBalancerClient.choose("PROVIDER-USER");
        System.out.println(instance.getHost()+":"+instance.getPort());
        User user = restTemplate.getForObject("http://PROVIDER-USER/user/"+id, User.class);
        return user;
    }

    /* 硬編碼url
    private RestTemplate restTemplate = new RestTemplate(); // spring提供的用於訪問接rest口的模板對象
    @GetMapping("user/{id}")
    public User getUser(@PathVariable Long id){
        User user = restTemplate.getForObject("http://localhost:7900/user/"+id, User.class);
        return user;
    }
     */
    /*
    服務提供者中的控制器
    @GetMapping("user/{id}")
    public User getUser(@PathVariable Long id){
        return new User(id);
    }
    */

}

在這裏插入圖片描述

三、總結

通過restTemplete獲得服務生產者實例時,restTemplete需由Spring容器來生成並加上LoadBlance註解,不能直接new一個實例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章