HTTPDNSLib

Project Url: CNSRE/HTTPDNSLib
More: Author   ReportBugs   
Tags:

该项目是手机微博研发团队和手机微博技术保障部共同努力的成果。

在此特别感谢:

等同学的支持。

感谢大家提出的宝贵意见,感谢大家为该项目付出的努力!

项目中有任何问题欢迎大家来吐槽,一起完善、一起提高、一起使用!
email: xingyu10@staff.weibo.com fenglei1@staff.sina.com.cn

由于该工程需要用户自定义部分配置文件,所以建议以源码方式使用。(同时也支持项目中设定Lib库的参数)

Lib库目前还没有打包成jar文件, 大家测试使用的话可以直接将工程包含到自己的工程内即可。

apk文件夹下内有打包好的对httpDNS库进行测试的程序。 该测试程序模拟了用户使用的场景,并且记录了相关统计数据,以及Lib库的时时的状态信息。

以下配置请按照顺序进行:

1.配置清单文件 - AndroidManifest.xml

<!-- 权限信息 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

2.初始化调用 - 【建议放在 Application 中处理】

DNSCache.Init(context);

3.预加载域名解析(可选) - 【建议放在 Application 中处理】 可提前预加载需要解析的域名,并将解析数据缓存到内存中。

DNSCache.getInstance().preLoadDomains(new String[]{"api.camera.weibo.com","domain2","domain3"});

4.开始使用

直接调用该方法获取 A 记录对象

DomainInfo[] infoList = DNSCache.getInstance().getDomainServerIp( "http://api.camera.weibo.com/index.html" ) ; 

//DomainInfo 返回有可能为 null,如果为空则使用域名直接请求数据吧~ 因为在 http server 故障的时候会出现这个问题。 
if( infoList != null ) { 
//A 记录可能会返回多个, 没有特殊需求直接使用第一个即可。  这个数组是经过排序的。 
DomainInfo domainModel = infoList[0] ;  
//这里是 android 请求网络。  只需要在 http 头里添加一个数据即可。 省下的请求数据和原先一样。
HttpGet getMethod = new HttpGet( domainModel.url );  
getMethod.setHeader("host", domainModel.host);
HttpClient httpClient = new DefaultHttpClient();  
HttpResponse response = httpClient.execute(getMethod); 
}

更多配置

你可以创建一个com.sina.util.dnscache.DNSCacheConfig.Data对象分别设置下面属性。

然后调用DNSCacheConfig.saveLocalConfigAndSync方法传入设定好的配置选项。

/**
* 是否启用 udpdns 服务器 默认不启用 | 1 启用 0 不启用
*/
public String IS_UDPDNS_SERVER = "";
/**
* udp dnsserver 的地址,如 8.8.8.8
*/
public String UDPDNS_SERVER_API = "";
/**
* 日志采样率。如设为 50,则为 50 次数据采样一次
*/
public String HTTPDNS_LOG_SAMPLE_RATE = "";
/**
* lib 库开关,“1”启用,“0”不启用。默认启用
*/
public String HTTPDNS_SWITCH = "";
/**
* 测速间隔时间
*/
public String SCHEDULE_SPEED_INTERVAL = "";

/**
* timer 轮询器的间隔时间
*/
public String SCHEDULE_TIMER_INTERVAL = "";
/**
* ip 数据过期延迟差值
*/
public String IP_OVERDUE_DELAY = "";
/**
* 是否启用自己家的 HTTP_DNS 服务器 默认不启用 | 1 启用 0 不启用
*/
public String IS_MY_HTTP_SERVER = null;
/**
* 自己家 HTTP_DNS 服务 API 地址 使用时直接在字符串后面拼接 domain 地址 |
* 示例(http://202.108.7.153/dns?domain=)+ domain
*/
public ArrayList<String> HTTPDNS_SERVER_API = new ArrayList<String>();
/**
* 是否启用 dnspod 服务器 默认不启用 | 1 启用 0 不启用
*/
public String IS_DNSPOD_SERVER = null;
/**
* DNSPOD HTTP_DNS 服务器 API 地址 | 默认(http://119.29.29.29/d?ttl=1&dn=)
*/
public String DNSPOD_SERVER_API = null;
/**
* DNSPOD 企业级 ID 配置选项 
*/
public String DNSPOD_ID = null;
/**
* DNSPOD 企业级 KEY 配置选项 
*/
public String DNSPOD_KEY = null;

/**
* 是否开启 本地排序插件算法 默认开启 | 1 开启 0 不开启
*/
public String IS_SORT = null;
/**
* 速度插件 比重分配值:默认 40%
*/
public String SPEEDTEST_PLUGIN_NUM = null;
/**
* 服务器推荐优先级插件 比重分配:默认 30% (需要自家 HTTP_DNS 服务器支持)
*/
public String PRIORITY_PLUGIN_NUM = null;
/**
* 历史成功次数计算插件 比重分配:默认 10%
*/
public String SUCCESSNUM_PLUGIN_NUM = null;
/**
* 历史错误次数计算插件 比重分配:默认 10%
*/
public String ERRNUM_PLUGIN_NUM = null;
/**
* 最后一次成功时间计算插件 比重分配:默认 10%
*/
public String SUCCESSTIME_PLUGIN_NUM = null;

