SpringCloud极简入门-客户端负载均衡-Feign

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在前一章节,我们使用Ribbon作为客户端负载均衡完成了订单服务和用户服务的通信,其实我们可以发现,当我们通过RestTemplate调用其它服务时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。而Feign的服务调用方式对于程序员来说更为友好,它基于Ribbon进行了封装,把一些负责的url和参数处理细节屏蔽起来,我们只需要简单编写Fiegn的客户端接口就可以像调用本地service去调用远程微服务。

七.客户端负载均衡-Feign

1.什么是Feign

1.1.为什么要使用Feign

在前一章节,我们使用Ribbon作为客户端负载均衡完成了订单服务和用户服务的通信,其实我们可以发现,当我们通过RestTemplate调用其它服务时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。而Feign的服务调用方式对于程序员来说更为友好,它基于Ribbon进行了封装,把一些负责的url和参数处理细节屏蔽起来,我们只需要简单编写Fiegn的客户端接口就可以像调用本地service去调用远程微服务。

1.2.什么是Feign

Feign是一个声明式的http客户端,使用Feign可以实现声明式REST调用,它的目的就是让Web Service调用更加简单。Feign整合了Ribbon和SpringMvc注解,这让Feign的客户端接口看起来就像一个Controller。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。同时Feign整合了Hystrix,可以很容易的实现服务熔断和降级(关于Hystrix我们后面再讲)。

2.Feign的编码实战

官方参考文档:OpenFeign

我们这里想要实现的效果和之前学习Ribbon案例的效果一样:

为了不和前面的案例混淆代码,我们搭建新工程“支付服务”来演示Feign。那在这里支付服务和订单服务充当的角色一样,都是服务消费者,通过调用用户服务来获取数据。

那么支付服务需要做什么事情?

  • 1.搭建基础项目结构,
  • 2.注册到Eureka,
  • 3.集成Feign向用户服务发起调用。

2.1.创建工程

创建工程 springcloud-pay-server-1040,用来集成Feign,效果如下:

springcloud-parent
  springcloud-eureka-server-1010
  springcloud-order-server-1030
  springcloud-pay-server-1040 //支付服务用来集成Feign
  springcloud-user-common
  springcloud-user-server-1020
pom.xml

2.2.导入依赖

导入Feign,Eureka Client和web的依赖包,同时依赖user-common模块 ,具体的 pom.xml如下

<dependencies><!--1.导入EurekaClient的包--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--2.导入Feign的包--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--web包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--user-common--><dependency><groupId>cn.itsource.springboot</groupId><artifactId>springcloud-user-common</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>

2.3.配置类如下

主配置类增加@EnableFeignClients标签 , 其value属性可以指定Feign的客户端接口的包,当然也可以省略value属性

/*** 支付的启动类* @EnableFeignClients :开启Feign支持*/@SpringBootApplication@EnableEurekaClient@EnableFeignClients(value="cn.itsource.springboot.feignclient")
publicclassPayServerApplication1040{
publicstaticvoidmain( String[] args )
    {
SpringApplication.run(PayServerApplication1040.class);
    }
}

yml配置如下:

server:  port: 1040eureka:  client:    serviceUrl:      defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
  instance:    instance-id: pay-server:1040 #实例ID    prefer-ip-address: true #使用ip注册到注册中心spring:  application:    name: pay-server

2.4.编写Feign的客户端接口

Feign的客户端接口是用来调用微服务的,我这里就编写了一个用来调用用户服务的客户端接口,如下:

packagecn.itsource.springboot.feignclient;
//...省略...@FeignClient("user-server")
publicinterfaceUserFeignClient {
//订单服务来调用这个方法      http://localhost:1020/user/10// @GetMapping(value = "/user/{id}" )@RequestMapping(value="/user/{id}",method=RequestMethod.GET)
UsergetById(@PathVariable("id")Longid);
}

解释

@FeignClient(“user-server”) : user-server是用户服务的服务名字,Feign根据服务名能够在注册中心找到目标服务的通信地址

你会发现接口中的方法跟用户服务(springcloud-user-server-1020)中的方法一样,其实Feign就是通过客户端接口里面的方法,来决定目标服务的资源路径url,参数以及返回值,这里我们可以直接把要调用的目标服务的controller方法拷贝过来,然后去掉方法体即可。

Feign可以根据@FeignClient(“user-server”)找到用户服务,根据方法上的     @RequestMapping(value = “/user/{id}”,method = RequestMethod.GET)找到目标服务的controller的方法 ,我们在使用Feign接口时传入的参数就会作为目标服务controller方法的参数,而返回值就是目标服务controller方法的返回值。

即:服务名要一致 , url路径要一致 , 参数要一致 , 返回值类型要一致。

建议 :服务名直接去目标服务配置中拷贝 , 方法直接从目标服务controller中拷贝

2.5.编写Controller使用Feign接口

通过注入UserFeignClient ,直接发起调用

//支付服务的controller@RestControllerpublicclassPayController{
@AutowiredprivateUserFeignClientuserFeignClient;
//浏览器来掉@RequestMapping("/pay/{id}")
publicUsergetById(@PathVariable("id")Longid){
//使用Feign调用用户服务获取UserreturnuserFeignClient.getById(id);
    }
}

这里调用UserFeignClient.getById方法,看起来是像在调用本地方法,其实该接口已经被Feign代理,我们发起调用时其实在像Feign接口配置的目标服务发起调用。

2.6.测试

依次启动注册中心springcloud-eureka-server-1010 ,两个用户服务springcloud-user-server-1020 , 启动支付服务 springcloud-pay-server-1040 ,

