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一个实例。

原创文章 22 获赞 10 访问量 2323

猜你喜欢

转载自blog.csdn.net/qq_41011723/article/details/105411336
今日推荐