SpringCloud之大数据转移RequestTooBigException:Connection terminated as request was larger than 10485760
在SpringCloud微服务项目中,应公司项目需求,需要将A服务器的大数据(他们给我们oracle数据库地址、用户名密码、视图等信息)转移到公司服务器mysql数据库中。首先,新加两个服务:分别是获取数据的服务(Spring-Cloud-GetData)、保存数据的服务(Spring-Cloud-SaveData)。在我的项目中(Spring-Cloud-Web)服务先去调用Spring...
在SpringCloud微服务项目中,应公司项目需求,需要将A服务器的大数据(他们给我们oracle数据库地址、用户名密码、视图等信息)转移到公司服务器mysql数据库中。
首先,新加两个服务:分别是获取数据的服务(Spring-Cloud-GetData)、保存数据的服务(Spring-Cloud-SaveData)。
在我的项目中(Spring-Cloud-Web)服务先去调用Spring-Cloud-GetData获取数据的接口,再通过声明式服务调用Spring-Cloud-SaveData保存数据。在此期间,由于数据量太大,导致获取数据后报错:
server.RequestTooBigException: UT000020: Connection terminated as request was larger than 10485760
原因:我的声明式服务调用feign配置了请求压缩
#请求压缩
feign.compression.request.enabled=true
feign.compression.response.enabled=true
但是未指定max-request-size:默认是10485760,对于大数据来说,显然是不够的。
解决:
#请求压缩
feign.compression.request.enabled=true
feign.compression.response.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
feign.compression.request.max-request-size=2097152000
同时,由于数据量大,请求时间肯定要加多一点,不然肯定会被熔断的:
#ribbon请求连接的超时时间- 限制3秒内必须请求到服务,并不限制服务处理的返回时间
ribbon.ConnectTimeout=14400000
#请求处理的超时时间 下级服务响应最大时间,超出时间消费方(路由也是消费方)返回timeout
ribbon.ReadTimeout=14400000
同时,我将需要转移的数据的时间段分割,以达到分批转移的目的:
/**
* 数据转移 oracle-->mysql
*/
@RequestMapping(value = "/saveStudentData")
public EqResult saveStudentData(@RequestParam String startTime,@RequestParam String endTime) throws Exception{
EqResult eqResult = new EqResult();
List<KeyValueForDate> list = SplitDateUtil.getKeyValueForDate(startTime,endTime);
if(!list.isEmpty()){
for(KeyValueForDate date : list){
System.out.println("时间段:"+date.getStartDate()+"--至---"+date.getEndDate()+"--转移开始,第一步获取数据...");
EqResult<List<Getstudent>> listEqResult = getStudentService.getStudent(date.getStartDate(),date.getEndDate());
if(CheckUtil.checkEqresultSuccessAndData(listEqResult)){
System.out.println("时间段:"+date.getStartDate()+"--至---"+date.getEndDate()+"--转移开始,第二步转移数据...");
eqResult = indexService.saveStudent(listEqResult.getData());
if(CheckUtil.checkEqresultSuccess(eqResult)){
System.out.println("时间段:"+date.getStartDate()+"--至---"+date.getEndDate()+"--转移完成,判断是否进入下一轮...");
}else{
System.out.println("时间段:"+date.getStartDate()+"--至---"+date.getEndDate()+"--转移失败,第二步未转移数据...");
}
}else{
System.out.println("时间段:"+date.getStartDate()+"--至---"+date.getEndDate()+"--转移失败,第一步未获取到数据...");
}
}
}else{
System.out.println("-----------时间段为空-------------");
}
return eqResult;
}
工具类SplitDateUtil:
public class SplitDateUtil {
@Test
public void demo(){
List<KeyValueForDate> list = SplitDateUtil.getKeyValueForDate("2015-08-23","2016-06-10");
System.out.println("开始日期--------------结束日期");
for(KeyValueForDate date : list){
System.out.println(date.getStartDate()+"-----"+date.getEndDate());
}
}
/**
* 根据一段时间区间,按月份拆分成多个时间段
* @param startDate 开始日期
* @param endDate 结束日期
* @return
*/
@SuppressWarnings("deprecation")
public static List<KeyValueForDate> getKeyValueForDate(String startDate,String endDate) {
List<KeyValueForDate> list = null;
try {
list = new ArrayList<KeyValueForDate>();
String firstDay = "";
String lastDay = "";
Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);// 定义起始日期
Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);// 定义结束日期
Calendar dd = Calendar.getInstance();// 定义日期实例
dd.setTime(d1);// 设置日期起始时间
Calendar cale = Calendar.getInstance();
Calendar c = Calendar.getInstance();
c.setTime(d2);
int startDay = d1.getDate();
int endDay = d2.getDate();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
KeyValueForDate keyValueForDate = null;
while (dd.getTime().before(d2)) {// 判断是否到结束日期
keyValueForDate = new KeyValueForDate();
cale.setTime(dd.getTime());
if(dd.getTime().equals(d1)){
cale.set(Calendar.DAY_OF_MONTH, dd.getActualMaximum(Calendar.DAY_OF_MONTH));
lastDay = sdf.format(cale.getTime());
keyValueForDate.setStartDate(sdf.format(d1));
keyValueForDate.setEndDate(lastDay);
}else if(dd.get(Calendar.MONTH) == d2.getMonth() && dd.get(Calendar.YEAR) == c.get(Calendar.YEAR)){
cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
firstDay = sdf.format(cale.getTime());
keyValueForDate.setStartDate(firstDay);
keyValueForDate.setEndDate(sdf.format(d2));
}else {
cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
firstDay = sdf.format(cale.getTime());
cale.set(Calendar.DAY_OF_MONTH, dd.getActualMaximum(Calendar.DAY_OF_MONTH));
lastDay = sdf.format(cale.getTime());
keyValueForDate.setStartDate(firstDay);
keyValueForDate.setEndDate(lastDay);
}
list.add(keyValueForDate);
dd.add(Calendar.MONTH, 1);// 进行当前日期月份加1
}
if(endDay<startDay){
keyValueForDate = new KeyValueForDate();
cale.setTime(d2);
cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
firstDay = sdf.format(cale.getTime());
keyValueForDate.setStartDate(firstDay);
keyValueForDate.setEndDate(sdf.format(d2));
list.add(keyValueForDate);
}
} catch (Exception e) {
return null;
}
return list;
}
}
实体类KeyValueForDate:
public class KeyValueForDate{
private String startDate;
private String endDate;
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate+" 23:59:59";
}
}
备注,到这里我已经成功解决了所有问题,同时,将我在网上找的解决方案提供参考(未解决我的项目需求):
#限制3000MB大小
spring.http.multipart.max-file-size=3000MB
spring.http.multipart.max-request-size=3000MB
server.max-http-post-size=1048576000
spring.sleuth.keys.http.request-size=1048576000
spring.sleuth.keys.http.response-size=1048576000
server.max-http-header-size=1048576000
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
server.undertow.buffer-size=2048
server.undertow.max-http-post-size=1048576000
# 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region
server.undertow.buffers-per-region=2048
# 是否分配的直接内存(NIO直接分配的堆外内存)
到了这里,你还不点赞吗? 嘻嘻^-^
更多推荐
所有评论(0)