NutzCN Logo
问答 Http工具类,是否有必要使用连接池。HttpClient与nutz http对比。
发布于 2129天前 作者 qq_16dd5808 4617 次浏览 复制 上一个帖子 下一个帖子
标签:

首先使用nutz并发http,代码如下,1000个

@Test
    public void t12() throws ExecutionException, InterruptedException {
        int taskSize = 1000;
        Sender.setup(null);

        List<Future> list = new ArrayList<>();

        for (int i = 0; i < taskSize; i++) {
            Future<Response> response = Sender.create("http://rc.uptechind.cn/ne").send(new Callback<Response>() {
                Stopwatch sw = Stopwatch.begin();

                @Override
                public void invoke(Response res) {
                    sw.stop();
                    System.out.println(res.getStatus());
                    System.out.println(String.format("线程[%s] %s", Thread.currentThread().getName(), sw.toString()));
                }
            });
            list.add(response);
        }

        int i = 0;
        for (Future f : list) {
            Response res = (Response) f.get();
            System.out.println(++i);
        }

        Sender.shutdown();
    }

执行一会后,没有执行完毕,就报错


java.util.concurrent.ExecutionException: org.nutz.http.HttpException: url=http://rc.uptechind.cn/ne at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at test.sunyu.tools.http.TestNutzHttp.t12(TestNutzHttp.java:254) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) Caused by: org.nutz.http.HttpException: url=http://rc.uptechind.cn/ne at org.nutz.http.sender.GetSender.send(GetSender.java:22) at org.nutz.http.Sender.call(Sender.java:236) at org.nutz.http.Sender.call(Sender.java:38) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.ConnectException: Connection timed out: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at sun.net.NetworkClient.doConnect(NetworkClient.java:175) at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) at sun.net.www.http.HttpClient.<init>(HttpClient.java:211) at sun.net.www.http.HttpClient.New(HttpClient.java:308) at sun.net.www.http.HttpClient.New(HttpClient.java:326) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1169) at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:933) at sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2662) at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2584) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1770) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at org.nutz.http.Sender.getResponseHeader(Sender.java:137) at org.nutz.http.sender.GetSender.send(GetSender.java:19) ... 6 more

再来看看HttpClient的,使用连接池。一万个

@Test
    public void t6() throws ExecutionException, InterruptedException {
        Stopwatch sw = Stopwatch.begin();
        int taskSize = 10000;
        ExecutorService executorService = Executors.newFixedThreadPool(taskSize);
        List<Future> list = new ArrayList<Future>();
        for (int i = 0; i < taskSize; i++) {
            Future f = executorService.submit(new MyHttpCallable2(i + ""));
            list.add(f);
        }
        for (Future f : list) {
            System.out.println(f.get());
        }
        sw.stop();
        System.out.println(String.format("总用时:" + sw.toString()));
        executorService.shutdown();
    }

    private class MyHttpCallable2 implements Callable<String> {
        String threadName;

        public MyHttpCallable2(String threadName) {
            this.threadName = threadName;
        }

        @Override
        public String call() throws Exception {
            Stopwatch sw = Stopwatch.begin();
            httpTools.get("http://rc.uptechind.cn/ne");
            sw.stop();
            return String.format("线程[%s] %s", threadName, sw.toString());
        }
    }

由于后台打印太多,所以直接打印后几个。看出来,10000个链接,全都执行完毕,没有错误。

线程[9981] Total: 99679ms : [2016-08-29 16:48:20.514]=>[2016-08-29 16:50:00.193]
线程[9982] Total: 106159ms : [2016-08-29 16:48:20.514]=>[2016-08-29 16:50:06.673]
线程[9983] Total: 106174ms : [2016-08-29 16:48:20.516]=>[2016-08-29 16:50:06.69]
线程[9984] Total: 99676ms : [2016-08-29 16:48:20.52]=>[2016-08-29 16:50:00.196]
线程[9985] Total: 83510ms : [2016-08-29 16:48:20.516]=>[2016-08-29 16:49:44.026]
线程[9986] Total: 106156ms : [2016-08-29 16:48:20.516]=>[2016-08-29 16:50:06.672]
线程[9987] Total: 57585ms : [2016-08-29 16:48:20.517]=>[2016-08-29 16:49:18.102]
线程[9988] Total: 99653ms : [2016-08-29 16:48:20.517]=>[2016-08-29 16:50:00.17]
线程[9989] Total: 99680ms : [2016-08-29 16:48:20.52]=>[2016-08-29 16:50:00.2]
线程[9990] Total: 25301ms : [2016-08-29 16:48:20.517]=>[2016-08-29 16:48:45.818]
线程[9991] Total: 99651ms : [2016-08-29 16:48:20.518]=>[2016-08-29 16:50:00.169]
线程[9992] Total: 99677ms : [2016-08-29 16:48:20.517]=>[2016-08-29 16:50:00.194]
线程[9993] Total: 106175ms : [2016-08-29 16:48:20.518]=>[2016-08-29 16:50:06.693]
线程[9994] Total: 83539ms : [2016-08-29 16:48:20.519]=>[2016-08-29 16:49:44.058]
线程[9995] Total: 106178ms : [2016-08-29 16:48:20.518]=>[2016-08-29 16:50:06.696]
线程[9996] Total: 83526ms : [2016-08-29 16:48:20.518]=>[2016-08-29 16:49:44.044]
线程[9997] Total: 83530ms : [2016-08-29 16:48:20.519]=>[2016-08-29 16:49:44.049]
线程[9998] Total: 83530ms : [2016-08-29 16:48:20.519]=>[2016-08-29 16:49:44.049]
线程[9999] Total: 57613ms : [2016-08-29 16:48:20.519]=>[2016-08-29 16:49:18.132]
总用时:Total: 113926ms : [2016-08-29 16:48:16.743]=>[2016-08-29 16:50:10.669]
26 回复

