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來(lái)存放dns信息,提供add方法往map添加host及對(duì)應(yīng)的ip地址,然后其resolve就是從這個(gè)map來(lái)讀取對(duì)應(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,可以通過(guò)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ì)通過(guò)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的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對(duì)連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請(qǐng)求目標(biāo)路由
- 使用Backoff策略提高HttpClient連接管理的效率
- 提升網(wǎng)絡(luò)請(qǐng)求穩(wěn)定性HttpClient的重試機(jī)制深入理解
- httpclient getPoolEntryBlocking連接池方法源碼解讀
相關(guān)文章
啟動(dòng)Springboot項(xiàng)目時(shí)找不到Mapper的問(wèn)題及解決
這篇文章主要介紹了啟動(dòng)Springboot項(xiàng)目時(shí)找不到Mapper的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Springboot結(jié)合Mybatis-Plus實(shí)現(xiàn)業(yè)務(wù)撤銷回滾功能
本文介紹了如何在Springboot結(jié)合Mybatis-Plus實(shí)現(xiàn)業(yè)務(wù)撤銷回滾功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12
java類Circle定義計(jì)算圓的面積和周長(zhǎng)代碼示例
要用Java計(jì)算圓的周長(zhǎng)和面積,需要使用圓的半徑和一些數(shù)學(xué)公式,下面這篇文章主要給大家介紹了關(guān)于java類Circle定義計(jì)算圓的面積、周長(zhǎng)的相關(guān)資料,需要的朋友可以參考下2024-04-04
IDEA報(bào)錯(cuò):java:無(wú)效的源發(fā)行版21解決方式
這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò):java:無(wú)效的源發(fā)行版21的解決方式,這個(gè)錯(cuò)誤是因?yàn)槟愕捻?xiàng)目使用的Java版本與你的IDEA使用的Java版本不一致導(dǎo)致的,文中通過(guò)圖文介紹的非常詳細(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}問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Java實(shí)現(xiàn)將容器 Map中的內(nèi)容保存到數(shù)組
這篇文章主要介紹了Java實(shí)現(xiàn)將容器 Map中的內(nèi)容保存到數(shù)組,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
SpringBoot?項(xiàng)目瘦身maven/gradle詳解
這篇文章主要介紹了SpringBoot項(xiàng)目瘦身(maven/gradle),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
Spring中Bean創(chuàng)建完后打印語(yǔ)句的兩種方法
這篇文章主要介紹了Spring中Bean創(chuàng)建完后打印語(yǔ)句的兩種方法,一個(gè)是實(shí)現(xiàn)InitializingBean接口,另一個(gè)使用@Bean注解和initMethod屬性,通過(guò)代碼示例介紹的非常詳細(xì),感興趣的小伙伴可以參考閱讀2023-07-07

