HttpClient的DnsResolver自定義DNS解析另一種選擇深入研究
序
本文主要研究一下HttpClient的DnsResolver
DnsResolver
org/apache/http/conn/DnsResolver.java
/** * Users may implement this interface to override the normal DNS lookup offered * by the OS. * * @since 4.2 */ public interface DnsResolver { /** * Returns the IP address for the specified host name, or null if the given * host is not recognized or the associated IP address cannot be used to * build an InetAddress instance. * * @see InetAddress * * @param host * The host name to be resolved by this resolver. * @return The IP address associated to the given host name, or null if the * host name is not known by the implementation class. */ InetAddress[] resolve(String host) throws UnknownHostException; }
DnsResolver定義了resolve方法,可用于替換OS提供的DNS lookup
InMemoryDnsResolver
org/apache/http/impl/conn/InMemoryDnsResolver.java
/** * In-memory {@link DnsResolver} implementation. * * @since 4.2 */ public class InMemoryDnsResolver implements DnsResolver { /** Logger associated to this class. */ private final Log log = LogFactory.getLog(InMemoryDnsResolver.class); /** * In-memory collection that will hold the associations between a host name * and an array of InetAddress instances. */ private final Map<String, InetAddress[]> dnsMap; /** * Builds a DNS resolver that will resolve the host names against a * collection held in-memory. */ public InMemoryDnsResolver() { dnsMap = new ConcurrentHashMap<String, InetAddress[]>(); } /** * Associates the given array of IP addresses to the given host in this DNS overrider. * The IP addresses are assumed to be already resolved. * * @param host * The host name to be associated with the given IP. * @param ips * array of IP addresses to be resolved by this DNS overrider to the given * host name. */ public void add(final String host, final InetAddress... ips) { Args.notNull(host, "Host name"); Args.notNull(ips, "Array of IP addresses"); dnsMap.put(host, ips); } /** * {@inheritDoc} */ @Override public InetAddress[] resolve(final String host) throws UnknownHostException { final InetAddress[] resolvedAddresses = dnsMap.get(host); if (log.isInfoEnabled()) { log.info("Resolving " + host + " to " + Arrays.deepToString(resolvedAddresses)); } if(resolvedAddresses == null){ throw new UnknownHostException(host + " cannot be resolved"); } return resolvedAddresses; } }
InMemoryDnsResolver實(shí)現(xiàn)了DnsResolver接口,它用一個(gè)ConcurrentHashMap來存放dns信息,提供add方法往map添加host及對應(yīng)的ip地址,然后其resolve就是從這個(gè)map來讀取對應(yīng)的ip地址信息
SystemDefaultDnsResolver
org/apache/http/impl/conn/SystemDefaultDnsResolver.java
/** * DNS resolver that uses the default OS implementation for resolving host names. * * @since 4.2 */ public class SystemDefaultDnsResolver implements DnsResolver { public static final SystemDefaultDnsResolver INSTANCE = new SystemDefaultDnsResolver(); @Override public InetAddress[] resolve(final String host) throws UnknownHostException { return InetAddress.getAllByName(host); } }
SystemDefaultDnsResolver實(shí)現(xiàn)了DnsResolver,它用的就是jdk提供的InetAddress.getAllByName,默認(rèn)是走的OS的DNS,可以通過sun.net.spi.nameservice.provider.<n>去自定義
DefaultHttpClientConnectionOperator
org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java
@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL) public class DefaultHttpClientConnectionOperator implements HttpClientConnectionOperator { static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry"; private final Log log = LogFactory.getLog(getClass()); private final Lookup<ConnectionSocketFactory> socketFactoryRegistry; private final SchemePortResolver schemePortResolver; private final DnsResolver dnsResolver; public DefaultHttpClientConnectionOperator( final Lookup<ConnectionSocketFactory> socketFactoryRegistry, final SchemePortResolver schemePortResolver, final DnsResolver dnsResolver) { super(); Args.notNull(socketFactoryRegistry, "Socket factory registry"); this.socketFactoryRegistry = socketFactoryRegistry; this.schemePortResolver = schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE; this.dnsResolver = dnsResolver != null ? dnsResolver : SystemDefaultDnsResolver.INSTANCE; } @Override public void connect( final ManagedHttpClientConnection conn, final HttpHost host, final InetSocketAddress localAddress, final int connectTimeout, final SocketConfig socketConfig, final HttpContext context) throws IOException { final Lookup<ConnectionSocketFactory> registry = getSocketFactoryRegistry(context); final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName()); if (sf == null) { throw new UnsupportedSchemeException(host.getSchemeName() + " protocol is not supported"); } final InetAddress[] addresses = host.getAddress() != null ? new InetAddress[] { host.getAddress() } : this.dnsResolver.resolve(host.getHostName()); final int port = this.schemePortResolver.resolve(host); for (int i = 0; i < addresses.length; i++) { final InetAddress address = addresses[i]; final boolean last = i == addresses.length - 1; Socket sock = sf.createSocket(context); sock.setSoTimeout(socketConfig.getSoTimeout()); sock.setReuseAddress(socketConfig.isSoReuseAddress()); sock.setTcpNoDelay(socketConfig.isTcpNoDelay()); sock.setKeepAlive(socketConfig.isSoKeepAlive()); if (socketConfig.getRcvBufSize() > 0) { sock.setReceiveBufferSize(socketConfig.getRcvBufSize()); } if (socketConfig.getSndBufSize() > 0) { sock.setSendBufferSize(socketConfig.getSndBufSize()); } final int linger = socketConfig.getSoLinger(); if (linger >= 0) { sock.setSoLinger(true, linger); } conn.bind(sock); final InetSocketAddress remoteAddress = new InetSocketAddress(address, port); if (this.log.isDebugEnabled()) { this.log.debug("Connecting to " + remoteAddress); } try { sock = sf.connectSocket( connectTimeout, sock, host, remoteAddress, localAddress, context); conn.bind(sock); if (this.log.isDebugEnabled()) { this.log.debug("Connection established " + conn); } return; } catch (final SocketTimeoutException ex) { if (last) { throw new ConnectTimeoutException(ex, host, addresses); } } catch (final ConnectException ex) { if (last) { final String msg = ex.getMessage(); throw "Connection timed out".equals(msg) ? new ConnectTimeoutException(ex, host, addresses) : new HttpHostConnectException(ex, host, addresses); } } catch (final NoRouteToHostException ex) { if (last) { throw ex; } } if (this.log.isDebugEnabled()) { this.log.debug("Connect to " + remoteAddress + " timed out. " + "Connection will be retried using another IP address"); } } } //...... }
DefaultHttpClientConnectionOperator的connect方法會(huì)通過dnsResolver.resolve解析host
小結(jié)
HttpClient提供了DnsResolver接口,可以用于自定義DNS解析,是除了使用sun.net.spi.nameservice.provider.<n>
去自定義JDK全局dns解析外的另外一種方案。
以上就是HttpClient的DnsResolver自定義DNS解析另一種選擇深入研究的詳細(xì)內(nèi)容,更多關(guān)于HttpClient DnsResolver解析DNS的資料請關(guān)注腳本之家其它相關(guān)文章!
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請求目標(biāo)路由
- 使用Backoff策略提高HttpClient連接管理的效率
- 提升網(wǎng)絡(luò)請求穩(wěn)定性HttpClient的重試機(jī)制深入理解
- httpclient getPoolEntryBlocking連接池方法源碼解讀
相關(guān)文章
啟動(dòng)Springboot項(xiàng)目時(shí)找不到Mapper的問題及解決
這篇文章主要介紹了啟動(dòng)Springboot項(xiàng)目時(shí)找不到Mapper的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11Springboot結(jié)合Mybatis-Plus實(shí)現(xiàn)業(yè)務(wù)撤銷回滾功能
本文介紹了如何在Springboot結(jié)合Mybatis-Plus實(shí)現(xiàn)業(yè)務(wù)撤銷回滾功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12java類Circle定義計(jì)算圓的面積和周長代碼示例
要用Java計(jì)算圓的周長和面積,需要使用圓的半徑和一些數(shù)學(xué)公式,下面這篇文章主要給大家介紹了關(guān)于java類Circle定義計(jì)算圓的面積、周長的相關(guān)資料,需要的朋友可以參考下2024-04-04IDEA報(bào)錯(cuò):java:無效的源發(fā)行版21解決方式
這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò):java:無效的源發(fā)行版21的解決方式,這個(gè)錯(cuò)誤是因?yàn)槟愕捻?xiàng)目使用的Java版本與你的IDEA使用的Java版本不一致導(dǎo)致的,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06解決springboot報(bào)錯(cuò)Could not resolve placeholder‘x
這篇文章主要介紹了解決springboot報(bào)錯(cuò):Could not resolve placeholder ‘xxx‘ in value “${XXXX}問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11Java實(shí)現(xiàn)將容器 Map中的內(nèi)容保存到數(shù)組
這篇文章主要介紹了Java實(shí)現(xiàn)將容器 Map中的內(nèi)容保存到數(shù)組,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09SpringBoot?項(xiàng)目瘦身maven/gradle詳解
這篇文章主要介紹了SpringBoot項(xiàng)目瘦身(maven/gradle),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01Spring中Bean創(chuàng)建完后打印語句的兩種方法
這篇文章主要介紹了Spring中Bean創(chuàng)建完后打印語句的兩種方法,一個(gè)是實(shí)現(xiàn)InitializingBean接口,另一個(gè)使用@Bean注解和initMethod屬性,通過代碼示例介紹的非常詳細(xì),感興趣的小伙伴可以參考閱讀2023-07-07