上面HttpClient使用到的相关类。spring注入的。

package sunyu.tools.http;

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * HttpConnection管理器,用于提供连接池功能
 *
 * @author 孙宇
 */
@Component("httpConnectionManager")
public class HttpConnectionManager {

    PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null;

    @Value("${http.maxTotal}")
    private int maxTotal;
    @Value("${http.defaultMaxPerRoute}")
    private int defaultMaxPerRoute;

    @PostConstruct
    public void init() {
        poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        poolingHttpClientConnectionManager.setMaxTotal(maxTotal);
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
    }

    @PreDestroy
    public void destroy() {
        poolingHttpClientConnectionManager.close();
    }

    public CloseableHttpClient getHttpClient() {
        // CloseableHttpClient httpClient = HttpClients.createDefault();//如果不采用连接池就是这种方式获取连接
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(poolingHttpClientConnectionManager).build();
        return httpClient;
    }

}

package sunyu.tools.http;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Http工具类
 *
 * @author 孙宇
 */
@Component
public class HttpTools {

    private static final Logger logger = LoggerFactory.getLogger(Thread.currentThread().getClass());

    @Resource(name = "httpConnectionManager")
    private HttpConnectionManager httpConnectionManager;

    private String charset = "UTF-8";

    public String getCharset() {
        return charset;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public String get(String url) {
        return get(url, null);
    }

    public String get(String url,
                      Map<String, String> params) {
        try {
            URIBuilder ub = new URIBuilder();
            ub.setPath(url);
            ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
            ub.setParameters(pairs);
            HttpGet httpGet = new HttpGet(ub.build());
            return execute(httpGet);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String post(String url) {
        return post(url, null, null);
    }

    public String post(String url,
                       Map<String, String> params) {
        return post(url, null, params);
    }

    public String post(String url,
                       Map<String, String> headers,
                       Map<String, String> params) {
        try {
            HttpPost httpPost = new HttpPost(url);
            addHeaders(headers, httpPost);
            ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
            httpPost.setEntity(new UrlEncodedFormEntity(pairs, charset));
            return execute(httpPost);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String postJson(String url,
                           String json) {
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity postEntity = new StringEntity(json, Charset.forName(charset));
            postEntity.setContentType("text/json");
            httpPost.setEntity(postEntity);
            return execute(httpPost);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String postJson(String url,
                           Map<String, String> headers,
                           String json) {
        try {
            HttpPost httpPost = new HttpPost(url);
            addHeaders(headers, httpPost);
            StringEntity postEntity = new StringEntity(json, Charset.forName(charset));
            postEntity.setContentType("text/json");
            httpPost.setEntity(postEntity);
            return execute(httpPost);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private ArrayList<NameValuePair> covertParams2NVPS(Map<String, String> params) {
        ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> param : params.entrySet()) {
                pairs.add(new BasicNameValuePair(param.getKey(), param.getValue()));
            }
        }
        return pairs;
    }

    private void addHeaders(Map<String, String> headers,
                            HttpPost post) {
        if (headers != null && !headers.isEmpty()) {
            for (Entry<String, String> entry : headers.entrySet()) {
                logger.debug(String.format("[%s]:[%s]", entry.getKey(), entry.getValue()));
                post.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    private String execute(HttpRequestBase request) {
        try {
            CloseableHttpClient httpClient = httpConnectionManager.getHttpClient();
            CloseableHttpResponse response = httpClient.execute(request);
            int statusCode = response.getStatusLine().getStatusCode();
            //logger.debug(statusCode + "");
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, charset);
                response.close();
                return result;
            }
            httpClient.close();
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

confit-http.properties

#整个连接池最大连接数
http.maxTotal=100
#每路由最大连接数,默认值是2
http.defaultMaxPerRoute=20

对比结果。Nutz的HTTP,大并发的时候,出现错误,
HttpClient,大并发,10倍与Nutz的http,目前没有错误。
不知是不是使用了连接池的缘故?

待我研究一下

这个地方改一下

                @Override
                public void invoke(Response res) {
                    sw.stop();
					res.getContent(); // 耗尽body才能重用连接,也许是这个原因.
                    System.out.println(res.getStatus());
                    System.out.println(String.format("线程[%s] %s", Thread.currentThread().getName(), sw.toString()));
                }

@wendal 果真是这样,我试了1000个没问题,我再试试1万个

1万个的时候,出错了

线程[pool-1-thread-45] Total: 31800ms : [2016-08-29 17:13:32.495]=>[2016-08-29 17:14:04.295]

java.util.concurrent.ExecutionException: org.nutz.http.HttpException: url=http://rc.uptechind.cn/ne

	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at test.sunyu.tools.http.TestNutzHttp.t12(TestNutzHttp.java:255)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
Caused by: org.nutz.http.HttpException: url=http://rc.uptechind.cn/ne
	at org.nutz.http.sender.GetSender.send(GetSender.java:22)
	at org.nutz.http.Sender.call(Sender.java:236)
	at org.nutz.http.Sender.call(Sender.java:38)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: Connection timed out: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
	at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)
	at sun.net.www.http.HttpClient.New(HttpClient.java:308)
	at sun.net.www.http.HttpClient.New(HttpClient.java:326)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1169)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
	at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:933)
	at sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2662)
	at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2584)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1770)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at org.nutz.http.Sender.getResponseHeader(Sender.java:137)
	at org.nutz.http.sender.GetSender.send(GetSender.java:19)
	... 6 more

@wendal 1500个的时候就不行了。
我这个业务的使用场景是,设备上传经纬度信息,上传到服务端,我们要将原始GPS经纬度转换成中文地址,然后存到Hbase中。
由于是车机设备上传,同时在线设备非常多,每个设备每秒上传一次,就产生了很大的并发量。

gps转中文地址,是我们公司内部一个http服务。

重定向的是同一个服务器地址吗? 我在想, "Connection timed out: connect" 证明依然是新建连接了,没有重用.

因为那个经纬度转换地址的http服务,压力比较大,所以部署了集群,跟这个有关么?

@wendal
好像不是这回事。

@Test
    public void t6() throws ExecutionException, InterruptedException {
        Stopwatch sw = Stopwatch.begin();
        int taskSize = 10000;
        ExecutorService executorService = Executors.newFixedThreadPool(taskSize);
        List<Future> list = new ArrayList<Future>();
        for (int i = 0; i < taskSize; i++) {
            Future f = executorService.submit(new MyHttpCallable2(i + ""));
            list.add(f);
        }
        for (Future f : list) {
            System.out.println(f.get());
        }
        sw.stop();
        System.out.println(String.format("总用时:" + sw.toString()));
        executorService.shutdown();
    }

    private class MyHttpCallable2 implements Callable<String> {
        String threadName;

        public MyHttpCallable2(String threadName) {
            this.threadName = threadName;
        }

        @Override
        public String call() throws Exception {
            Stopwatch sw = Stopwatch.begin();
            httpTools.get("http://www.baidu.com");
            sw.stop();
            return String.format("线程[%s] %s", threadName, sw.toString());
        }
    }

我把地址改成了百度。用HttpClient的那个,1万次,也是没问题的。百度这个地址应该没有重定向的。
但是用nutz的http还是不行

我想想哦...

另外,我想问一下, 这个重定向是怎么样一个流程

@wendal 可以说是没啥流程,就是http://xxx.xxx.xxx?lon=123&lat=123
然后就返回中文的地址,内部使用,没有权限限制。
指向单IP也是一样的错误。

麻烦把返回的header贴一下, 单一ip的时候及重定向之后的

记得把敏感信息过滤一下...

@wendal 嗯,你稍等一下。

貌似测出来了, 我看看怎么解决

@wendal

{
   "null" :"HTTP/1.1 200 OK",
   "Server" :"Apache-Coyote/1.1",
   "Content-Length" :"53",
   "Date" :"Mon, 29 Aug 2016 09:42:51 GMT"
}
甘肃省,金昌市,永昌县,沙帽翅沟(南586米)
线程[pool-1-thread-1] Total: 19ms : [2016-08-29 17:43:09.602]=>[2016-08-29 17:43:09.621]
1

@wendal
改成单IP,结果错误变了


Connected to the target VM, address: '127.0.0.1:59281', transport: 'socket' java.util.concurrent.ExecutionException: org.nutz.http.HttpException: url=http://192.168.11.169:9094/DiscInfo/getDisc?pointX=101.8016950000&pointY=38.3976280000 at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at test.sunyu.tools.http.TestNutzHttp.t12(TestNutzHttp.java:257) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) Caused by: org.nutz.http.HttpException: url=http://192.168.11.169:9094/DiscInfo/getDisc?pointX=101.8016950000&pointY=38.3976280000 at org.nutz.http.sender.GetSender.send(GetSender.java:22) at org.nutz.http.Sender.call(Sender.java:236) at org.nutz.http.Sender.call(Sender.java:38) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.BindException: Address already in use: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at sun.net.NetworkClient.doConnect(NetworkClient.java:175) at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) at sun.net.www.http.HttpClient.<init>(HttpClient.java:211) at sun.net.www.http.HttpClient.New(HttpClient.java:308) at sun.net.www.http.HttpClient.New(HttpClient.java:326) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1169) at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:933) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at org.nutz.http.Sender.getResponseHeader(Sender.java:137) at org.nutz.http.sender.GetSender.send(GetSender.java:19) ... 6 more Disconnected from the target VM, address: '127.0.0.1:59281', transport: 'socket' Process finished with exit code -1

就奇了怪了,改了并发数,又出现别的错

java.util.concurrent.ExecutionException: org.nutz.http.HttpException: url=http://192.168.11.169:9094/DiscInfo/getDisc?pointX=101.8016950000&pointY=38.3976280000

	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at test.sunyu.tools.http.TestNutzHttp.t12(TestNutzHttp.java:257)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
Caused by: org.nutz.http.HttpException: url=http://192.168.11.169:9094/DiscInfo/getDisc?pointX=101.8016950000&pointY=38.3976280000
	at org.nutz.http.sender.GetSender.send(GetSender.java:22)
	at org.nutz.http.Sender.call(Sender.java:236)
	at org.nutz.http.Sender.call(Sender.java:38)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connect
	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:83)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
	at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)
	at sun.net.www.http.HttpClient.New(HttpClient.java:308)
	at sun.net.www.http.HttpClient.New(HttpClient.java:326)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1169)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
	at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:933)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at org.nutz.http.Sender.getResponseHeader(Sender.java:137)
	at org.nutz.http.sender.GetSender.send(GetSender.java:19)
	... 6 more

