美文网首页
Java HTTP代理

Java HTTP代理

作者: 码中仙 | 来源:发表于2019-10-07 16:09 被阅读0次

    1. 专有云访问公网资源

    最近一个部署在专有云的项目上线后,需要访问公网资源,客户专有云环境对外网访问控制比较严格,开放一个代理服务器可访问外网。

    2. Linux 上通过Http代理访问

    在Linux上需要下载公网的资源,只要指定https_proxy和https_proxy即可,我们测试一下是否可行

    #设置http/htts代理
    [root@iZvy205enekymwo01x4w3vZ test]# export https_proxy=10.145.9.74:3128
    [root@iZvy205enekymwo01x4w3vZ test]# export http_proxy=10.145.9.74:3128
    # 查看是否走到代理
    [root@iZvy205enekymwo01x4w3vZ test]# curl -v -o /dev/null -s https://www.taobao.com
    * About to connect() to proxy 10.145.9.74 port 3128 (#0)
    *   Trying 10.145.9.74...
    * Connected to 10.145.9.74 (10.145.9.74) port 3128 (#0)
    * Establish HTTP proxy tunnel to www.taobao.com:443
    
    # 查看请求时间
    [root@iZvy205enekymwo01x4w3vZ ~]# curl -o /dev/null -s -w %{time_namelookup}:%{time_connect}:%{time_starttransfer}:%{time_total}:%{speed_download}"\n" https://www.taobao.com
    0.000:0.002:0.190:0.286:514182.000
    

    各参数的含义
    time_namelookup - DNS服务器解析时间,单位秒
    time_connect - client 发出请求,到 c/s 建立TCP 的时间;里面包括 DNS 解析的时间
    time_starttransfer - client 发出请求;到 server 响应发出第一个字节开始的时间;包括前面的2个时间
    time_total - client 发出请求;到 server 把响应的数据全部发送给 client;并关闭 connect 的时间
    speed_download - 下载速率

    3. Java应用中使用HTTP代理

    在Java应用中,常用的有两种http客户端实现

    • Java自带的HttpUrlConnection
    • Apache的HttpClient
      这两种实现设置代理的方式有一些区别
    3.1 HttpUrlConnection代理
    3.1.1 设置JVM启动参数
     -Dhttp.proxyHost=10.145.9.74 -Dhttp.proxyPort=3128 -Dhttps.proxyHost=10.145.9.74 -Dhttps.proxyPort=3128
    
    

    该方式会将所有使用HttpUrlConnection做http客户端的请求都走代理,对HttpClient无效。在专有云上使用访问内部资源也会走到代理,这样可能会带来问题。我们需要能控制访问外网的请求走代理,下面我们来看看在代码里如何实现。

    3.1.2 Proxy
    URL url = new URL("https://www.taobao.com");
    Proxy proxy = new Proxy(Proxy.Type.DIRECT.HTTP, new InetSocketAddress("10.145.9.74", 3128));  
    HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
    

    该方式简单,但是对于已经封装好的二方库,我们没办法去修改代码,JDK提供了一种代理选择机制

    3.1.3 ProxySelector
    //实现代理选择器,根据域名选择代理服务器
    public class MyProxySelector extends ProxySelector {
        private List<Proxy> proxyList = Lists.newArrayList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("10.145.9.74", 3128)));
        
        private ProxySelector defaultProxy = ProxySelector.getDefault();
        @Override
        public void connectFailed(URI uri, SocketAddress address, IOException e) {
             //代理出错处理
        }
     
        @Override
        public List<Proxy> select(URI uri) {
            String host = uri.getHost().toLowerCase();
            if(host.endsWith("taobao.com")){
                return proxyList;
            }else{
                return defaultProxy;
            }
        }
    }
    //设置系统默认代理服务器
    ProxySelector.setDefault(new MyProxySelector());
    

    ProxySelector机制所有采用HttpUrlConnection实现http的请求都会经过select方法,在这里可以根据URI来决定是否走代理。
    对于HttpUrlConnection实现的http请求,ProxySelector可以完美解决,但是Apache HttpClient实现默认情况下无效,我们看看Apache HttpClient如何实现代理。

    3.2 Apache HttpClient代理
    3.2.1 为单个请求设置代理
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory 
        = new HttpComponentsClientHttpRequestFactory(
            HttpClientBuilder.create()
                    .setProxy(new HttpHost("10.145.9.74", 3128, "http"))
                    .build());
    clientHttpRequestFactory.getHttpClient().execute(request);
    
    3.2.2 根据URI选择代理服务器,也是使用ProxySelector
    HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new MyProxySelector());
    
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory 
        = new HttpComponentsClientHttpRequestFactory(
            HttpClientBuilder.create()
                .setRoutePlanner(routePlanner)
                .build());
    
    3.2.3 使用系统默认ProxySelector
    HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner(ProxySelector.getDefault());
    
        HttpClient httpClient = HttpClientBuilder
                .create()
                .setRoutePlanner(routePlanner)
                .build();
    
    • 3.2.2和3.2.3本质上是一样的,应用中同时存在HttpUrlConnection和Apache HttpClient两种实现,可以采用3.2.3来统一实现代理选择。
    • Apache HttpClient 第三方库中如果没有提供指定代理的设置接口,只能修改代码了,没办法像HttpUrlConnection那样统一拦截。

    相关文章

      网友评论

          本文标题:Java HTTP代理

          本文链接:https://www.haomeiwen.com/subject/xhympctx.html