在Mac上使用Apache HttpClient 4.5进行“连接重置”异常

时间:2015-10-27 19:01:53

标签: java macos apache httpclient apache-httpclient-4.x

我需要启动 1000 个线程来同时发送HTTP请求。然而,在Mac上我似乎遇到了一些限制,这导致Apache HTTPClient返回异常:

INFO: I/O exception (java.net.SocketException) caught when processing request to {}->http://my.url:80: Connection reset

限制似乎介于200到300个并发连接之间。

我创建了一个简单的应用程序,即使使用该应用程序也可以重现该问题:

import java.io.IOException;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class App implements Runnable
{
    private static final int NUMBER_THREADS = 1000;

    public static void main( String[] args )
    {
        Thread[] threads = new Thread[NUMBER_THREADS];
        for(int i = 0; i < NUMBER_THREADS; i++)
        {
            threads[i] = new Thread(new App()); 
        }
        for(int i = 0; i < NUMBER_THREADS; i++)
        {
            threads[i].start(); 
        }
    }

    public void run() 
    {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet("http://my.url/test.html");
        CloseableHttpResponse response = null;
        try 
        {
            System.out.println( System.nanoTime() + " " + Thread.currentThread().getName() + " started" );
            response = httpclient.execute(httpget);
            System.out.println( System.nanoTime() + " " + Thread.currentThread().getName() + " finished" );
        } 
        catch (ClientProtocolException e) 
        {
            e.printStackTrace();
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        } 
        finally 
        {
            try 
            {
                if(response != null)
                {
                    response.close();
                }
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }
}

我更新了一些Mac设置,但这没有任何帮助:

> sysctl -a | grep files
kern.maxfiles = 12288
kern.maxfilesperproc = 10240
kern.maxfiles: 12288
kern.maxfilesperproc: 10240
kern.num_files: 3202
> ulimit -n 10240
> ulimit -n
10240
> sysctl -a | grep somax
kern.ipc.somaxconn: 128
> sudo sysctl -w kern.ipc.somaxconn=2048
Password:
kern.ipc.somaxconn: 128 -> 2048
> sysctl -a | grep somax
kern.ipc.somaxconn: 2048

所以我想知道这个限制来自哪里? OsX / Apache HttpClient本身?是否可以控制它?

提前致谢。

1 个答案:

答案 0 :(得分:1)

问题确实存在于maxfiles中,但我没有正确地改变它们。 This文章通过在Mac OS X Yosemite / El Capitan上显示更新文件限制的正确程序帮助我解决了这个问题。

  1. 创建和更新/Library/LaunchDaemons/limit.maxfiles.plist文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
      <plist version="1.0">
        <dict>
          <key>Label</key>
            <string>limit.maxfiles</string>
          <key>ProgramArguments</key>
            <array>
              <string>launchctl</string>
              <string>limit</string>
              <string>maxfiles</string>
              <string>65536</string>
              <string>65536</string>
            </array>
          <key>RunAtLoad</key>
            <true/>
          <key>ServiceIPC</key>
            <false/>
        </dict>
      </plist>
    
  2. 创建/Library/LaunchDaemons/limit.maxproc.plist文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
      <plist version="1.0">
        <dict>
          <key>Label</key>
            <string>limit.maxproc</string>
          <key>ProgramArguments</key>
            <array>
              <string>launchctl</string>
              <string>limit</string>
              <string>maxproc</string>
              <string>2048</string>
              <string>2048</string>
            </array>
          <key>RunAtLoad</key>
            <true />
          <key>ServiceIPC</key>
            <false />
        </dict>
    

  3. 使用以下行添加.bashprofile:

    ulimit -n 65536
    ulimit -u 2048
    
  4. 重新启动系统