我改了一下你的代码, 改成用Sender内置的线程池跑.

    @Test
    public void t6() throws ExecutionException, InterruptedException {
        Sender.setup(null);
        Stopwatch sw = Stopwatch.begin();
        int taskSize = 10000;
        AtomicLong atom = new AtomicLong();
        for (int i = 0; i < taskSize; i++) {
            int t = i;
            Sender.create("http://any.nutz.cn").send(new Callback<Response>() {
                public void invoke(Response obj) {
                    System.out.println("t="+t);
                    atom.incrementAndGet();
                    obj.getContent();
                }
            });
        }
        while (atom.get() != taskSize) {
            Lang.quiteSleep(100);
        }
        sw.stop();
        System.out.println(String.format("总用时:" + sw.toString()));
    }

另外, 服务器本身需要支持长连接, 以下是我的测试服务器, 注意看Connection这个Header

[strato@VPN ~]$ curl -I -H "Connection: keep-alive" http://any.nutz.cn
HTTP/1.1 200 OK
Server: nutzweb 1.r.55
Date: Mon, 29 Aug 2016 09:50:43 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 07 Jan 2016 06:22:50 GMT
Connection: keep-alive
ETag: "568e043a-264"
Accept-Ranges: bytes

taskSize开到1w和5w均可pass.

