鹅厂往事中提到
HttpDNS主要解决三类问题:
LocalDNS劫持: 由于HttpDNS是通过ip直接请求http获取服务器A记录地址,不存在向本地运营商询问domain解析过程,所以从根本避免了劫持问题。 (对于http内容tcp/ip层劫持,可以使用验证因子或者数据加密等方式来保证传输数据的可信度)
用户连接失败率下降: 通过算法降低以往失败率过高的服务器排序,通过时间近期访问过的数据提高服务器排序,通过历史访问成功记录提高服务器排序。如果ip(a)访问错误,在下一次返回ip(b)或者ip(c) 排序后的记录。(LocalDNS很可能在一个ttl时间内(或多个ttl)都是返回记录
检查本地是否有对应的 domain 缓存
如果没有 则从本地LocalDNS获取然后从httpdns更新domain记录
有数据则检测是否过期 已过期则更新记录返回 LocalDNS 记录, 未过期则直接返回缓存层数据。
从HttpDNS 接口查询本次app开启后使用过的domain 记录定时访问,更新内存缓存,数据库缓存等记录
根据SP(或Wifi名)缓存域名信息
更具SP(或Wifi名)缓存服务器ip信息、优先级
记录服务器ip每次请求成功数、错误数
记录服务器ip最后成功访问时间、最后测速
添加 内存 》数据库 之间的缓存层
根据本地数据,对一组IP排序
处理用户反馈回来的请求明细,入库
针对用户反馈是失败请求,进行分析上报预警
给HttpDns服务端智能分配A记录提供数据依据
从这张图中可以看出来 整个业务的交互流程,用户向查询模块传入一个URL地址,然后查询模块会检查缓存是否存在,不存在从httpdnsapi接口查询, 然后经过评估模块返回。在用户请求URL过程完毕时,需要将这次请求的结果反馈给 lib库的评估模块由评估模块入库记录本次质量数据。
左部分是app主线程操作的事情,中间部分是app调用者线程中处理lib库事件逻辑的事情,右面部分是新线程独立处理事件的逻辑。
lib模块设定定时器,根据ttl过期时间来检查domain是否需要更新。 定时器是独立线程, 不会影响app主线程。 httpdns api请求数据, 先从自己配置的 httpdns api接口获取数据,如果获取不到会从 dnspod api接口获取如果也获取不到 直接从本地 localDNS获取数据,(从本地localDNS获取数据后期会改为发送UDP包封装dns协议从公共dns服务器直接获取,比如114dns等。dns服务器地址可自行设定。 )获取到数据后进入测速模块。 测速模块最新版本可以配置两种方式,一种是http空请求。 两个http头的交互,类似tcp首保耗时时间原理 ,用来测试链路最快。 另一种是ping命令,(icmp协议)来尽量最小化流量的消耗,考虑倒可能有的服务器禁ping就使用空http测速即可。 测速后将数据插入本地 cache 即可。
由于内部model数据过于复杂,为用户专门封装DomainInfo模型。 该类仅返回用户使用的相关数据。
代码结构如下图所示:
在编写该库的时候遇到最头疼的问题可能就是多线程同时访问导致遇到的数据异常错误。比如用户访问 api.weibo.cn 域名该域名目前数据库中没有缓存,内存中也没有缓存。在同时有多个请求以来来获取该域名的ip的时候, 因为没有数据会去请求api接口获取数据, 导致同时开启多个线程访问数据。 解决办法在请求api接口前增加正在请求队列,
以上为冯老师的分享,接下来是星宇跟大家分享下项目从研发倒现在所遇到的一些主要问题和大家有疑问的点。
2、网络发生变化后,返回的A记录还一样么?
3、怎样进行测速?
4、域名ttl刚刚过期,库还没有从HttpDNS拉取回来数据怎么办?
5、lib库目前只能使用 dnspod 服务商么? 支持dnspod 企业版本么?
6、使用这个库会不会降低应用请求网络的访问速度?
一旦从LocalDNS获取后,会缓存倒内存中,在HttpDNS获取数据后会更新内存中得domain记录。 从库中获取a记录会比从LocalDNS获取a记录快一些。 在访问网络的时候由于是使用ip直链,可以起到一些加速效果,lib库获取domainA记录 + ip直接访问服务器 耗时小于 直接域名请求服务器。相关数据图片
模拟了客户端访问http请求,分别标识了每个任务的详细信息。
这个页面全都是数据库相关配置,在代码中可以直接找到具体设置库文件的接口。
数据报表入口,包含全部任务加速效果延迟效果数据记录, lib库耗时走向,每个ip直接访问请求和domain访问请求速度对比, 统计了服务器平局速度。
缓存数据标签中包含了 当前库的所有状态, 能实时的看到内存缓存层的所有数据状态,包括数据库中得所有数据状态。 每秒钟刷新一次。 在这里可以清空缓存层数据、数据层数据、已经当前测试工程的数据。 在这里你可以清楚的看到 ip 和 domain的对应关系, 以及数据库表中 每项的关系。 和所有的domain 以及 ip 的状态。
Q&A
检测链路 如果配置成 http 空的请求, 也是同理 在 httpdns api请求结束后, 才会检测链路是否畅通。
Q3、南北网络之间请求有特别处理么?
首先 HttpDNS 返回的a记录会根据你的出口ip 来从权威的 dns 服务器问出来结果。 如果你是南方的ip 肯定给你的a记录 也是南方的, httpdns 返回的记录理论应该是和 传统的 dns 返回的 a 记录是一样的。 而去问 httpdns 的api 地址 是 bgp的机房。 所以 也是 兼容多链路 多地域。有遇见过 传统 dns 出口可能是 电信的, 但业务访问的 ip 出口是联通的情况。 所以 HttpDNS 访问 a记录 也能避免这类一部分错误。
Q5、数据库中记录的是cname,还是cname解析出的ip?
因为测试过, 从一栋大楼走到另外一个大楼 里面 访问的最终ip可能都不相同。 所以如果返回的是cname 则直接存储cname 。 网络环境发生变化, 会重新拉取, 不会使用缓存的cname 。