接口超时,接口参数的特殊符号,接口的有序性,重试机制的结果一致性
1.http超时时间,将restTemplate的连接,超时时间设置更加长的时间。
2.http mvc GET请求,?a=1&b=2&c=#3,测试发现含#符号会在服务接口接收参数异常。需要将#特殊符合过滤,比如:可以替换为中文”井“
3.请求的有序性保持
3.1服务端方法:比如接收到无序的MQ消息或者binlog,比如对库存的控制,删除之前先验证订单状态。只有取消订单状态才会删除库存。
代码语言:txt复制 删除库存记录之前,先验证一下订单状态(非取消的情况下)库存是需要占据的,不应删除。
代码语言:txt复制 正常的顺序是:先删后增。如果反过来:先增后删,就会出现增加的时候无法新增,因为已经存在了。而最终的结果是删除了。
- A >> B
- 删除,没有记录了,导致库存没有记录,引起超卖。
3.2客户端方法:客户端请求失败 重试机制,如何保障2次请求的结果正确,而不被覆盖。
从大的方面来看:其实是涉及到两个系统的事务一致性问题,A系统的结果 = B系统的结果。
比如:请求a 参数100 失败
代码语言:txt复制 请求b 参数200 成功 >> B系统结果200
代码语言:txt复制 重试请求a 参数100 成功 >> B系统结果100
以上操作就会出现最终的结果不一致:期望是A系统结果200,B系统的结果是100
解决方法:在重试请求的操作中,需要获取最新的参数值来发起请求,而不是基于上一次请求失败的参数来发起。关键
3.3 客户端方法2: 异步方法@Async 延时重试 while循环(在一段时间内的循环,确保接口的顺序执行,比如:先取消后新增,没有取消成功之后,不能新增操作)
@Transactional事务注解及请求接口的定义先后执行顺序设计
代码语言:javascript复制//超时时间设置代码
@Autowired
RestTemplateConfig restTemplateConfig;
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE); //application/x-www-form-urlencoded
httpHeaders.set("user-agent", "自定义");
HttpEntity httpEntity = new HttpEntity(httpHeaders);
String responseStr = restTemplateConfig.restTemplate().postForObject(url "?" object, httpEntity, String.class);
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.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/***
* 内部服务调用者
*/
@Configuration
public class RestTemplateConfig {
/**
* 适用于服务使用RestTemplate调用外部地址请求
* @return
*/
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
return restTemplate ;
}
/***
* 适用于服务内部之间使用RestTemplate相互调用增加Rinbbo机制
* 通过服务名方式
* @return
*/
@Bean(name="loadBalancedRestTemplate")
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
return restTemplate ;
}
private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(30000);
factory.setConnectTimeout(30000);
factory.setConnectionRequestTimeout(30000);
return factory;
}
}