Axis2 webservice close_wait,java heap space错误的研究

 
Axis2 webservice close_wait,java heap space错误的研究
2009-05-20 16:20
客户端伪代码如下
//主线程方法
while(true){
            test.TestGetServiceStatus();//客户端连接服务端的测试方法
            try{
                Thread.sleep(23 * 1000);//每隔23秒执行下webservice客户端方法
            }catch(Exception e){
                e.printStackTrace();
            }
}

private String wsUrl = "http://127.0.0.1:8080/axis2/services/webservice/";
    public void TestGetServiceStatus(){
        WebserviceStub stub = null;
        try{
            stub = new WebserviceStub(wsUrl);//实例华客户端
            System.out.println("new a stub");
            Thread.sleep(5000);//5秒钟后执行客户端向服务端的请求

            String result = stub.queryServiceStatus(request).getResult();//请求服务端
            System.out.println("result: " + result);
//清除客户端
            stub._getServiceClient().cleanupTransport();
            stub._getServiceClient().cleanup();
            stub.cleanup();
            stub = null;
        }catch(Exception e){
}
    }
步骤解释:
1、主线程每隔23秒调用方法,来实现客户端对服务端的调用
2、客户端在对服务段进行借口调用时:
    2.1、实例化客户端对象
    2.2、睡5秒钟
    2.3、调用服务端接口,得到结果
     2.4、清除客户端
3、服务端的相应接口,收到请求后,睡眠25秒,给出结果。
4、webservice服务端配置文件里,加入连接的存活时间,为20s,如下(axis2.xml):
         class="org.apache.axis2.transport.http.SimpleHTTPServer">
        8080
    20

基于以上的调用,用ethereal抓包得到下图:
(图片看不清楚,可以点击图片进行查看

注意两个绿色框的内容,详细过程分析如下:
1、new stub的时候,客户端与服务端并没有连接;
2、5秒钟后,客户端向服务端发送请求,连接建立,如图的1—7个数据包;
3、测试客户端做出处理,即睡眠25秒,之后返回数据,如图的8—23个数据包;
4、客户端收到数据后,cleanup,方法退出,但是此时看到连接并没有关闭;
5、服务端在20秒后(设置的连接存活时间),断开连接,如图的24,25个数据包;
6、由于客户端这边在25秒的时候(23个数据包所示)退出了方法,过23秒后重新调用测试方法,于是应该在48秒的时候,重新new stub,这个时候,看图知道,在第26个数据包的时候(也就是48秒的时候)客户端发出了先前连接的断开包,至此前一个连接完全释放,开始下一轮的连接循环。
由此可以得出:
1、客户端new stub的时候,并没有与服务端建立连接,而只是释放之前的连接;
2、连接是由服务端先发起的;
3、客户端发送服务端请求的时候,连接由客户端发起,并建立;
由上面的结论可以分析出一个问题:客户端在调用服务端接口方法,并退出后,连接还存在,直到连接存活时间达到服务端设置的连接存活时间后,才被服务端所关闭,这个时候,如果客户端不再重新发起请求,或者客户端出错(内存溢出,无法new stub等),那么之前的那个连接就一直会处在close_wait状态,而无法清除。这就是为什么有些webservice客户端这边,跑了一段时间后,会出现很多close_wait状态的连接的缘故。
    再来看,是什么原因导致了new stub的时候出错的呢?上面也讲到了,虽然可能性有很多,但是有一个却是大家经常犯的,那就是客户端这边内存溢出了。
    很多webservice客户端,在跑了很长时间后,发现内存就不够用了,抛出java heap space的错误,随之而来的就是类似Read Timeout阿等错误,这样close_wait就越来越多,这些错误也会越抛越多……直到整个客户端都无法与服务端取得任何连接,而进入“假死”状态。那么如何避免客户端内存持续走高呢?
    通过jdk自带的jconsole和eclipse提供的memory analyzer可以看到,客户端这边的内存在不断上升,java的gc根本无法释放使用过的内存,而通过memory analyzer可以看到,很多堆内存都在客户端调用服务端的方法里,无法释放(图就不上了)。也就是说,这不是我们实现某功能时自己的原因导致的内存溢出,而是axis2本身的内存溢出。那是不是就没有办法解决了呢?不是的!
    细心的你有没有注意到开篇的时候我提供的客户端的伪代码?里面有四句:
stub._getServiceClient().cleanupTransport();
        stub._getServiceClient().cleanup();
        stub.cleanup();
        stub = null;
当时加这四句代码,只是为了验证客户端时候能把连接主动关闭,可是结果是否定的,但是,恰好是这几句解决了内存溢出的问题!只要在每次客户端调用后,都执行以上四句代码,那么客户端new出来的堆内存资源就可以被java的gc所回收掉了。

你可能感兴趣的:(Webservice)