通过浏览器访问pay-server的controller:http://localhost:1040/pay/1,多次请求发现依然默认使用了轮询策略:

2.7.理解Feign的工作原理

要使用Feign,我们除了导入依赖之外,需要主配置类通过@EnableFeignClients(value="")注解开启Feign,也可以通过value属性指定了Feign的扫描包。同时我们需要为Feign编写客户端接口,接口上需要注解@FeignClient标签。 当程序启动,注解了@FeignClient的接口将会被扫描到然后交给Spring管理。

当请求发起,会使用jdk的动态代理方式代理接口,生成相应的RequestTemplate,Feign会为每个方法生成一个RequestTemplate同时封装好http信息,如:url,请求参数等等

最终RequestTemplate生成request请求,交给Http客户端(UrlConnection ,HttpClient,OkHttp)。然后Http客户端会交给LoadBalancerClient,使用Ribbon的负载均衡发起调用。

4.Feign的参数配置

4.1.负载均衡配置

Feign已经集成了Ribbon,所以它的负载均衡配置基于Ribbon配置即可,这里使用xml简单配置负载均衡策略如下:

user-server:  ribbon:    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

4.2.Feign的超时配置

如果在服务调用时出现了 “feign.RetryableException : Read timed out…”错误日志,说明Ribbon处理超时 ,我们可以配置Ribbon的超时时间:

ribbon:
  ConnectTimeout: 3000
    ReadTimeout: 6000

如果服务调用出现“com.netflix.hystrix.exception.HystrixRuntimeException:… timed - out and no fallback available” 错误日志,是因为Hystrix超时,默认Feign集成了Hystrix,但是高版本是关闭了Hystrix,我们可以配置Hystrix超时时间:

feign:   hystrix:       enabled: true #开启熔断支持hystrix:  command:      default:        execution:          isolation:            thread:              timeoutInMilliseconds: 6000   #hystrix超时时间

5.Feign开启日志调试

官方文档:https://cloud.spring.io/spring-cloud-openfeign/reference/html/#feign-logging

5.1.配置Feign日志打印内容

有的时候我们需要看到Feign的调用过程中的参数及相应,我们可以对Feign的日志进行配置,Feign支持如下几种日志模式来决定日志记录内容多少:

  • NONE,不记录(DEFAULT)。
  • BASIC,仅记录请求方法和URL以及响应状态代码和执行时间。
  • HEADERS,记录基本信息以及请求和响应标头。
  • FULL,记录请求和响应的标题,正文和元数据。

创建Feign配置类

@ConfigurationpublicclassFeignConfiguration {
@BeanLogger.LevelfeignLoggerLevel() {
returnLogger.Level.FULL;   //打印Feign的所有日志    }
}

5.2.配置日志打印级别

配置UserFeignClient的日志打印级别,上面的配置打印Feign的那些内容,下面这个是配置日志框架打印日志的级别,不修改可能打印不出来日志,DEBUG打印日志调试信息。

logging:  level:    cn.itsource.springboot.feignclient.UserFeignClient: debug

6.Feign开启GZIP

可以通过开启Feign的数据压缩传输来节省网络开销,但是压缩数据会增加CPU的开销,所以太小的数据没必要压缩,可以通过压缩大小阈值来控制,配置如下:

feign:  compression:    request:      enabled: true      min-request-size: 1024 #最小阈值,小于这个不压缩      mime-types: text/xml,application/xml,application/json #压缩哪些类型的数据    response:      enabled: true

在Feign中该配置对应的配置类是FeignClientEncodingProperties ,最终效果如下 :

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
2月前
|
负载均衡 算法 Java
Spring Cloud全解析:负载均衡算法
本文介绍了负载均衡的两种方式:集中式负载均衡和进程内负载均衡,以及常见的负载均衡算法,包括轮询、随机、源地址哈希、加权轮询、加权随机和最小连接数等方法,帮助读者更好地理解和应用负载均衡技术。
|
9天前
|
负载均衡 算法 Java
除了 Ribbon,Spring Cloud 中还有哪些负载均衡组件?
这些负载均衡组件各有特点,在不同的场景和需求下,可以根据项目的具体情况选择合适的负载均衡组件来实现高效、稳定的服务调用。
23 5
|
30天前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
2月前
|
负载均衡 Java 对象存储
负载均衡策略:Spring Cloud与Netflix OSS的最佳实践
负载均衡策略:Spring Cloud与Netflix OSS的最佳实践
49 2
|
1月前
|
负载均衡 监控 算法
Nginx入门 -- 深入了解Nginx负载均衡
Nginx入门 -- 深入了解Nginx负载均衡
20 0
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
2月前
|
负载均衡 Java 开发者
Ribbon框架实现客户端负载均衡的方法与技巧
Ribbon框架为微服务架构中的客户端负载均衡提供了强大的支持。通过简单的配置和集成,开发者可以轻松地在应用中实现服务的发现、选择和负载均衡。适当地使用Ribbon,配合其他Spring Cloud组件,可以有效提升微服务架构的可用性和性能。
32 0
|
4月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
488 15
|
4月前
|
缓存 负载均衡 算法
微服务之客户端负载均衡
微服务中的客户端负载均衡是指将负载(即工作任务或访问请求)在客户端进行分配,以决定由哪个服务实例来处理这些请求。这种负载均衡方式与服务端负载均衡相对,后者是在服务端(如服务器或负载均衡器)进行请求的分发。
74 5
|
4月前
|
消息中间件 存储 负载均衡
消息队列 MQ使用问题之如何在grpc客户端中设置负载均衡器
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。