问题描述
1. 负载均衡Ribbon
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。
负载均衡策略
- 随机策略:该策略实现了从服务清单中随机选择一个服务实例的功能。
- 轮训策略:该策略实现按照线性轮询的方式依次选择实例的功能。
基于基于ribbon实现负载均衡
-
开启ribbon负载均衡,注解@LoadBalanced
@Configuration public class ConfigBean { @Bean /** * 添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取 * 注册中心的所有可用服务,通过获取到的服务信息(ip,port)替换 serviceId 实现负载请求。 */ @LoadBalanced //开启负载均衡,默认是轮询策略 public RestTemplate getRestTemplate(){ return new RestTemplate(); } } //指定随机策略 @Bean public IRule iRule() { return new RandomRule(); }
-
发送请求,借助RestTemplate对象发送请求,请求路径不再是ip+端口号,而是在nacos注册的服务名
String serviceUrl = "ribbon-provider"; return restTemplate.getForObject("http://" + serviceUrl + "/provider/getUserById/" + id, User.class);
ribbon的问题
拼接url和参数,是一种硬编码的方式。为了解决把请求路径硬编码的问题,我们推荐使用Feign声明式调用服务
2.声明式服务调用Feign
什么是feign
- Feign是Spring Cloud提供的声明式、模板化的HTTP客户端,工作在consumer端
- feign支持springmvc注解
- feign集成了Ribbon也支持负载均衡
- (ribbon+restTemplate)+优化=feign
feign依赖:spring-cloud-starter-openfeign
feign 的入门使用
消费者通过feign接口来调用某一个服务,需要三个模块,服务消费者,服务提供者,feign接口
-
创建provider,即服务提供者
RestController @RequestMapping("/provider") public class ProviderController { @Autowired private UserService userService; @RequestMapping("/getUserById/{id}") public User getUserById(@PathVariable Integer id){ return userService.getUserById(id); } }
-
创建feign_interface工程,注意feign接口必须在名为feign的包下
-
引入openfeign依赖
-
feign接口,@FeignClient注解里的值为在nacos中注册的服务名,即要调用的服务;接口的方法名和所有注解要和调用的服务的方法保持一致
@FeignClient("服务名") public interface UserFeign{ @RequestMapping("/getUserById/{id}") User getUserById(@PathVariable("id") Integer Id); }
-
-
创建consumer,即服务消费者
-
依赖引入feign_interface
-
controller层,注入UserFeign的代理类,直接使用UserFeign代理类调用所需的服务
@RestController @RequestMapping(value = "/consumer") public class ConsumerController { @Autowired private UserFeign userFeign; @RequestMapping("getUserById/{id}") public User getUserById(@PathVariable Integer id){ return userFeign.getUserById(id); } }
-
application启动类上,添加@EnableFeignClients注解,表示开启feign注解扫描
-
feign接口的三种传参方式
-
键值对传参或者路径?拼接传参
参数前加@RequestParam(“id”),注解的值必须写明
-
restful风格传参,即路径传参
参数前加@PathVariable(“id”),注解的值必须写明
-
pojo传参,即前端传json串之后json转换工具转换成java对象,包括实体对象、数组、集合等
参数前加@RequestBody
feign原理
- 将feign接口的代理类扫描到Spring容器中:
@EnableFeignClients开启feign注解扫描:FeignClientsRegistrar.registerFeignClients()扫描被 @FeignClient标识的接口生成代理类,并把接口和代理类交给Spring的容器管理。 - 为接口的方法创建RequestTemplate,当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url,参数)
- 发出请求:
代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求
feign优化
开启feign日志
feign日志默认有四种输出级别:NONE,BASIC,HEADERS,FULL
-
NONE:没有日志记录
-
BASIC:记录请求方法、URL以及响应状态代码和执行时间(一般使用这个)
-
HEADERS:记录基本信息以及请求和响应头信息
-
FULL:记录基本信息以及请求和响应头信息、请求和响应体信息
-
特别提醒:在为某一个FeignClient文件设置日志记录级别的时候,一定要先设置好日志级别,推荐日志级别设置为DEBUG
# feign配置
feign:
client:
config:
default: #default默认所有服务,也可以写要调用的服务名称
loggerLevel: full
logging:
level:
com.bjpowernode.feign: debug #配置feign所在包的日志级别
feign超时
## 方法一:设置在ribbon上
ribbon:
OkToRetryOnAllOperations: false #对所有操作请求都进行重试,默认false
ReadTimeout: 5000 #负载均衡超时时间,默认值5000
ConnectTimeout: 3000 #ribbon请求连接的超时时间,默认值2000
MaxAutoRetries: 0 #对当前实例的重试次数,默认0
MaxAutoRetriesNextServer: 1 #对切换实例的重试次数,默认1
## 方法二:设置在feign client上
feign:
client:
config:
default:
connectTimeout: 5000 #请求连接的超时时间
readTimeout: 3000 #请求处理的超时时间
http连接池
feign的Http客户端支持3中框架,HttpURLConnection,HttpClient,OkHttp
两台服务器建立HTTP连接的过程涉及到多个数据包的交换,因为Feign默认采用的是传统JDK中的java.net.HttpURLConnection,每次请求都会建立,关闭连接,Http 连接需要的 3 次握手 4 次分手开销很大,很消耗时间。
所以我们需要更换http通信框架来节约大量的时间提示吞吐量,把它换成HttpClient作为底层通信框架。HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头,参数,内容体,响应等等;它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性;另外高并发大量的请求网络的时候,还是用“连接池”提升吞吐量。
-
解决办法:添加依赖
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
-
配置文件中开启
feign: httpclient: #开启httpclient enabled: true
gzip压缩
-
为什么要开启gzip压缩:
我们压缩文件的目的就是为了把传输文件的体积减小,加快传输速度。我们在
http
传输中开启gZip
的目的也是如此,我们写的代码(css,js
)之类的文件会有很好的压缩效果,但是图片之类文件则不会被gzip
压缩太多,因为它们已经内置了一些压缩。 -
feign的gzip压缩配置
### Feign 配置 feign: compression: request: # 开启请求压缩 enabled: true # 配置压缩的 MIME TYPE(这项默认压缩所有它认定的文件类型,可以不写) mime-types: text/xml,application/xml,application/json # 配置压缩数据大小的下限 min-request-size: 2048
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)