在进行压力测试的时候,我们的系统A 高并发的请求另外一个系统B,是tcp通讯方式。A系统采用Java,B系统用的C语言。在高并发的情况下,跑了一段压力测试,weblogic10被系统给kill掉了。没有堆栈异常现象,后来重现了发现有大量的端口time_wait。根据这样的判断应该是welogic在不断的申请系统资源,而这些端口有没有得到及时的释放。后来在通讯层的代码解决了。
现在对这部分还不是很了解。于是自己写了简单的例子看看这个问题。          //读取流中字节的方法
          private byte[] readMessage(InputStream is) throws IOException{
int bufferSize = 0;
int bufferCapacity = maxbytes;
byte[] b = new byte[bufferCapacity];
int numberRead = 0;
do{
if((numberRead = is.read(b,bufferSize,bufferCapacity - bufferSize)) == -1){
break;
}
bufferSize += numberRead;
if(bufferSize == bufferCapacity){
bufferCapacity = 2 * bufferCapacity;
byte[] newBuffer = new byte[bufferCapacity];
System.arraycopy(b,0,newBuffer,0,bufferSize);
b = newBuffer;
}
}while(true);
//过滤后面的多余字节
while(b[bufferSize - 1] == 0x00){
bufferSize--;
}
byte[] res = new byte[bufferSize];
System.arraycopy(b,0,res,0,res.length);
return res;
}
         //写数据的方法
         private void writeMessage(OutputStream os,byte[] buff) throws IOException{
os.write(buff);
os.flush();
}  服务端的程序:服务端只是接收数据。不发送。package com.haowei.socket.tcp;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;import com.haowei.JavaSocketUtil;public class Server {
public static void main(String[] args) throws IOException {
int count = 0;
ServerSocket server = new ServerSocket(9999);
System.out.println("......服务开启监听.....");
while(true){
Socket socket = server.accept();
new Thread(new ServerThread(String.valueOf(count),socket)).start();
count ++;
}
}
}class ServerThread implements Runnable{
private Socket socket;
private String name;

public ServerThread(String name,Socket socket) {
super();
this.name = name;
this.socket = socket;
}

@Override
public void run() {
System.out.println("线程 [" + name + "]开始执行....");
OutputStream os = null;
InputStream is = null;
byte[] data = null;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
data = JavaSocketUtil.readMessage(socket);
System.out.println("线程 [" + name + "]收到的数据:-->" + new String(data));
// String resp = "我是服务端返回的数据。";
// JavaSocketUtil.writeMessage(socket,resp.getBytes());
} catch (IOException e1) {
e1.printStackTrace();
}
try {
if(socket!=null){
System.out.println("线程[" + name + "]关闭连接。");
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}

}客户端代码:客户端只是发送数据package com.haowei.socket.tcp;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;import com.haowei.JavaSocketUtil;public class Client {
public static void main(String[] args) throws UnknownHostException, IOException{
int count = 0;
while(count<1000){
Socket socket = new Socket("127.0.0.1",9999);
new Thread(new ClientThread(String.valueOf(count),socket)).start();
count ++;
}
}
}class ClientThread implements Runnable{
private Socket socket;
private String name;

public ClientThread(String name,Socket socket) {
super();
this.socket = socket;
this.name = name;
} public void run(){
System.out.println("客户端线程 [" + name + "]开始执行....");
OutputStream os = null;
InputStream is = null;
byte[] data = null;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
String resp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
JavaSocketUtil.writeMessage(socket,resp.getBytes());
// data = JavaSocketUtil.readMessage(socket);
// System.out.println("读取的数据:-->" + new String(data));
} catch (Exception e1) {
e1.printStackTrace();
}
// try {
// socket.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}服务端和客户端程序都采用了多线程,便于进行压力测试。
现在的问题是:我服务端在读取完数据之后关闭socket,而客户端没有关闭,这样的话电脑不会出现time_wait现象。但是从开发的角度去考虑,客户端程序不释放资源是不合理的。但是如果在客户端发送完之后也释放资源,在客户端会出现很多的time_wait。这样的问题很头疼。我们生产上也是这样的现象,我们的A系统是作为客户端程序访问C语言的B系统,B系统也是在发送完响应数据之后进行了关闭连接。而我们在收完数据之后也是关闭连接的。这样就导致我们这边出现大量的time_wait,把我们的系统搞垮了。后来的解决方案是//以下代码是我们请求系统的通讯层处理代码
try{
   //接收完数据
}catch(Exception e){
   //异常处理
}finally{
   //关闭资源。
    if(is!=null&&is.read()==-1){//加上这段代码就OK了。我们的请求系统A,一个time_wait都没有。
         log.debug("服务端关闭了Socket");
    }
    if(is!=null)
       is.close();
    if(socket!=null)
       socket.close();
}
不知道大家有没有碰到这样的问题。

解决方案 »

  1.   

    可能是关闭的次序的问题。似乎先关闭 InputStream 还是 OutputStream 是有讲究的,仅仅是听写 C 程序的人说的,具体原因我也不清楚。也就是要正确地响应 TCP 连接释放的过程。还是去找些 TCP 的书看吧。次序或步骤不正确会导致 Time-wait,而这个time-wait 需要一定的时间才消失(依赖操作系统的设置)。
      

  2.   


    time_wait时间确实在操作系统中有设置,linux下有个配置文件/proc/sys/net/ivp4/tcp_time具体的文件名称不记得了。路径大概就是这个,里面设置了60秒,让操作系统自动关闭的话得两个周期,具体为啥我也不清楚,还有一个就是设置time_wait 重用的参数reuse,加速回收的cycle这几个都是在这个文件夹下配置,reuse为1和cycle为1都是使设置生效,但是因为这样的改动影响比较大,最后就没这么做了。另外,有什么tcp详细介绍的书能推荐一下不,在网上搜的都是些很浅显的东西,也许是自己还不够用心。总之,希望能有个推荐。谢谢。这样更快点嘛。