HttpClient请求成功,定义了超时,但没有挂起

jah*_*ezz 2 java rest timeout apache-httpclient-4.x

我找到了一种修复我的代码的奇怪的黑客方式,我想知道是否有人可以解释它为什么有效.我正在编写与REST API通信的代码,以将视频文件上传到多个HTTP请求中.

我的一个视频部分请求连接有问题,但从未响应.该程序分五个部分上传视频,但它总是挂在五个部分的第三部分.我决定添加一个请求硬超时来强制程序跳过那个悬挂部分.好吧,加入那个计时器后神奇地说,没有更多的挂断!

任何想法为什么会这样?请求实际上并没有超时,但添加此代码可以保持程序的正常运行.

private void uploadParts(String assetId) throws IOException {
    //set up post request
    HttpClient client = HttpClientBuilder.create().build();

    String url = "";

    //prepare video
    File video = new File("files/video.mp4");
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(video));

    int partMaxSize = 1024 * 1024 * 5;
    byte[] buffer = new byte[partMaxSize];
    double fileSize = video.length();
    System.out.println(fileSize);
    System.out.println(fileSize / partMaxSize);
    int parts = (int) Math.ceil(fileSize / partMaxSize);
    System.out.println(parts);

    for(int i = 1; i < parts+1; i++)    {
        String partNumber = i + "";
        System.out.println("part: " + partNumber);
        int partSize = (int) (i < parts ? partMaxSize : fileSize);
        fileSize -= partSize;
        int tmp = 0;
        tmp = bis.read(buffer);
        url = String.format("https://www.site.com/upload/multipart/%s/%s", assetId, partNumber);

        final HttpPut request = new HttpPut(url);
        request.addHeader("Authorization", "Bearer " + accessToken);
        request.addHeader("Content-Type", "application/octet-stream");
        request.setEntity(new ByteArrayEntity(buffer));

        //Magical code start
        int hardTimeout = 5; // seconds
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                if (request != null) {
                    request.abort();
                }
            }
        };
        new Timer(true).schedule(task, hardTimeout * 1000);
        //Magical code end

        HttpResponse response = client.execute(request);
        System.out.println(response.getStatusLine().getReasonPhrase());
    }
    bis.close();
}
Run Code Online (Sandbox Code Playgroud)

如果我遗漏魔法代码部分,我的代码挂在第三部分.如果我包括它,该程序运行良好.

jah*_*ezz 6

我找到了答案!原来HttpClient一次只允许一定数量的连接.根据我的代码,默认的最大连接数为2.我需要在完成后关闭每个连接并且上传运行正常.

固定代码添加了请求连接释放.

private void uploadParts(String assetId) throws IOException {
    //set up post request
    HttpClient client = HttpClientBuilder.create().build();

    String url = "";

    //prepare video
    File video = new File("files/video.mp4");
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(video));

    int partMaxSize = 1024 * 1024 * 5;
    byte[] buffer = new byte[partMaxSize];
    double fileSize = video.length();
    System.out.println(fileSize);
    System.out.println(fileSize / partMaxSize);
    int parts = (int) Math.ceil(fileSize / partMaxSize);
    System.out.println(parts);

    for(int i = 1; i < parts+1; i++)    {
        String partNumber = i + "";
        System.out.println("part: " + partNumber);
        int partSize = (int) (i < parts ? partMaxSize : fileSize);
        fileSize -= partSize;
        int tmp = 0;
        tmp = bis.read(buffer);
        url = String.format("https://www.site.com/upload/multipart/%s/%s", assetId, partNumber);

        final HttpPut request = new HttpPut(url);
        request.addHeader("Authorization", "Bearer " + accessToken);
        request.addHeader("Content-Type", "application/octet-stream");
        request.setEntity(new ByteArrayEntity(buffer));

        //Magical code start
        int hardTimeout = 5; // seconds
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                if (request != null) {
                    request.abort();
                }
            }
        };
        new Timer(true).schedule(task, hardTimeout * 1000);
        //Magical code end

        HttpResponse response = client.execute(request);
        request.releaseConnection();
        System.out.println(response.getStatusLine().getReasonPhrase());
    }
    bis.close();
}
Run Code Online (Sandbox Code Playgroud)

计时器正在工作,因为它在10秒后关闭了我的旧连接.伙计们,谢谢你的意见.