服务之间的rpc调用要能达到高可用,重试机制是必不可少的.
(1).server-user调用server-basic.
(2).server-basic服务有节点A和节点B.
(3).server-user服务通过ribbon的算法拿到了节点A.
(4).server-basic服务节点A挂了.
(5).server-user发起调用.
(6).server-user调用连接超时,调用失败.
server-basic服务有节点A和节点B,server-user服务从注册中心定时拉取注册表(比如30秒拉取一次),此时server-basic服务的节点A挂了,server-user调用server-basic服务时注册表未能及时更新,以为server-basic服务的节点A是健康,去调用了,结果就是握手失败,调用失败.这个时候如果server-user能够切换实例到节点B,进行重试,那么就解决了这个问题.
(1)server-user服务关闭ribbon的重试机制,见ribbon相关配置,配置详解注释中已经说明.
server:
port: 1001 #服务端口
spring:
application:
name: server-user #服务名称
cloud:
nacos:
discovery:
server-addr: 47.96.131.185:8848
config:
server-addr: 47.96.131.185:8848 #nacos config配置中心ip和端口
file-extension: yaml #文件扩展名格式,针对于默认的{spring.application.name}-${profile}.${file-extension:properties}配置
enabled: true #开启或关闭配置中心
shared-dataids: mysql-user.yaml #自定义的配置文件dataid,以逗号分隔
refreshable-dataids: mysql-user.yaml #自定义的配置文件dataid实现自动刷新,以逗号分隔(其实就是热加载配置文件)
ribbon:
#对所有操作请求都进行重试,默认false(false=只有get请求才会进行重试)
OkToRetryOnAllOperations: false
#响应超时时间
ReadTimeout: 3000
#请求连接的超时时间
ConnectTimeout: 2000
#对当前实例的重试次数,默认0
MaxAutoRetries: 0
#对切换实例的重试次数,默认1
MaxAutoRetriesNextServer: 0
(2)启动一个server-user服务,启动两个server-basic服务不同的端口,测试代码复用上一章节的ribbon负载均衡测试,这里贴出.
server-user服务的RibbonTestConsumerController.java
package com.ccm.server.user.controller;
import com.ccm.common.exception.ServerException;
import com.ccm.common.exception.result.ResultSet;
import com.ccm.server.user.openfeign.ServerBasicFeign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description ribbon负载均衡测试客户端
* @Author zhouzhiwu
* @CreateTime 2020/07/18 19:37
*/
@RestController
@RequestMapping(value = "ribbonTestProducer")
@Api(tags = "ribbon负载均衡测试服务端")
public class RibbonTestConsumerController {
@Autowired
private ServerBasicFeign serverBasicFeign;
@ApiOperation(value = "ribbon负载均衡测试")
@GetMapping(value = "test01")
public ResultSet test01() {
ResultSet<String> feignVO = serverBasicFeign.test02();
if(feignVO.getCode() == 0) {
return ResultSet.success(feignVO.getData());
}
throw new ServerException("调用外部服务失败");
}
}
server-user服务的ServerBasicFeign.java
package com.ccm.server.user.openfeign;
import com.ccm.common.exception.result.ResultSet;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @Description 调用server-basic的feign层
* @Author zhouzhiwu
* @CreateTime 2020/07/17 9:46
*/
@FeignClient(name = "server-basic")
public interface ServerBasicFeign {
@GetMapping(value = "openFeignTest/test01")
ResultSet<String> test01();
@GetMapping(value = "ribbonTestProducer/test01")
ResultSet<String> test02();
}
server-basic服务的RibbonTestProducerController.java
package com.ccm.server.basic.controller;
import com.ccm.common.exception.result.ResultSet;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description ribbon负载均衡测试服务端
* @Author zhouzhiwu
* @CreateTime 2020/07/18 19:37
*/
@RestController
@RequestMapping(value = "ribbonTestProducer")
@Api(tags = "ribbon负载均衡测试服务端")
public class RibbonTestProducerController {
@Value("${server.port}")
private String port;
@ApiOperation(value = "ribbon负载均衡测试")
@GetMapping(value = "test01")
public ResultSet test01() {
return ResultSet.success("我是server-basic的数据,端口="+port);
}
}
启动服务
(3)服务启动成功后等待1分钟(保证server-user中当前的注册表为最新),然后关闭server-basic的其中一个节点,迅速使用swagger调用两次(保证server-user服务中注册表刷新前,一般是10秒左右刷新一次).
(1)阅读到这里,读者们早就发现了,默认情况下ribbon是有重试机制的,不需要我们去加入,相关的配置参数如下.
ribbon:
#对所有操作请求都进行重试,默认false(false=只有get请求才会进行重试)
OkToRetryOnAllOperations: false
#响应超时时间
ReadTimeout: 3000
#请求连接的超时时间
ConnectTimeout: 2000
#对当前实例的重试次数,默认0
MaxAutoRetries: 0
#对切换实例的重试次数,默认1
MaxAutoRetriesNextServer: 0
(2)配置建议
a.开启连接重试,关闭响应重试(原因:响应重试一般是被调用方代码执行时间较长,关闭响应重试可以保证代码不会重复执行).
b.关闭当前实例重试,开启切换重试实例(原因:当前实例失败了,第二次重试的失败的几率也会很高).
c.相关配置组合很多,要熟悉这一章节,必须自己手动去配置玩玩,看看不同的效果.
源码地址:https://gitee.com/chouchimoo/ccm-mall.git(本章节分支:zj-16)