axis2开发webservice_docker映射出来端口访问不了

axis2开发webservice_docker映射出来端口访问不了记录一次正式环境服务报错排查记录。某日被通知线上服务告警,错入日志全是Timeoutwaitingforconnection首先梳理项目架构,项目很简单,就是一个使用axis2构建的webserice的客户端开始从此段报错入手排查,定位到MultiThreadedHttpConnectionManager这个类的doGetConnection方法privateHttpConnectiondoGetConnection(HostConfigurationhostCo.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

记录一次正式环境服务报错排查记录。

某日被通知线上服务告警,错误日志全是 Timeout waiting for connection

axis2开发webservice_docker映射出来端口访问不了

首先梳理项目架构,项目很简单,就是一个使用axis2构建的webserice的客户端, Axis2版本为1.5.5

开始从此段报错入手排查,定位到 MultiThreadedHttpConnectionManager 这个类的 doGetConnection 方法

private HttpConnection doGetConnection(HostConfiguration hostConfiguration, 
        long timeout) throws ConnectionPoolTimeoutException {

        HttpConnection connection = null;

        int maxHostConnections = this.params.getMaxConnectionsPerHost(hostConfiguration);
        int maxTotalConnections = this.params.getMaxTotalConnections();
        
        synchronized (connectionPool) {

            // we clone the hostConfiguration
            // so that it cannot be changed once the connection has been retrieved
            hostConfiguration = new HostConfiguration(hostConfiguration);
            HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration, true);
            WaitingThread waitingThread = null;

            boolean useTimeout = (timeout > 0);
            long timeToWait = timeout;
            long startWait = 0;
            long endWait = 0;

            while (connection == null) {

                if (shutdown) {
                    throw new IllegalStateException("Connection factory has been shutdown.");
                }
                
                // happen to have a free connection with the right specs
                //
                if (hostPool.freeConnections.size() > 0) {
                    connection = connectionPool.getFreeConnection(hostConfiguration);

                // have room to make more
                //
                } else if ((hostPool.numConnections < maxHostConnections) 
                    && (connectionPool.numConnections < maxTotalConnections)) {

                    connection = connectionPool.createConnection(hostConfiguration);

                // have room to add host connection, and there is at least one free
                // connection that can be liberated to make overall room
                //
                } else if ((hostPool.numConnections < maxHostConnections) 
                    && (connectionPool.freeConnections.size() > 0)) {

                    connectionPool.deleteLeastUsedConnection();
                    connection = connectionPool.createConnection(hostConfiguration);

                // otherwise, we have to wait for one of the above conditions to
                // become true
                //
                } else {
                    // TODO: keep track of which hostConfigurations have waiting
                    // threads, so they avoid being sacrificed before necessary

                    try {
                        
                        if (useTimeout && timeToWait <= 0) {
                            throw new ConnectionPoolTimeoutException("Timeout waiting for connection");
                        }
                        
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("Unable to get a connection, waiting..., hostConfig=" + hostConfiguration);
                        }
                        
                        if (waitingThread == null) {
                            waitingThread = new WaitingThread();
                            waitingThread.hostConnectionPool = hostPool;
                            waitingThread.thread = Thread.currentThread();
                        } else {
                            waitingThread.interruptedByConnectionPool = false;
                        }
                                    
                        if (useTimeout) {
                            startWait = System.currentTimeMillis();
                        }
                        
                        hostPool.waitingThreads.addLast(waitingThread);
                        connectionPool.waitingThreads.addLast(waitingThread);
                        connectionPool.wait(timeToWait);
                    } catch (InterruptedException e) {
                        if (!waitingThread.interruptedByConnectionPool) {
                            LOG.debug("Interrupted while waiting for connection", e);
                            throw new IllegalThreadStateException(
                                "Interrupted while waiting in MultiThreadedHttpConnectionManager");
                        }
                        // Else, do nothing, we were interrupted by the connection pool
                        // and should now have a connection waiting for us, continue
                        // in the loop and let's get it.
                    } finally {
                        if (!waitingThread.interruptedByConnectionPool) {
                            // Either we timed out, experienced a "spurious wakeup", or were
                            // interrupted by an external thread.  Regardless we need to 
                            // cleanup for ourselves in the wait queue.
                            hostPool.waitingThreads.remove(waitingThread);
                            connectionPool.waitingThreads.remove(waitingThread);
                        }
                        
                        if (useTimeout) {
                            endWait = System.currentTimeMillis();
                            timeToWait -= (endWait - startWait);
                        }
                    }
                }
            }
        }
        return connection;
    }

 得到几个关键变量:

        连接池最大连接数 maxTotalConnections=20;

当前连接主机(或相同主机)最大连接数 maxHostConnections=2;

连接池总空闲连接数 connectionPool.freeConnections;

当前连接主机空闲连接数 hostPool.freeConnections;

 

得到结论一:

当前主机连接数达到最大值,且当前连接主机空闲连接数为0时,获取连接超时时会抛出 Timeout waiting for connection 异常。

 

到此,初步怀疑某次请求时未正常释放占用的连接,或未回收到空闲连接池中。

继续排查日志,一直找到第一次抛出 Timeout waiting for connection 异常的时候再往上查看还有没有其他错误日志。于是发现了 Transport error: 503 Error: Service Unavailable 这个异常

