资讯专栏INFORMATION COLUMN

一次线上问题的排查解决过程

宋华 / 2601人阅读

摘要:排查异常日志,发现没有该问题存在。测试功能正常,没有重现线上问题。解决问题原因定位好了,剩下的就是如何解决了。两个方案修改线上配置该上实施难度系数高,因为公司使用的统一发布部署平台,开发人员无服务器操作权限。

问题

XX系统中,一个用户需要维护的项目数过多,填写的任务数超多,产生了一次工时保存中,只有前面一部分的xx数据持久化到数据库,后面的数据没有保存。

图1

排查过程 1.增加日志,监控参数信息

首先想到的是否后面部分的数据在保存过程中发生了异常。排查异常日志,发现没有该问题存在。

然后增加方法参数信息日志,数据参数信息。发现参数集合size=200,前端发送集合size=400。判断问题可以能是因为服务器容器环境(Nginx+Tomcat)导致

2.开发环境问题重现 2.1 模拟数据

在测试环境模拟线上数据。如图1

2.2 只配置Tomcat

在idea中直接启动tomcat,无nginx环境,如果没有问题,则可暂时确定为nginx问题。

然而,在过程中发现了新的问题。

</>复制代码

  1. 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
  2. at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:833) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  3. at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:576) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  4. at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:553) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  5. at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:914) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  6. at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  7. at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:692) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  8. at org.springframework.validation.DataBinder.doBind(DataBinder.java:588) ~[spring-context-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  9. at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191) ~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]
  10. at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:112) ~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]

查看BeanWrapperImpl源码

</>复制代码

  1. else if (value instanceof List) {
  2. int index = Integer.parseInt(key);
  3. List list = (List) value;
  4. growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1);
  5. value = list.get(index);// 测试报错时,此处list只有256个,index为256时,取第257个报错
  6. }

</>复制代码

  1. @SuppressWarnings("unchecked")
  2. private void growCollectionIfNecessary(
  3. Collection collection, int index, String name, PropertyDescriptor pd, int nestingLevel) {
  4. if (!this.autoGrowNestedPaths) {
  5. return;
  6. }
  7. int size = collection.size();
  8. // 当个数小于autoGrowCollectionLimit这个值时才会向list中添加新元素
  9. if (index >= size && index < this.autoGrowCollectionLimit) {
  10. Class elementType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), nestingLevel);
  11. if (elementType != null) {
  12. for (int i = collection.size(); i < index + 1; i++) {
  13. collection.add(newValue(elementType, name));
  14. }
  15. }
  16. }
  17. }

根据上面的分析找到autoGrowCollectionLimit的定义

</>复制代码

  1. public class DataBinder implements PropertyEditorRegistry, TypeConverter {
  2. /** Default object name used for binding: "target" */
  3. public static final String DEFAULT_OBJECT_NAME = "target";
  4. /** Default limit for array and collection growing: 256 */
  5. public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
  6. private int autoGrowCollectionLimit = DEFAULT_AUTO_GROW_COLLECTION_LIMIT;

解决方案,是在自己的Controller中加入如下方法

</>复制代码

  1. @InitBinder
  2. protected void initBinder(WebDataBinder binder) {
  3. binder.setAutoGrowNestedPaths(true);
  4. binder.setAutoGrowCollectionLimit(1024);
  5. }

==BUT 这个问题和线上的不同,只能算是意外收获。革命尚未成功,同志仍需努力!!!!==

2.3 增加Nginx

经过2.2的奋斗,暂时判定是否为Nginx post请求参数做了限制。嗯,开搞~ 在开发环境配置Nginx代理,过程略·····

nginx.conf 如下

</>复制代码

  1. upstream xxxxxxx {
  2. server 127.0.0.1:8080 weight=10 max_fails=2 fail_timeout=30s ;
  3. }
  4. server {
  5. listen 80;
  6. server_name xxxxxxx.com;
  7. client_max_body_size 100M; # 配置post size
  8. #charset koi8-r;
  9. #access_log logs/host.access.log main;
  10. location / {
  11. #proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
  12. proxy_set_header Host $host;
  13. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  14. proxy_pass http://xxxxxxx;
  15. expires 0;
  16. }
  17. }

对于client_max_body_size 100M;,网上都是与文件上传相关的。不过都是通过post, request body的方式上传数据,所以通用。

测试~~

功能正常,没有重现线上问题。 哭死~~~

革命还要继续~~

2.4 Tomcat post设置

去线上服务器拉去配置

</>复制代码

经分析,发现线上没有body size的配置,却有maxParameterCount="1000"。该参数为限制请求的参数个数,从而变相限制body size。

在开发环境配置该参数,测试,问题重现

3. 解决

问题原因定位好了,剩下的就是如何解决了。

两个方案:

修改线上配置

该上实施难度系数高,因为公司使用的统一发布部署平台,开发人员无服务器操作权限。

修改代码

修改保存逻辑,分片存储

总结

问题排查,需要先对整体有个把握,然后分析影响范围。不能钻牛角尖,采用西医“头疼医头”的方式。有可能最后结果还是要医头,但此时的医头已经是建立在中医的辩证主义上,对症下药。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71050.html

相关文章

  • 一次线上问题排查解决过程

    摘要:排查异常日志,发现没有该问题存在。测试功能正常,没有重现线上问题。解决问题原因定位好了,剩下的就是如何解决了。两个方案修改线上配置该上实施难度系数高,因为公司使用的统一发布部署平台,开发人员无服务器操作权限。 问题 XX系统中,一个用户需要维护的项目数过多,填写的任务数超多,产生了一次工时保存中,只有前面一部分的xx数据持久化到数据库,后面的数据没有保存。 图1 showImg(htt...

    airborne007 评论0 收藏0
  • 一次线上问题排查解决过程

    摘要:排查异常日志,发现没有该问题存在。测试功能正常,没有重现线上问题。解决问题原因定位好了,剩下的就是如何解决了。两个方案修改线上配置该上实施难度系数高,因为公司使用的统一发布部署平台,开发人员无服务器操作权限。 问题 XX系统中,一个用户需要维护的项目数过多,填写的任务数超多,产生了一次工时保存中,只有前面一部分的xx数据持久化到数据库,后面的数据没有保存。 图1 showImg(htt...

    HollisChuang 评论0 收藏0
  • 一次线上问题排查所引发思考

    摘要:直到有一天你会碰到线上奇奇怪怪的问题,如线程执行一个任务迟迟没有返回,应用假死。正好这次借助之前的一次生产问题来聊聊如何排查和解决问题。本地模拟上文介绍的是线程相关问题,现在来分析下内存的问题。尽可能的减少多线程竞争锁。 showImg(https://segmentfault.com/img/remote/1460000015568421?w=2048&h=1150); 前言 之前或...

    levy9527 评论0 收藏0
  • 一次线上频繁FGC事件和解决方式

    摘要:直接显示了一个疑似内存泄漏的问题。然后分析文件给出的信息,发现一个叫的类。文件里面说的内存泄漏的大概的意思就是说,这个类里面的存放的东西太多了,爆掉了。修改了代码将调用的地方改成了单例。修改完线上跑了一段日子,后来也没有出现过这样的问题。 问题描述:     早上去公司上班,突然就邮件一直报警,接口报异常,然后去查服务器的运行情况,发现java的cpu爆了.接着就开始排查问题 问题解决...

    Alliot 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<