Eureka+Ribbon+RestTemplate实现客户端软负载均衡的两种方式

前言

最近在学习 SpringCloud 的东西,在使用 RestTemplate 结合 Ribbon 时,自己写的demo死活不过去。

在 Server 的 demo 里,我提供了一个对外的 Controller 。而里面调用的,则是用了这次说的实现软负载均衡的调用方法。

但,其中遇到一个问题,就是下面的:

No instances available for XXX

主要是刚学习,稀里糊涂的,经过一天的测试,终于摸清了原因。待我慢慢道来。

环境

  • mac
  • idea
  • maven
  • springcloud - Hoxton.SR1

第一次demo

第一次的 demo 结构图如下:
在这里插入图片描述

建立 demo 工程,直接用 idea 自行建立即可 ,eureka-server:

在这里插入图片描述

eureka-client:

在这里插入图片描述

包结构:

在这里插入图片描述

在 server 端提供的 Controller ,代码如下:

/**
 * @author sy
 * @Date 2020/1/16 6:04 下午
 * @Desc
 **/
@RestController
@RequestMapping("/")
public class ServerController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplates;

    @GetMapping("/msg")
    public String testRestTemplate() {
        //1. 直接使用 restTemplate 地址写死
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject("http://localhost:8081/hello", String.class);
    }

    @GetMapping("/msg2")
    public String testRestTemplate2() {
        //2. loadBalancerClient 获取实例名
        RestTemplate restTemplate = new RestTemplate();
        ServiceInstance instance = loadBalancerClient.choose("EUREKA-PROVIDER");
        String url = String.format("http://%s:%s/hello", instance.getHost(), instance.getPort());
        return restTemplate.getForObject(url, String.class);
    }

    @GetMapping("/msg3")
    public String testRestTemplate3() {
        //3. 利用 @LoadBalanced 负载均衡动态加载
        String url = String.format("http://%s/hello","EUREKA-PROVIDER");
        return restTemplates.getForObject(url, String.class);
    }
}

其中,msg 是单节点调用,意味着 url 写死的请求。

msg2和msg3则是客户端的软负载,去进行调用。结构图中有2个client注册到服务中心,所以当其中一台挂掉,那就会请求到另一台。

msg2利用了 loadBalancerClient 动态获取主机名和端口。

msg3则是需要用以下的 @LoaderBalance 来进行配置注入:

/**
 * @author sy
 * @Date 2020/1/17 9:40 上午
 * @Desc
 **/
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

当时想本意是,为了省事,让 server 端自己充当消费者的情况,但事实上,这种想法是错误的。

服务端里本身去消费 client 的角色,所以上述代码直接发出请求,msg1是可以成功的,但 msg2和msg3则会报错:

No instances available for EUREKA-PROVIDER

第二次 demo

在这里插入图片描述

把服务端的 Controller 迁移出来到新的 eureka-client 工程中,再次实现原来的 restTemplate 调用,发现无报错信息。

注意 :

通过上述方法的 testRestTemplate2 和 testRestTemplate3 调用时,他们的服务实例名,都是和下图对等。

//testRestTemplate2
loadBalancerClient.choose("EUREKA-PROVIDER");
//testRestTemplate3 
String url = String.format("http://%s/hello","EUREKA-PROVIDER");
return restTemplates.getForObject(url, String.class);

在这里插入图片描述

总结

看了许多 No instances available for 这样的错误,但没有一篇是和我遇到的情况是相关的,可能大家遇到的都不是初学遇到的场景,应该没有人会像我一样,demo写入 eureka-server中去吧。。。

反正我是把全网的类似这种错误的解决方案全试了一遍…都没效果,最后还是自己的锅。。。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页