至于您后面贴的那些错误, 应该是服务器没开长连接支持

用这段代码居然过了。。。

@Test
    public void t13() throws ExecutionException, InterruptedException {
        Sender.setup(null);
        Stopwatch sw = Stopwatch.begin();
        int taskSize = 100000;
        AtomicLong atom = new AtomicLong();
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < taskSize; i++) {
            Future<Response> response = Sender.create("http://192.168.11.169:9094/DiscInfo/getDisc?pointX=101.8016950000&pointY=38.3976280000").send(new Callback<Response>() {
                public void invoke(Response obj) {
                    atom.incrementAndGet();
                    obj.getContent();
                }
            });
            list.add(response);
        }
        int i = 0;
        for (Future f : list) {
            Response res = (Response) f.get();
            System.out.println(++i + "\t" + res.getStatus());
        }
        sw.stop();
        System.out.println(String.format("总用时:" + sw.toString()));
    }
99995	200
99996	200
99997	200
99998	200
99999	200
100000	200
总用时:Total: 15964ms : [2016-08-29 18:02:32.722]=>[2016-08-29 18:02:48.686]

没下文了。。。

又出问题了?

来自美丽的 NutzCN

我也遇到这个问题了。。

所以怎么解决呢?

添加回复
请先登陆
回到顶部