题目
XX体系中,一个用户须要保护的项目数过量,填写的使命数超多,产生了一次工时保留中,只要前面一部份的xx数据耐久化到数据库,背面的数据没有保留。
图1
排查历程
1.增添日记,监控参数信息
起首想到的是不是背面部份的数据在保留历程当中发生了非常。排查非常日记,发明没有该题目存在。
然后增添要领参数信息日记,数据参数信息。发明参数鸠合size=200,前端发送鸠合size=400。推断题目能够能是由于服务器容器环境(Nginx+Tomcat)致使
2.开辟环境题目重现
2.1 模仿数据
在测试环境模仿线上数据。如图1
2.2 只设置Tomcat
在idea中直接启动tomcat,无nginx环境,假如没有题目,则可临时确定为nginx题目。
但是,在历程当中发明了新的题目。
org.springframework.beans.InvalidPropertyException: Invalid property 'detail[256]' of bean class [com.suning.asvp.mer.entity.InviteCooperationInfo]: Index of out of bounds in property path 'detail[256]'; nested exception is java.lang.IndexOutOfBoundsException: Index: 256, Size: 256
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:833) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:576) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:553) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:914) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:692) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.validation.DataBinder.doBind(DataBinder.java:588) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191) ~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:112) ~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]
检察BeanWrapperImpl源码
else if (value instanceof List) {
int index = Integer.parseInt(key);
List list = (List) value;
growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1);
value = list.get(index);// 测试报错时,此处list只要256个,index为256时,取第257个报错
}
@SuppressWarnings("unchecked")
private void growCollectionIfNecessary(
Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
if (!this.autoGrowNestedPaths) {
return;
}
int size = collection.size();
// 当个数小于autoGrowCollectionLimit这个值时才会向list中增加新元素
if (index >= size && index < this.autoGrowCollectionLimit) {
Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
if (elementType != null) {
for (int i = collection.size(); i < index + 1; i++) {
collection.add(newValue(elementType, name));
}
}
}
}
依据上面的剖析找到autoGrowCollectionLimit的定义
public class DataBinder implements PropertyEditorRegistry, TypeConverter {
/** Default object name used for binding: "target" */
public static final String DEFAULT_OBJECT_NAME = "target";
/** Default limit for array and collection growing: 256 */
public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
private int autoGrowCollectionLimit = DEFAULT_AUTO_GROW_COLLECTION_LIMIT;
处理计划,是在本身的Controller中到场以下要领
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setAutoGrowNestedPaths(true);
binder.setAutoGrowCollectionLimit(1024);
}
==BUT 这个题目和线上的差别,只能算是不测收成。反动还没有胜利,同道仍需勤奋!!!!==
2.3 增添Nginx
经由2.2的斗争,临时剖断是不是为Nginx post要求参数做了限定。嗯,开搞~ 在开辟环境设置Nginx代办,历程略·····
nginx.conf 以下
upstream xxxxxxx {
server 127.0.0.1:8080 weight=10 max_fails=2 fail_timeout=30s ;
}
server {
listen 80;
server_name xxxxxxx.com;
client_max_body_size 100M; # 设置post size
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://xxxxxxx;
expires 0;
}
}
关于client_max_body_size 100M;
,网上都是与文件上传相干的。不过都是经由过程post, request body的体式格局上传数据,所以通用。
测试~~
功用一般,没有重现线上题目。 哭死~~~
反动还要继承~~
2.4 Tomcat post设置
去线上服务器拉去设置
<Connector port="1601" maxParameterCount="1000" protocol="HTTP/1.1" redirectPort="8443" maxSpareThreads="750" maxThreads="1000" minSpareTHreads="50" acceptCount="1000" connectionTimeout="20000" URIEncoding="utf-8"/>
经剖析,发明线上没有body size的设置,却有maxParameterCount="1000"
。该参数为限定要求的参数个数,从而变相限定body size。
在开辟环境设置该参数,测试,题目重现。
3. 处理
题目缘由定位好了,剩下的就是怎样处理了。
两个计划:
- 修正线上设置
该上实行难度系数高,由于公司运用的一致宣布布置平台,开辟人员无服务器操纵权限。
- 修正代码
修正保留逻辑,分片存储
总结
题目排查,须要先对团体有个把握,然后剖析影响局限。不能钻牛角尖,采纳西医“头疼医头”的体式格局。有能够末了效果照样要医头,但此时的医头已经是建立在中医的辩证主义上,对症下药。