天天看点

【Spring Cloud总结】7.Ribbon的基本使用

接上篇《6.将微服务注册到Eureka Server上》  Spring Cloud版本为Finchley.SR2版

上一篇我们将服务消费者movie工程和服务提供者user工程都注册到了注册中心Eureka Server上,那么本篇我们就来学习movie工程如何调用Eureka Server注册的user工程提供的服务,并延伸出Ribbon的知识。

既然我们已经把服务提供者user工程的服务注册到Eureka Server上了,那必然是不想在服务消费者movie工程中对需要调用服务的ip进行硬编码。那么就有以下两个问题:

1.我们如何让movie工程使用到Eureka Server中注册的信息呢?

2.假设user微服务有两个节点,那么movie微服务去调用user微服务的时候,怎么样做到负载均衡呢?

首先我们来讨论一下实现负载均衡的两种方式:

一种负载均衡的做法,是很常见的,就是在集群前添加一个Nginx,所有访问集群节点的请求都通过Nginx进行反向代理,利用轮询等负载均衡的算法,命中某个节点进行请求:

【Spring Cloud总结】7.Ribbon的基本使用

我们称这种负载均衡做法为服务端负载均衡。

另一种负载均衡做法,是在请求端添加一个组件,该组件可以知道当前有几个可用的用户微服务的ip和端口,然后在请求前使用负载均衡算法,命中其中一个节点。而往往这个组件存储的可用微服务的ip和端口往往是从类似注册中心的地方获取的:

【Spring Cloud总结】7.Ribbon的基本使用

那么在Spring Cloud中,提供了一种客户端负载均衡的组件,就是Ribbon。下图展示了Eureka使用Ribbon时的大致架构:

【Spring Cloud总结】7.Ribbon的基本使用

可以Ribbon的模式就是典型的客户端负载均衡的模式。Ribbon工作时分为两步:第一步先选择Eureka Server,它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询round robin,随机Random,根据响应时间加权等。

那么我们如何集成Ribbon?我们在microserver-consumer-movie工程中集成Ribbon。首先在pom文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
           

使用Ribbon也十分简单,我们在原来的RestTemplateConfig配置类中原来注入了请求Http服务的RestTemplate对象,我们只需要在它的类声明前添加@LoadBalanced标签即可:

package com.microserver.cloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);//在Spring容器中注入RestTemplate对象
    }
 
    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        //初始化RestTemplate对象需要的Factory工厂类,biang注入到Spring容器中
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);//读取反馈超时时间5000ms
        factory.setConnectTimeout(15000);//连接超时时间15000ms
        return factory;
    }
}
           

此部分详见Finchley.SR2版官方文档,66.4.1 Using Ribbon章节(https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#netflix-ribbon-starter)。

然后我们修改一下调用远程user服务的MovieController类,将原来的动态ip地址改为服务提供者在Eureka Server中注册的应用名(application name):

package com.microserver.cloud.controller;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.microserver.cloud.entity.User;
 
@RestController
public class MovieController {

    @Autowired
    private RestTemplate restRemplate;
    
    /* 使用了ribbon,不需要再从配置文件中加载请求ip和端口了
     * @Value("${user.userServicePath}") private String userServicePath;
     */
    
    @GetMapping("/movie/{id}")
    public User findUserById(@PathVariable Long id){
        return this.restRemplate.getForObject("http://microserver-provider-user/findById/"+id, User.class);
    }
}
           

我们之前的url是:http://localhost:7900/findById/,现在改成了user微服务的spring.application.name,这个application.name在Eureka Server注册中心中,就是一个VIP,即virtual IP。

我们把movie、user和注册中心Eureka启动一下,看到应用注册成功:

【Spring Cloud总结】7.Ribbon的基本使用

然后我们请求movie的http://localhost:7901/movie/服务,请求id为1的用户信息,此时movie工程就会使用restRemplate进行请求,拿到结果:

【Spring Cloud总结】7.Ribbon的基本使用

注:如果出现查询失败或者表不存在的情况,请将user配置文件的ddl-auto改为update

可以看到通过application.name是可以访问注册的服务的。那么下面测试一下负载均衡。我们在user工程7900端口启动的情况下,修改user工程的application.yml的端口为7902,:

server:
  port: 7902
           

再启动一个user工程:

【Spring Cloud总结】7.Ribbon的基本使用
【Spring Cloud总结】7.Ribbon的基本使用

现在有两个user工程,我们访问movie的http://localhost:7901/movie/1请求,多次访问后,可以看到7900和7902的应用都有接收请求的日志打印出来,说明负载均衡生效了:

【Spring Cloud总结】7.Ribbon的基本使用
【Spring Cloud总结】7.Ribbon的基本使用

在一开始的访问过程中,可能前面要访问很多次,请求才会命中刚刚启动的7902端口的服务,那是因为前面构造图中的服务消费者的可用服务列表是有缓存的,而这个缓存需要一段时间才会刷新,所以一开始一直没有命中7902端口的服务是因为一直获取的是可用服务列表的本地缓存,到了刷新的时候,从Eureka Server拉取了新的可用服务列表,此时就会命中7902服务。

而且我们在两个端口服务都有命中的情况下,反复访问,可以看到请求交替的命中两个服务,可以推测出Ribbon的默认负载均衡策略是轮询机制。

我们目前使用的都是默认配置的Ribbon,那么我们如何去自定义Ribbon的配置,例如修改其负载均衡策略?下一篇我们继续介绍如何定制一个Ribbon Client。

参考:《51CTO学院Spring Cloud高级视频》

转载请注明出处:https://blog.csdn.net/acmman/article/details/94876570

继续阅读