问题和解决方案:
1、问题:此方案解决用户DNS有问题,网页无法访问,
2、思路:通过获取NetError类型,处理DNS解析类型问题,替换无效DNS,使用新DNS解析出IP尝试访问
生命周期:
创建一个HostResolverImpl (后面成为NewResolver对象,对应系统Resolver对象)并保存到SystemRequestContext;
创建一个DnsResolverCollcetorNew保存在IOThread中,随着IOThread的一起析构
在系统的系统Resolver中保存NewResolver裸指针,TransportConnectJobFactory::NewConnectJob会根据判断条件来使用那个对象 ,判断条件是否在新DNS解析的host列表中;
访问错误后调用OnUrlRequestCompleted,并根据云控错误码和云控DNS处理指定解析host,对应函数:HandleDnsResolver,如果解析出有效IP则保存到host列表中。
chrome原生类图实现涉及类图
HostResolverImpl host解析实现类
HostResolver host解析抽象类
IOThread 保存HostResolver对象信息
DnsResolverCollcetorNew 配置host解析config并使用HostResolver解析
URLRequestInfoCollectorNew 错误收集类
TransportConnectJobFactory 创建解析host的一个job
host_resolver_impl.cc
每一个hostname请求,HostResolver 创建一个HostResolverImpl::Job。当这个job被执行的时候它创建一个DnsTask用来异步解析hostname。如果请求相同的host并且在缓存有效期则不在创建新的直接使用存在的job,此异步操作是非线程安全需要在同一个现场创建和完成。
关键代码
class DnsResolverCollcetorNew : public HostResolver::DelegateNew {
public:
DnsResolverCollcetorNew();
virtual ~DnsResolverCollcetorNew();
void HandleDnsResolver(const GURL& url, const int error);
// HostResolver::DelegateNew
bool IsHostResolverList(const std::string& url_host) override;
void ClearHostResolverList() override;
private:
int Resolve(const HostResolver::RequestInfo& info);
void OnComplete(int rv);
private:
std::unique_ptr out_request_;
AddressList list_;
std::string url_host_;
std::liststring> host_list_;
HostResolver* resolver_New_;
DISALLOW_COPY_AND_ASSIGN(DnsResolverCollcetorNew);
};
关键点
1、列表中超过5000个host则清除一次
2、检测一下网络变化清空host列表
OnNetworkChanged 网络变动检测
OnIPAddressChanged IP变动检测
OnConnectionTypeChanged 连接类型检测
OnDNSChanged DNS变动检测
系统HostResolver和New HostResolver区别
New HostResolver里会设置一个DnsClient并指定DNS以及设置SetDnsClientEnabled
New HostResolver会设置DnsResolverCollcetorNew的代理指针,用来后续判断访问的host是否在列表中
系统HostResolver会保存一个New HostResolver裸指针,当判断访问url在host列表中则替换HostResolver
系统HostResolver会通过默认通过StartProcTask解析ip,NewHostRelver通过 StartDnsTask
ClearHostCache这里跟随系统HostResolver清楚host缓存,比如无痕模式会清除
测试
修改www.baidu.com 的 hosts ,本地配置一个异常值:127.0.1.1 www.baidu.com
此时通过新制定DNS(223.5.5.5)解析出新IP,加到host列表后续可正常访问
2、修改系统DNS为异常值如:1.2.3.4 ,所有请求无法正常访问,此时会通过指定的DNS如(223.5.5.5)解析IP加到host列表,后续正常访问。
3、使用Shadowsocks本地PAC模式或全局模式如,可以正常使用不受影响
{host_="127.0.0.1" port_=1080 } 这个网络检测不会执行动作,不过所有符合条件的请求host都会改为127.0.0.1 所以认为不在我们ip列表中
127.0.0.1屏蔽,不能加入ip列表,不触发网络检测
4、VPN代理,触发网络检测 OnNetworkChanged
5、网络禁用可以检测到,OnIPAddressChanged
6、DNS切换可以检测到OnDNSChanged
造成的风险
额外操作
这里属于做无效尝试
"s.cpro.baidu.com" http://zwcsgun/ http://adoqatqdtf/ 错误码:105
http://www.37zw.com/favicon.ico 错误码:101
www.google.com 错误码:118
这三种情况都是无感知请求,虽然无法访问,但是用户没感觉,开启NetError后会多一次解析
切核DNS
一个host中当前1min有问题如www.baidu.com有问题,此时我更换DNS导致所有的这个host资源请求都变了,流程会转到我们指定的DNS,但这个DNS不一定最优也不一定快, 后续的请求都会走我们的DNSTask请求。
对当前流程的影响
每次host对应的job请求NewConnectJob都会增加一次判断,判断是否在我们host列表中
OnUrlRequestCompleted网络请求结束后,对于指定错误码增加一次解析host的操作
对于在我们host列表中的url会通过我们的resolverimpl
网友评论