动态更新参数

DNSCacheConfig类下的ConfigText_API字段可以配置成自动更新配置参数的接口。该接口返回json数据类型 具体数据格式详见DNSCacheConfig.Data toJson()方法。

自己家 HttpDNS 服务接入

  1. 开启DNSCacheConfig.Data.IS_MY_HTTP_SERVER = 1;
  2. 设定 DNSCacheConfig.Data.HTTPDNS_SERVER_API接口地址(示例http://XXX.XXX.XXX.XXX/dns?domain=)+ domain,该接口返回格式。
    (重载com.sina.util.dnscache.httpdns.IJsonParser类可以自定义格式)
{
    "domain": "api.weibo.cn",
    "device_ip": "10.209.70.192",
    "device_sp": "0",
    "dns": [
        {
            "priority": "0",
            "ip": "123.125.105.231",
            "ttl": "60"
        },
        {
            "priority": "0",
            "ip": "123.125.105.246",
            "ttl": "60"
        },
        {
            "priority": "0",
            "ip": "202.108.7.133",
            "ttl": "60"
        }
    ]
}

PS: priority字段是服务器推荐优先级。device_sp字段是该设备出口运营商。

HttpDns 是什么?

如果你对 httpdns 还不了解他是什么!

你可以阅读:【鹅厂网事】全局精确流量调度新思路-HttpDNS 服务详解

传统 DNS 解析 和 HTTPDNS 解析 本质的区别

传统 DNS 解析

客户端发送 udp 数据包到 dns 服务器,dns 服务器返回该域名的相关 A 记录信息。

HTTPDNS 解析

客户端发起 http 请求携带需要查询的域名,通过 IP 直接访问服务器,该 Http 服务器接倒请求后返回域名对应的 A 记录。

HttpDns sdk (android 版本)

希望解决的问题:

1. LocalDNS 劫持
2. 平均访问延迟下降
3. 用户连接失败率下降

目录结构说明:

HttpDns/src/DNSCache --- HttpDns lib 库主工程。
HttpDns/src/DNSCacheTest --- HttpDns 库测试工程。
HttpDns/doc --- 项目相关的一些文档、流程图、结构图等。
HttpDns/ui/DNSCacheTest --- 存放 HttpDns 测试项目 UI 源文件以及切图文件。

HttpDns 交互流程

image

HttpDns Lib 库交互流程

image



查询模块

检测本地是否有相应的域名缓存
没有记录则根据当前运营商返回内置的 ip 节点
从 httpdns 查询域名相应 A 记录,缓存域名信息
查询模块必须保证响应速度,基于已有设备测试平均在 5 毫秒左右

数据缓存模块

根据 sp(或 wifi 名)缓存域名信息
根据 sp(或 wifi 名)缓存服务器 ip 信息、优先级
记录服务器 ip 每次请求成功数、错误数
记录服务器 ip 最后成功访问时间、最后测速
添加 内存 -》数据库 之间的缓存层

评估模块

根据本地数据,对一组 ip 排序
处理用户反馈回来的请求明细,入库
针对用户反馈是失败请求,进行分析上报预警
给 HttpDns 服务端智能分配 A 记录提供数据依据

评估算法插件

本次测速 - 对 ip 组的每个 ip 测速打分
官方推荐 - HttpDns 接口 A 记录中返回的优先级
历史成功 - 该 ip7 天内成功访问次数
历史错误 - 该 ip7 天内访问错误次数
最后成功时间 - 该 ip 最后一次成功时间,阈值 24

打分比重权值分配

对每个 IP 打分,总分 100 分。
本次测速 - 40 分
官方推荐 - 30 分
历史成功 - 10 分
历史错误 - 10 分
最后成功时间 - 10 分
总分=本次测速+官方推荐+历史成功次数+历史错误次数+最后成功时间

目前权重分配完全基于主观认识,后期会根据建立的相应基线进行权重分配调整。

使用者需要自己权衡,有可能随机的 ip 速度都好于权重打分的 ip。



PS:给出一副算法计算分数时的细节图,有兴趣的朋友可以一起探讨研究。

image



HttpDns Test (android 版本)

测试工程主要最初为了模拟用户使用 APP 发出的网络请求,进行数据记录和对比。
在页面中能很直观的看到每个任务的相关信息。
比如:任务总耗时,httpdns lib 库耗时、http 请求耗时、以及设备当前环境信息 等。。
由于 UE,UI 都是自己设计,对于表达信息的布局和美观可能还有欠缺,本程序猿的能力有限,大家多多包涵。

你未必会需要“它”,上传几张测试工程的截图,提供参考。
image

image

image

image

image

image

Apps
About Me
Google+: Trinea trinea
GitHub: Trinea