NutzCN Logo
问答 Nutz web 接口请求,有5% 左右改了 端口连接,报java.net.SocketException: Connection reset by peer: socket write error
发布于 17天前 作者 hui453694187 169 次浏览 复制 上一个帖子 下一个帖子
标签: nutzwk

下面这个异常, 我生产上 偶发性,出现, 大概百分之 几,导致请求 超时,请问这个是什么原因? 烦不胜烦,导致页面卡顿请求超时,
每个接口都有几率会 连接重置, 搜了一大圈,没找到有人说个所以然的

[http-bio-8001-exec-2932] WARN  org.nutz.mvc.impl.processor.FailProcessor - Error@/pc/order/***** :
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
	at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:367)
	at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:331)
	at org.apache.catalina.connector.Response.flushBuffer(Response.java:594)
	at org.apache.catalina.connector.ResponseFacade.flushBuffer(ResponseFacade.java:306)
	at org.nutz.mvc.Mvcs.write(Mvcs.java:294)
	at org.nutz.mvc.view.UTF8JsonView.render(UTF8JsonView.java:68)
	at org.nutz.mvc.impl.processor.ViewProcessor.process(ViewProcessor.java:66)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:33)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:58)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:123)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
	at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
	at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
	at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:44)
	at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:67)
	at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:31)
	at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at com.liqi.health.cloudhospital.system.filter.EncodingFilter.doFilter(EncodingFilter.java:36)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketException: Connection reset by peer: socket write error
	at java.net.SocketOutputStream.socketWrite0(Native Method)
21 回复

其实没啥, 就是浏览器/客户端提前中断了连接, 并不属于服务器异常

不过呢, 有一种特例, 就是发ajax请求, 又直接提交了, 表现就是提交了两次. 通常是$("xxx").click的回调没返回false.

一开始,我跟客户说是网络不稳定导致的, 后面客户 从客户机 ping 服务器, ping 包一直稳定的, 但是后面还是没解决,每天都会有几率发生, 前端是用 ajax 请求的, 请问 这样写 会造成,上面这个问题吗?

$msg.loading();
var ajaxTimeoutTest = $.ajax({
        url: url, //请求的URL
        timeout: 40000, //超时时间设置,单位毫秒
        type: 'get', //请求方式,get或post
        data: data, //请求所传参数,json格式
        dataType: 'json',//返回的数据格式
        success: function (data) { //请求成功的回调函数
            if (callback) callback(data);
        },
        complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
            if (status == 'timeout') {//超时
                ajaxTimeoutTest.abort();
            }
            console.log("请求结果:"+status);
            if(status !== 'success'){
                $msg.error('失败!['+status+'][readyState:'+XMLHttpRequest.readyState +']' +
                    '[status:'+XMLHttpRequest.status+"]" +
                    "[statusText:" + XMLHttpRequest.statusText+']',5000);
            }
            $msg.closeLoading();
        }
    });

$.ajax语句之后,加个return false

这是onClick事件的回调?这代码缺外面的一层没贴

报错的请求,并不都是点击事件发起请求导致的, 有点击事件, 也有下面这种 src 里面直接请求后端资源的 也报这异常的

<img class="reportPic"
                         src="${ContextPath}/pc/inspectPrintTemplate/decodeReportPic?inspectionNo=${obj.inspectionNo}&index=${page}"/>

然后还有 这种 在页面加载 之后就触发的 ajax请求 的也有出现请求之后,后端报这个异常的。

   $F.POSTLoading($C.apiPath + '/pc/pay/siPay/sendFY005', param, function (data) {
          // 请求收到响应后的处理 逻辑
    });
// 下面 这个是 公共的 ajax 请求 封装
F.POSTLoading = function (url, data, callback) {
    $msg.loading();
    var ajaxTimeoutTest = $.ajax({
        url: url, //请求的URL
        timeout: 40000, //超时时间设置,单位毫秒
        type: 'post', //请求方式,get或post
        data: data, //请求所传参数,json格式
        dataType: 'json',//返回的数据格式
        success: function (data) { //请求成功的回调函数     
                if (callback) callback(result1);
        },
        complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
            if (status == 'timeout') {//超时,status还有success,error等值的情况
                ajaxTimeoutTest.abort();
            }
            console.log("请求结果:"+status);
            //debugout.log("响应头状态:"+status);
            //debugout.log("响应体:"+XMLHttpRequest.readyState +'- '+XMLHttpRequest.status+" - " + XMLHttpRequest.statusText);
            if(status !== 'success'){
                $msg.error('失败!['+status+'][readyState:'+XMLHttpRequest.readyState +']' +
                    '[status:'+XMLHttpRequest.status+"]" +
                    "[statusText:" + XMLHttpRequest.statusText+']',5000);
            }
            $msg.closeLoading();
        }
    });
};

用的 一个类似 vue 的框架,绑定 页面点击事件

<td width="100">
    <button :click="@mzFeePay" >自费</button>
 </td>

这种点击后发起 的请求

mzFeePay: function () {
            $F.POSTLoading($C.apiPath + 'pc/mzfee/createOrder', {isInsurance: 0}, function (res) {
                // 收到请求后的 逻辑
            });
        }
    }

所以,我猜测, 应该 跟点击事件 回调 return false 关系不大 , 这个retren false 是反正 用户手抖的处理吧?
大佬,还有其他解决思路或者方向吗, 我除了网络问题,真想不到还有什么原因导致这异常了

不是手抖,是终止冒泡

有没有规律的?总是这个url报错吗?

我把日志看了一遍, 没发现啥规律, 并不是特定 url 报这个错, 很多个 url 都报,一天下来出现 二十多次这个异常, 非得说规律....报错的url 都是 后台的接口 ,加了 @At注解的,但是感觉应该跟这没关系 o(╥﹏╥)o , 有可能是 机器性能问题吗?Tomcat 配置,并发? 因为 这个错误之前基本没有, 最近老是出现, 并且,我没什么大的版本更新

后台接口都是UTF8JsonView吗?

机器内存多少?剩余多少?考虑把LogPosscor加上呗,会打印每个入口方法的耗时。 nutzbook有相关代码

大部分 是 @ok("json") 也有 @Ok("raw:jpg") , 机器有八个G 内存, 最繁忙的时候,剩余内存我看也差不多有两个G .

我去看看 nutzbook 项目 的代码先, 看怎么加 LogPosscor 日志, 这个是Nutz 的只带的吗? 打印 入口方法耗时

https://gitee.com/wendal/nutz-book/tree/master/cn/logsystem

是这个里面的吗? 似乎没看到有 说怎么加上 LogPosscor 打印入口方法耗时的

已经更新了,明天观察一下

这一段时间观察日志, 发现 绝大部分 接口 耗时都不超过 2秒

2019-11-12 09:20:44,6173487] ERROR LogTimeProcessor - java.net.SocketException: Connection reset by peer: socket write error
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
	at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:367)
	at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:331)
	at org.apache.catalina.connector.Response.flushBuffer(Response.java:594)


2019-11-12 15:33:49,780 LogTimeProcessor inspectPrintTemplate/printView 60032ms

org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
2019-11-12 08:40:11,3803458] [POST]URI=/pc/freshTime 16255ms
[POST]URI=/pc/order/orderPaySuccess 68469ms


LogTimeProcessor - java.net.SocketException: Connection reset by peer: socket write error
org.apache.catalina.connector.ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error
2019-11-12 16:51:45,7893676] [POST]URI=/pc/printView 62389ms

2019-11-12 16:05:38,7243583] ERROR LogTimeProcessor - java.net.SocketException: Connection reset by peer: socket write error
2019-11-12 16:05:38,7253583] [POST]URI=//pc/pay/siPay/sendMZ002 100199ms


2019-11-12 15:33:49,7793630] ERROR LogTimeProcessor - java.net.SocketException: Connection reset by peer: socket write error
2019-11-12 15:33:49,7803630] [POST]URI=/pc/inspectPrintTemplate/printView 60032ms

2019-11-12 16:05:38,7243583] ERROR LogTimeProcessor - java.net.SocketException: Connection reset by peer: socket write error
2019-11-12 16:05:38,7253583] [POST]URI=/pc/sendMZ002 100199ms

异常后面的接口 方法耗时, 好像确实 都是很久, 超过一分钟了 , 我还是没找到原因,为什么 一样的 接口, 偶尔耗时这么久,然后抛出 连接断开的异常 ....
@wendal

系统繁忙, 数据库连接池满了?

@wendal 大佬, 我现在怀疑是 ,数据库 这方面的问题, 数据库连接池满了 会抛异常信息吗, 因为我没看到 有 数据库方面的异常日志 , 我是用的 nutz + Mysql + c3p0 数据库连接池
这个是我的配置。

dataSource: {
        type: "com.mchange.v2.c3p0.ComboPooledDataSource",
        events: {
            depose: "close"
        },
        fields: {
            driverClass: {java: "$config.get('db-driver')"},
            jdbcUrl: {java: "$config.get('db-url')"},
            user: {java: "$config.get('db-username')"},
            password: {java: "$config.get('db-password')"},
            minPoolSize: 5,
            initialPoolSize: 10,
            maxPoolSize: 100,
            testConnectionOnCheckin: true,
            automaticTestTable: "C3P0TestTable",
            idleConnectionTestPeriod: 18000,
            maxIdleTime: 300,
            maxStatements: 0,
            numHelperThreads: 5
        }
    },

其实一样的配置, 一个月之前是没这些问题, 我也怀疑,是不是 数据库,数据量大了,导致接口处理时间偶尔会很长,还是数据库的连接被阻塞了?

现在的情况是, 客户端出现卡顿,是全部一起卡顿的 ,然后大概 一分钟之后,客户端刷新一下就恢复正常了, 隔 一个小时或者半个小时 左右 出现一次......

maxPoolSize 改到500,my.cnf/my.ini也同步改一下

ok,谢谢 ,我改了,再继续观察,

我看日志有个问题很不解, 这个接口 用时 20秒, 但是,我看日志,应该是 判断了空,马上返回的,请问这有可能慢在哪个地方了, 日志 和 接口 的代码,我都贴出来了。

2019-11-13 12:31:10,491 [http-bio-8001-exec-4160] INFO  com.common.module.PCModule - 回调updateTerminalDeviceStatus事件,参数为:deviceCode:{null},status:{0},detail{null}

2019-11-13 12:31:10,491 [http-bio-8001-exec-4160] DEBUG com.LogTimeProcessor - [POST]URI=/pc/updateTerminalDeviceStatus 20015ms

下面是对应 的 入口方法 updateTerminalDeviceStatus , 看日志, deveiceCode 为 null 应该直接 返回了,为什么还会 耗时 20 秒 ?? Nutz 里面 过滤器有做些什么操作吗?

    @At
    @Ok("json")
    public Map<String, Object> updateTerminalDeviceStatus(@Param("deviceCode") String deviceCode,
                                                          @Param("status") int status, @Param("detail") String detail) {
        Map<String, Object> result = new HashMap<String, Object>();

        log.info("回调updateTerminalDeviceStatus事件,参数为:deviceCode:{" + deviceCode + "},status:{"
                + status + "},detail{" + detail + "}");
	// deveiceCode 为null 直接 return 。
        if (deviceCode == null || deviceCode.trim().equals("")) {
            result.put(IConstants.RESULT_CODE_KEY, IConstants.RESULT_CODE_FAILURE);
            result.put(IConstants.RESULT_MESSAGE_KEY, "获取IP失败");
            return result;
        }

	......
        
        return result;
    }

类似的情况我发现挺多的, 接口里面的逻辑执行时间不长,但是 整个 接口, 响应时间却 很长....

下面这个 接口, 压根没有什么耗时的操作, 也要20 秒才返回 ......

2019-11-13 12:31:08,244 [http-bio-8001-exec-4284] DEBUG com.LogTimeProcessor - [POST]URI=/pc/mzfee/saveMzfeeRecordInSession 20015ms
    @At
    @Ok("json")
    public Map<String, Object> saveRecordInSession(
            @Param("..") Record record,
            @Param("canUseInsurance") String canUseInsurance,
            HttpSession session) {
        Map<String, Object> response = new HashMap<>();
        if (session.getAttribute(MainModule.CURRENT_PATIENT) == null) {
            response.put(IConstants.RESULT_CODE_KEY, IConstants.RESULT_CODE_FAILURE);
            response.put(IConstants.RESULT_MESSAGE_KEY, "用户未登陆,请重新登陆");
            return response;
        }
        record.setIsInsurance(canUseInsurance);
        session.setAttribute(MainModule.CURRENT_RECORD, record);
        response.put(IConstants.RESULT_CODE_KEY, IConstants.RESULT_CODE_SUCCESS);
        response.put(IConstants.RESULT_MESSAGE_KEY, "保存成功");
        return response;
    }
添加回复
请先登陆
回到顶部