axis2开发webservice_docker映射出来端口访问不了

直接进入源码

/**
     * Used to handle the HTTP Response
     *
     * @param msgContext - The MessageContext of the message
     * @param method     - The HTTP method used
     * @throws IOException - Thrown in case an exception occurs
     */
    private void handleResponse(MessageContext msgContext,
                                HttpMethodBase method) throws IOException {
        int statusCode = method.getStatusCode();
        log.trace("Handling response - " + statusCode);
        if (statusCode == HttpStatus.SC_OK) {
            // Save the HttpMethod so that we can release the connection when cleaning up
            msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
            processResponse(method, msgContext);
        } else if (statusCode == HttpStatus.SC_ACCEPTED) {
            // Since we don't expect any content with a 202 response, we must release the connection
            method.releaseConnection();
        } else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR ||
                statusCode == HttpStatus.SC_BAD_REQUEST) {
            // Save the HttpMethod so that we can release the connection when cleaning up
            msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
            Header contenttypeHeader =
                    method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
            String value = null;
            if (contenttypeHeader != null) {
                value = contenttypeHeader.getValue();
            }
            OperationContext opContext = msgContext.getOperationContext();
            if(opContext!=null){
                MessageContext inMessageContext =
                        opContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                if(inMessageContext!=null){
                    inMessageContext.setProcessingFault(true);
                }
            }
            if (value != null) {

                processResponse(method, msgContext);
            }
            Object isTransportNonBlocking = msgContext.getProperty(
                    MessageContext.TRANSPORT_NON_BLOCKING);
            if (isTransportNonBlocking != null && (Boolean)isTransportNonBlocking) {
                throw new AxisFault(Messages.getMessage("transportError",
                        String.valueOf(statusCode),
                        method.getStatusText()));
            }
        } else {
            throw new AxisFault(Messages.getMessage("transportError",
                    String.valueOf(statusCode),
                    method.getStatusText()));
        }
    }

根据我之前读的源码我知道 method.releaseConnection(); 这个方法将会最终调用 connectionPool.freeConnection(conn); 即生成空闲连接放入总连接池中。

而 msgContext.setProperty(HTTPConstants.HTTP_METHOD, method); 这个方法将由其他地方获取调用并最终调用的仍是 method.releaseConnection();

综上可知 返回码为503或者任意其他上述代码中未处理的返回码时都不会将占用连接重置为空闲连接放入总连接池中。

 

到此可知服务告警原因:

因为服务端发生了我们未知的操作,导致客户端获取请求时的返回码为503而占用了所有的当前主机连接数(2个)而不会释放重置为空闲连接放入连接池

于是后续连接从连接池获取连接时均超时抛出异常 Timeout waiting for connection

 

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194542.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java 的double转BigDecimal的坑

    java 的double转BigDecimal的坑大家都知道java的double由于精度问题会给你挖无数个坑,一般采取的方式都会避免使用,但是android的dbflow对model里面的BigDecimal转换为sqlitetable时,fieldtype居然是text.所以,model里面field的属性只能保持double那么,先测试一下:doubled=3.1415;…

    2022年5月27日
    43
  • pycharm双击打不开_pycharm社区版双击没反应

    pycharm双击打不开_pycharm社区版双击没反应方法一:出现这个问题应该是想永久使用pycharm然后修改了pycharm的Help”->“EditCustomVMOptions文件,导致打不开pycharm,无论怎么下载重新下载还是打不开,原因就是我们所修改的文件,在最后一行添加路径的时候出现了错误。打开C盘用户名下的文件夹,按图中步骤找到pycharm,打开.vmoptions文件,删除最下面这一行自己添加的语句,。然后重启pycharm就可以了。方法二:我们可以在Windows10系统的开始菜单上,单击

    2022年8月27日
    6
  • 【18】进大厂必须掌握的面试题-15个Kafka面试

    【18】进大厂必须掌握的面试题-15个Kafka面试

    2020年11月14日
    223
  • CPU后缀字母性能[通俗易懂]

    CPU后缀字母性能[通俗易懂]Intel桌面级CPUK代表此款CPU是不锁倍频的,是可以超频的,用户可以通过超频来提升CPU性能(需要搭配可超频的主板)。X:intel带X的CPU很少,是extreme,也就是代表着“极限“。只有当时intel的旗舰级CPU才有可能带X,代表同一时代性能最强的CPU。C:在Broadwell酷睿的时代,Intel搞出的一个新花样。代表了反CPU性能发展规律:CPU性能退步/最强集显GP…

    2022年5月30日
    51
  • 单片机之IIC通信协议「建议收藏」

    单片机之IIC通信协议「建议收藏」概念I2C(IIC,Inter-IntegratedCircuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。硬件IIC:硬件IIC速度比模拟快,并且可以用DMA。硬件IIC会自动匹配与从机的通信时序,…

    2022年6月9日
    53
  • 源码网_python源码从哪下载

    源码网_python源码从哪下载源码目录结构我们首先来看下models.py的代码结构我们可以看到这个模块中定义了12个属性和22个模型类,我们依次来看属性源码分析importosfromenumimportEnu

    2022年7月30日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号