Spring Cloud 远程调用与负载均衡

发布于:2024-05-21 ⋅ 阅读:(158) ⋅ 点赞:(0)

本篇主要介绍Spring Cloud远程调用和负载均衡的相关内容。

目录

一、远程调用

RestTemplate

Rest

RestTemplate的使用

二、负载均衡

什么是负载均衡

Spring Cloud  LoadBalancer

负载均衡策略


一、远程调用

在上一篇中,介绍了如何从注册中心eureka获取服务的信息,但如何通过获取的信息来远程调用其它服务呢?接下来我们来详细了解一下。

在Spring Cloud中实现远程调用常见的有两种方式,一种是RestTemplate,一种是Open Fegin。这里,我们先只介绍一下RestTemplate。

RestTemplate

RestTemplate是一个从Spring 3.0 开始支持的一个http请求工具,它是一个同步的Rest API客户端。在了解什么是RestTemplate之前,我们先来了解一下什么是Rest。

Rest

Rest是由Http的主要设计者Roy Fiedling 博士在他的博士论文中提出的一种软件架构风格,它表示资源在网络中以某种表现形式进行状态转移,这段话中有三个概念,我们来了解一下:

  • 资源:网络上的所有事务都可以称之为资源,并且每个资源都对应一个唯一的资源标识符(URI)
  • 表现层,资源的表现形式,例如一个文本,就可以用txt来表示,也可以用Json,二进制等来表现
  • 状态转移:在客户端和服务端进行交互时,可能会使对方的资源发生改变,例如增删改查等,这就是资源的状态转移。

Rest本身不实用,它只是为网络接口设计提供一种风格,而这种风格被作为Restful接口。

Restful需要通过HTTP才能实现,因此,Restful是基于http的。RestTemplate就是一种强制依据Restful设计的,只需要提供资源的地址和参数,就能让其它主机上的资源进行一些状态转移。

RestTemplate的使用

由于RestTemplate是由Spring提供的,因此我们在Spring项目中,无需引入相关jar包就能直接使用,但他并没有存入Spring 容器中,因此如果我们需要注入使用的话,需要先将其存放到Spring容器中,具体可以参考下面的代码

 当我们需要进行远程调用时,可以直接将RestTemplate注入进来,注入之后,我们可以通过RestTemplate的getForObject方法来调用其它服务,在这个方法中,有两个参数,第一个参数为服务的url,第二个则为调用服务的返回值。下面,我们来结合一下注册中心来测试一下RestTemplate远程调用的效果。具体代码如下

下面我们来测试一下这串代码,控制台输出的日志如下: 

通过日志可以发现通过RestTemplate已经成功实现远程调用product-servicre服务并获取到一个productInfo的相关数据了。

二、负载均衡

什么是负载均衡

当一个微服务项目的用户越来越多,就会使各服务的负载增大,如果一个服务只部署到一台机器上的话,那势必是无法承载如此高额的负载的,因此,通常情况下,一个服务都是会多机部署的。这样就会产生一个问题,当需要调用服务,到底要去访问哪台机器呢?并且如何才能保证每台机器承受的负载都是均衡的呢?

为了解决这个问题,就需要使用到负载均衡,负载均衡能够对每次请求访问哪个服务器进行控制,并通过一些算法,来使打到每一台服务器的请求的数量趋于一个均衡的状态。

负载均衡有两种,一种是服务端负载均衡,这种负载均衡是在服务端进行负载均衡的算法分配,具体流程可以参考下图

 

常见的服务端负载Nginx 。

另一种则是客户端负载均衡,这种负载均衡下,客户端会先去注册中心获取所需调用服务的所有服务器地址,然后在客户端通过负载均衡选择一个地址进行访问

常见的客户端负载均衡有Spring Cloud  LoadBalancer ,下面我们来具体了解一些Spring Cloud  LoadBalancer.

Spring Cloud  LoadBalancer

Spring Cloud  LoadBalancer的使用非常简单,只需要在前面将RestTemplate注入到Spring容器的方法上加上一个@LoadBalanced注解即可。具体如下:

加上之后,LoadBalanced负载均衡就开启了。

开启之后,在进行远程调用,就不再需要自己去手动从注册中心获取服务地址信息了,直接在url中设置服务名称即可,LoadBalance会自动去根据我们url中设置的服务名称去注册中心获取,并通过负载均衡算法选择一个合适的服务地址来进行服务调用,具体可以参考如下代码。

接下来,我们通过开启多个product-service服务来观察一下负载均衡的效果 

,具体调用的Product-service的接口如下:

在这个接口中只要被调用就会有所打印,方便我们来观察。

下面我们来多次访问一下127.0.0.1:8080/order/1这个url,该url会调用的相关代码已经实现好,大体就是每访问一次都会去远程调用一次product-service服务中的getProductById接口。

多次访问之后, 三个product-service服务的打印结果分别如下:

 可以发现每个服务被调用的次数是趋于均衡的。

负载均衡策略

负载均衡具体选择访问哪个地址的服务是由负载均衡策略来决定的,常见的负载均衡赛策略有轮询策略(对获取的服务地址一个一个按顺序使用),随机策略(随机选择一个服务地址进行使用)。LoadBalance默认采取的是轮询策略,如果想要修改成随机策略,需要我们自己自定义一个负载均衡策略,自定义负载均衡策略的流程如下:

创建一个LoadBalanceConfig类(类名可以自定义),并在这个类中通过@Bean方法注解加载一个随机算法对象到Spring容器中,具体可以参考下面的代码



import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

public class LoadBalanceConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment
            , LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        System.out.println("=============="+name);
        return new RandomLoadBalancer(
                loadBalancerClientFactory.getLazyProvider(name,
                ServiceInstanceListSupplier.class), name);
    }

}

需要注意的是这里不需要在类上加五大类注解。

接下来在前面加载RestTemplate的类上加上@LoadBalanceCilent或者 @LoadBalanceCilents注解,然后在注解里设置两个属性,name属性和Configuration属性,其中name属性表示要对哪个服务使用该负载均衡策略,configuration则是表示我们刚才定义的LoadBalanceCofig,详细代码如下:



import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
@LoadBalancerClient(name = "product-service",configuration = LoadBalanceConfig.class)
public class BeanConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

此时再远程调用product-service时,LoadBalance就使用的是随机策略了(调用其它服务还是轮询策略)。

接下来我们重启然后再重新多次访问前面的url,然后我们再来观察三个product-service服务的打印结果

 

可以发现 9092调用的次数明显对于另外两个,这是因为负载均衡策略已经改为随机策略了,调用的情况变得随机了。


网站公告

今日签到

点亮在社区的每一天
去签到