unity支持linux吗httpdns吗

Happy Coding
webview接入HttpDNS实践
本文是对去年做的webview接入HttpDNS工作的一个总结,拖的时间有点久了。主要分享了GOT Hook webview中域名解析函数的方法。
HttpDNS简介
首先简单介绍下移动App接入HttpDNS后有什么好处,这里直接引用腾讯云文档中的:
HttpDNS是通过将移动APP及桌面应用的默认域名解析方式,替换为通过Http协议进行域名解析,以规避由运营商Local DNS服务异常所导致的用户网络接入异常。减少用户跨网访问,降低用户解析域名时延。
更详细的内容可以参考这篇文章:
移动端的实现原理
域名的解析工作将在HttpDNS服务器上完成,客户端只要把待解析的域名作为参数发起一个HTTP请求,HttpDNS服务器就会把解析结果下发给客户端了。
在客户端,默认的域名解析是系统的getaddrinfo()库函数实现的,默认的域名解析请求会走到LocalDNS。
所以域名解析的工作必须要交给app应用层来实现。下面介绍几种实现方案。
okhttp的实现是建立在socket之上的,并且实现了HTTP协议。对于客户端发起的http请求,okhttp首先会跟远端服务器建立socket连接,在此之前okhttp会根据http请求中url的domain做域名解析,默认的实现是java网络库提供的InetAddress.getAllByName。
如果项目中用的网络库是okhttp,所有的网络请求都是通过它完成的话就可以使用okhttp提供的DNS解析接口,实现自己的DNS resolver,代码如下:
public class HttpDns implements Dns {
public List&InetAddress& lookup(String hostname) throws UnknownHostException {
String ip = DNSHelper.getIpByHost(hostname);
List&InetAddress& inetAddresses = Arrays.asList(InetAddress.getAllByName(ip));
return inetA
2、native hook的方法
通过Hook libc的getaddrinfo库函数,将函数指针指向app应用层实现的DNS解析函数地址。
要深入了解linux native hook的技术的话,需要了解ELF文件格式和动态链接的相关知识,可参考。
getaddrinfo是在libc.so中的定义的,其它库如libandroid_runtime.so、libjavacore.so要使用这个函数的话,只能通过动态导入符号的形式,好在java网络库底层是就是通过这个方式实现的。
android nativehook原理
下面代码是arm架构的一种实现方案,具体实现参考Andrey Petrov的.
#include "linker.h"
unsigned elfhash(const char *_name);
static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)
Elf32_Sym *s;
Elf32_Sym *symtab = si-&
const char *strtab = si-&
n = hash % si-&
for(n = si-&bucket[hash % si-&nbucket]; n != 0; n = si-&chain[n]){
s = symtab +
if(strcmp(strtab + s-&st_name, name)) continue;
return NULL;
int hook_call(char *soname, char *symbol, unsigned newval) {
soinfo *si = NULL;
Elf32_Rel *rel = NULL;
Elf32_Sym *s = NULL;
unsigned int sym_offset = 0;
si = (soinfo*) dlopen(soname, 0);
s = soinfo_elf_lookup(si, elfhash(symbol), symbol);
sym_offset = s - si-&
rel = si-&plt_
for (int i = 0; i & si-&plt_rel_ i++, rel++) {
unsigned type = ELF32_R_TYPE(rel-&r_info);
unsigned sym = ELF32_R_SYM(rel-&r_info);
unsigned reloc = (unsigned)(rel-&r_offset + si-&base);
uint32_t page_size = 0;
uint32_t entry_page_start = 0;
unsigned oldval = 0;
if (sym_offset == sym) {
switch(type) {
case R_ARM_JUMP_SLOT:
page_size = getpagesize();
entry_page_start = reloc& (~(page_size - 1));
int ret = mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
oldval = *(unsigned*)
*((unsigned*)reloc) =
程序中调用mprotect的作用是: 修改一段指定内存区域的保护属性。以防万一,将这它改为可读写,因为后面就要对这块内存做写操作了。
为:int mprotect(const void *start, size_t len, int prot);
mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。
hook_call("libjavacore.so", "getaddrinfo", &my_getaddrinfo);
1.调用dlopen拿到so的句柄,得到soinfo,它包含了符号表、重定位表、plt表等信息。
2.查找需要hook的函数的符号,得到它在符号表中的索引。
3.遍历plt表,直到匹配第2步中找到的符号索引。
如果是JUMP_SLOT类型(函数调用),替换为新的符号地址(函数指针)。
如下图所示,my_code_func的函数地址替换了GOT表项中原来指向libc中的getaddrinfo函数地址,达到了hook的效果。
跟进一步地,可以把设备上的libjavacore.so导出,用IDA Pro打开,观察getaddrinfo的引用关系,将有助于理解上面的代码。
找到libjavacore.so中getaddrinfo导入符号的位置:
定位到getaddrinfo在plt表中引用的位置:
定位到getaddrinfo在GOT表中引用的位置:
定位到在代码段中调用getaddrinfo的位置:
通过分析得知,虽然getaddrinfo是libc.so的导出函数,但是这种方法无法hook导出函数,没有一劳永逸的方法,只能hook导入函数,因为这种方案是通过修改GOT表项实现的,这是它的缺陷。
3、webview
webview作为H5的容器,在做网络请求的时候也需要做DNS域名解析,要对其接入HttpDNS的一般做法是通过拦截WebView的各类网络请求,截取URL请求的host,然后调用HttpDns解析该host,通过得到的ip组成新的URL来请求网络地址。
不过这种方式只能处理资源,处理正常的http/https请求会存在问题。
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (request.getMethod().equalsIgnoreCase("get")) {
String url = request.getUrl().toString();
if (url.contains(".css") || url.endsWith(".png")) {
URL oldUrl = new URL(url);
URLConnection connection = oldUrl.openConnection();
String ips = MSDKDnsResolver.getInstance().getAddrByName(oldUrl.getHost());
String newUrl = url.replaceFirst(oldUrl.getHost(), ip);
connection = (HttpURLConnection) new URL(newUrl).openConnection();
connection.setRequestProperty("Host", oldUrl.getHost());
return new WebResourceResponse("text/css", "UTF-8", connection.getInputStream());
必须要对webview的DNS域名解析函数进行拦截替换。
webview的DNS域名解析函数具体实现是在chromiumn.so,不同版本的实现也不同,5.0版本的代码见
webview的DNS域名解析函数是否也跟java的网络库一样最终调用的libc.so动态库中getaddrinfo呢?
通过源码注释得知确实如此。
中也对其进行过断点调试。
所以解决方法很简单,只需要hook libchromium_net.so中getaddrinfo导入符号即可。
hook_call("libchromium_net.so", "getaddrinfo", &my_getaddrinfo);
在实践中我们发现,不同机型不同版本的android在实现DNS解析函数的导出符号是不同的,更糟糕的是调用DNS解析函数的动态库也不一定就是libjavacore.so。
我之前定位过Android5.0设备的DNS解析函数,发现它的名字改为android_getaddrinfofornet。
webview的so库位置也曾遇到过找不到的问题。
解决方法是通过一个脚本,pull下测试设备上的所有so到主机上,然后用readelf工具查找so的导入符号,观察是否有getaddrinfo字样的导入符号。
为此我写了一个,方便自动化进行。运行如下命令即可
$ python sofinder.py -e getaddrinfo
在上面输出的第一行可以看到,android 5.0以上版本webview的so已经被放在system/app目录中了。
需要写全so的路径:
hook_call("/system/app/WebViewGoogle/lib/arm/libwebviewchromium.so", "getaddrinfo", &my_getaddrinfo);
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:
没有更多推荐了,客户端改为https+httpdns后的抓包教程 - 简书
客户端改为https+httpdns后的抓包教程
背景介绍:
安卓6.2.4版本开始尝试启用https+httpdns,给我们的抓包工作带来了一定挑战(主要是需要连测试环境测试时)!!以后测试有料的过程中,做安卓端的测试一定需要安卓抓包,不过糕糕别怕,我们已经踩过一些坑,现将抓包方法写在下方,参考进行一下配置即可。若有问题,及时再补充 ~
1.前提:保证你的charles可以抓https的包
2.手机连上charles代理,访问:下载证书
3.设置External Proxy Settings
Paste_Image.png
4.勾选“Use external proxy servers”,"Web Proxy(HTTP)","Secure Web Proxy(HTTPS)"
并在右侧设置Web Proxy(HTTP)和Secure Web Proxy(HTTPS)为127.0.0.1:8887(端口号根据自己的mitmproxy端口号设置)并保存
Paste_Image.png
5.启动自己本机mitmproxy,命令行输入mitmproxy查看是否安装?若未安装--&输入“brew install mitmproxy”,等待安装完成
6.设置端口号&代理地址(以代理到t000环境为例):mitmproxy -p 8887 -U
其中-p后为端口号,即填入第4步中端口号地址
7.设置完毕,将命令号置于后台即可,可通过charles正常抓包啦!(当然,mitmproxy中也可以看到请求的数据)
Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调导致了样板模式, 使用Spring Cloud开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式...
1.OkHttp源码解析(一):OKHttp初阶2 OkHttp源码解析(二):OkHttp连接的&前戏&——HTTP的那些事3 OkHttp源码解析(三):OKHttp中阶之线程池和消息队列4 OkHttp源码解析(四):OKHttp中阶之拦截器及调用链5 OkHttp源...
原文地址: http://blog.devtang.com//charles-introduction/ Charles 4 新增的主要功能包括:支持 Http 2。支持 IPv6。 安装 Charles去 Charles 的官方网站(http://ww...
目录 本文的内容主要包括: Charles 的简介 如何安装 Charles 将 Charles 设置成系统代理 Charles 主界面介绍 过滤网络请求 截取 iPhone 上的网络封包 截取 Https 通讯信息 模拟慢速网络 修改网络请求内容 给服务器做压力测试 修改...
简述 在测试app的时候,比如:页面无法展示内容(由服务端接口返回值提供),往往就需要去定位问题,找到所抛出的请求是否异常,pc浏览器和mac浏览器访问是可以通过平台提供的软件(Charles&fiddler)来实现,那么如何抓到手机抛出的请求呢?实现抓取手机网络请求 这里...
现如今,很多工业随着清洁工人的工薪以及清洁工人老龄化的增加,面临招聘难以及开支大等问题,所以,为了降低大部分的开支和解决清洁工人招聘难的问题,各大工业逐渐使用驾驶式扫地机来代替人工的清洁,那么,大型工业到底适不适合使用驾驶式扫地机,接下来合美小编就带你详细了解下: 大型工业...
都说结了婚的男人对女人的态度会有所改变,的确婚姻生活太平淡,两个人互相习惯了彼此的生活,互相越看越来越难受,都有情况发生。但是如果你想婚姻生活幸福,那么就要来学习一下怎么提升幸福感了。成都婚恋网蓉城热恋网王老师说。 首先你要学会表达感激。很多夫妻觉得和伴侣之间那么熟了就没必...
Swift中如果想获取字符串中的某个字符,通过Index索引获取,先来简单看一下几个简单的字符串获取字符的方法: 第一个方法获取的是第一个字符,如果想往后获取,需要通过advancedBy往后获取,注意如果获取最后一个字符,还需要调用一下predecessor方法: 我们来...
nsnsdhx nsxhdsn
神奇的微店
文/朱成龙 这是一家独一无二神奇的微店,不卖衣服不卖手机,专卖温暖和关爱。 习少强,人如其名,性格坚强,无所畏惧。 最初有这个想法的时候,是在十年前,那一年,爷爷奶奶妈妈爸爸先后因疾病思念意外和悔恨...互联网中间件
域名与网站
开发者工具
人工智能(AI)
大数据基础服务
大数据可视化服务
大数据应用服务
行业解决方案
大数据与AI解决方案
物联网解决方案
安全与运维解决方案
微信解决方案
微信小程序
服务与培训
移动解析 HttpDNS
移动解析(HttpDNS)基于 Http 协议向腾讯云的 DNS 服务器发送域名解析请求,替代了基于 DNS 协议向运营商 Local DNS 发起解析请求的传统方式,可以避免 Local DNS 造成的域名劫持和跨网访问问题,解决移动互联网服务中域名解析异常带来的困扰。
入门与使用
开发者资源
关注公众号,移动管理云服务
长按识别或截图保存关注公众号,移动管理云服务本文根据冯磊和赵星宇在&高可用架构&微信群所做的HttpDNS智能缓存库原理整理而成,转发请注明来自微信公众号ArchNotes。
冯磊,目前主要从事手机应用平台的构建,任职新浪网技术中国研发中心技术保障部架构师。5+年互联网,移动终端,游戏从业经验。历任软件工程师,高级软件工程师,技术经理。
赵星宇,HttpDNS的合作者。目前就职于新浪微博,从事手机微博的基础架构开发,任android高级研发工程师职位。
HttpDNS是使用HTTP协议向DNS服务器的80端口进行请求,代替传统的DNS协议向DNS服务器的53端口进行请求,绕开了运营商的Local DNS,从而避免了使用运营商Local DNS造成的劫持和跨网问题。 (具体httpdns是什么?详细阅读见(【鹅厂网事】全局精确流量调度新思路-HttpDNS服务详解):http://mp.weixin.qq.com/s?__biz=MzA3ODgyNzcwMw==&mid=&idx=1&sn=b2a152b84df1c7dbd294ea6&scene=2&from=timeline&isappinstalled=0&utm_source=tuicool)
鹅厂往事中提到
那么对于腾讯这样的域名数量在10万级别的互联网公司来讲,域名解析异常的情况到底有多严重呢?每天腾讯的分布式域名解析监测系统在不停地对全国所有的重点LocalDNS进行探测,腾讯域名在全国各地的日解析异常量是已经超过了80万条。这给腾讯的业务带来了巨大的损失。为此腾讯建立了专业的团队与各个运营商进行了深度沟通,但是由于各种原因,处理效率及效果均不能达到腾讯各业务部门的需求。除了和运营商进行沟通,有没有一种技术上的方案,能从根源上解决域名解析异常及用户访问跨网的问题呢?
HttpDNS主要解决三类问题:
LocalDNS劫持
平均访问延迟下降
用户连接失败率下降
LocalDNS劫持: 由于HttpDNS是通过ip直接请求http获取服务器A记录地址,不存在向本地运营商询问domain解析过程,所以从根本避免了劫持问题。 (对于http内容tcp/ip层劫持,可以使用验证因子或者数据加密等方式来保证传输数据的可信度)
平均访问延迟下降: 由于是ip直接访问省掉了一次domain解析过程,(即使系统有缓存速度也会稍快一些&毫秒级&)通过智能算法排序后找到最快节点进行访问。
用户连接失败率下降: 通过算法降低以往失败率过高的服务器排序,通过时间近期访问过的数据提高服务器排序,通过历史访问成功记录提高服务器排序。如果ip(a)访问错误,在下一次返回ip(b)或者ip(c) 排序后的记录。(LocalDNS很可能在一个ttl时间内(或多个ttl)都是返回记录
HttpDNSLib库组成
HttpDNSLib库主要由三个模块组成,查询模块,缓存模块,评估模块。
查询模块:
检查本地是否有对应的 domain 缓存
如果没有 则从本地LocalDNS获取然后从httpdns更新domain记录
有数据则检测是否过期 已过期则更新记录返回 LocalDNS 记录, 未过期则直接返回缓存层数据。
从HttpDNS 接口查询本次app开启后使用过的domain 记录定时访问,更新内存缓存,数据库缓存等记录
数据模块:
根据SP(或Wifi名)缓存域名信息
更具SP(或Wifi名)缓存服务器ip信息、优先级
记录服务器ip每次请求成功数、错误数
记录服务器ip最后成功访问时间、最后测速
添加 内存 -》数据库 之间的缓存层
评估模块:
根据本地数据,对一组IP排序
处理用户反馈回来的请求明细,入库
针对用户反馈是失败请求,进行分析上报预警
给HttpDns服务端智能分配A记录提供数据依据
HttpDNS交互流程
HttpDNS交互流程图:
从这张图中可以看出来 整个业务的交互流程,用户向查询模块传入一个URL地址,然后查询模块会检查缓存是否存在,不存在从httpdnsapi接口查询, 然后经过评估模块返回。在用户请求URL过程完毕时,需要将这次请求的结果反馈给 lib库的评估模块由评估模块入库记录本次质量数据。
HttpDns Lib库交互流程:
这张图就更深入的说了下 lib的工作原理。有两条竖线讲图片分为了三个区域,分别是左部分、中间部分 和 右部分。
左部分是app主线程操作的事情,中间部分是app调用者线程中处理lib库事件逻辑的事情,右面部分是新线程独立处理事件的逻辑。
开始是里客户端调用方,传入一个 url,获取domain信息后由查询模块查询domain记录,查询模块会从内存缓存层查询,内存缓存层没有数据会,查询数据库,如果数据库也没有数据会请求本地 LocalDNS。从三个环节中任何一个环节拿到数据后, 都会进入下一个环节,如果没有拿到数据返回null结束。进入评估模块,根据五个插件进行排序, 排序后返回数据给客户端。
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 即可。
工程代码一共有八个主要package包,分别是cache、httpdns、log、model、query、score、speedtest、networktype。
cache包数据缓存层
IDnsCache是该包的对外主要接口。DnsCacheManager 实现该接口,封装了管理该包的所有逻辑调度,ConcurrentHashMap是内存缓存层的介质,当初使用过非线程安全的hashMap遇到了很多线程锁的问题,没有更好的办法自己控制锁管理,就替换成线程安全的concurrenthashmap对象了。DBConstants 设定了数据库名字表名字以及表字段,包含全部sql语句。 DNSCacheDatabaseHelper 用来操作数据库,所有和数据库交互的逻辑都在该类。
networktype包用来监控网络变化和检测当前网络状态
Constants 设定了网络状态的相关常量。 NetworkManager类也是这个包的主入口类所有网络状态的获取都是通过这个类来获取。 NetworkStateReceiver用来注册网络广播来接受网络发生变化的事件 。
httpdns包封装了所有HttpDNS api交互请求
IHttpDNS接口定义了该包和外部交互的所有数据格式,HttpDnsManager 实现了IHttpDNS接口。 HttpDnsConfig定义了使用到的常量配置, 以及dns api接口的开关,和顺序。 requests包里INetworkRequests接口轻量级的定义了 网络请求的实现, 目前使用ApacheHttp实现的该接口,如果用户有需求更换网络实现方式实现INetworkRequests 接口即可。 IJsonParser 接口定义了 httpdns api返回数据解析json的方式, 目前使用 android jsonObject实现。 如果需要扩展直接实现该接口即可。
log包实现了记录dnscachelib库记录日志倒文件的工具类
IDnsLog约定了写log和获取log的方法。 HttpDnsLogManager实现该接口,并管理log模块。该模块还有一个写文件的工具类。
model包封装了全部数据交互模型
DomainModel对应数据库domain表, IpModel对应数据库ip表。 HttpDnsPack是获取httpdns api接口数据的模型 。 ConnectFailModel用来记录所有异常错误。
query包是查询模块的入口
IQuery定义了该包对外的协议接口。 QueryManager实现该接口封装了所有查询相关操作。
Score包也是前面说的评估模块
IScore定义该包对外实现的接口,ScoreManager实现该接口。 PlugInManager用来管理所有评估插件。 所有的评估插件均实现 IPlugIn接口协议,规定输入输出。使用者可以自行添加评估插件。
speedtest包实现测速逻辑
ISpeedtest规定该包对外的接口协议, SpeedtestManager实现ISpeedtest接口。 封装了测速相关逻辑, 包括空http请求,以及ping命令测速。
另外场景包种有几个类简单介绍下。 DNSCache类是lib的主入口类,用户的所有操作均调用该入口类,该类是单利类直接获取实例调用即可,也是主场景。
由于内部model数据过于复杂,为用户专门封装DomainInfo模型。 该类仅返回用户使用的相关数据。
DNSCacheConfig 是httpdns库的全局配置文件, 可以直接修改该文件,也可以外部调用方法设置参数 。 该文件还封装了云端动态更新缓存配置。
代码结构如下图所示:
在编写该库的时候遇到最头疼的问题可能就是多线程同时访问导致遇到的数据异常错误。比如用户访问 api.weibo.cn 域名该域名目前数据库中没有缓存,内存中也没有缓存。在同时有多个请求以来来获取该域名的ip的时候, 因为没有数据会去请求api接口获取数据, 导致同时开启多个线程访问数据。 解决办法在请求api接口前增加正在请求队列,
任何需要请求数据的domain都先要在该队列检测是否有请求存在如果没有在继续进入后面流程如果有则丢掉本次请求指令。 另外在操作数据库的时候使用了 对象锁和 synchronized 方法锁, 导致了程序有锁死的情况,后改成全部使用对象锁就解决了该问题。全程的调试数据也是最头疼的环节,后直接编写测试程序,时时调试所有环节的数据(看到时时数据后发现了很多程序的bug,后都一一解决)。
以上为冯老师的分享,接下来是星宇跟大家分享下项目从研发倒现在所遇到的一些主要问题和大家有疑问的点。
开发过程中,常见的一些问题
1、手机网络从3G 切换到 Wifi下处理了什么?
NetworkStateReceiver类来监听网络是否发生变化,在网络有变化的时候,会刷新 NetworkManager类中的网络环境,在客户端内如果是手机网络可以知道网络类型(2G、3G、4G)也可以知道当前SP(移动、联通、电信),如果是Wifi网络环境可以知道SSID(wifi名字)在刷新网络环境后,会重新查询缓存内是否有当前链路下的最优A记录,如果没有则从LocalDNS获取第一次,然后马上更新httpdns记录。
2、网络发生变化后,返回的A记录还一样么?
数据库中缓存的数据,是根据当前sp来缓存的,也就是说当自身网络环境变化后,返回的a记录是不一样的 。手机网络下会根据当前sp来缓存 a记录服务器ip,如果是wifi网络环境下 根据当前ssid来缓存a记录,因为wifi环境下库自己没有办法明确判断出自己的运营商,但相同的ssid不会发生频繁的网络运营商变化。 所以在wifi下请求回来的a记录直接关联ssid名字即可,即使wifi sp发生变化,最多延迟一个ttl时间就更新成最新的a记录了。
3、怎样进行测速?
在从HttpDNS获取回来a记录的时候进行测速,测速的方式有两种: ping和空的http请求。考虑倒有些服务器不支持ping来进行链路质量评判,可以使用空的http请求,仅仅是两个http头的流量开销,而ping的方式流量开销就更小了。 这个功能可以在库中自己配置。这里的测速其实是模拟首保接收的时间来做的, 同时对于流量控制严格的可以在库中配置测速频繁度,比如一台服务器在5分钟内有过测速记录则不进行测速。
4、域名ttl刚刚过期,库还没有从HttpDNS拉取回来数据怎么办?
ttl过期的前10秒去请求数据,在ttl过期后的10秒内库也认为当前a记录是有效的,会给你直接返回。
5、lib库目前只能使用 dnspod 服务商么? 支持dnspod 企业版本么?
目前库可以支持自定义的 HttpDNS api接口, 只需要实现IHttpDns接口类即可,在配置了dnspod企业key和id 的时候自动启用企业版本加密传输,支持企业版本。
6、使用这个库会不会降低应用请求网络的访问速度?
从目前的测试数据来看是不会的,HttpDNS库返回a记录的时间平均在5毫秒以内,有时会出现内存缓存中没有该域名记录,数据库中也没有的时候会从LocalDNS获取a记录,时间会稍长一些
一旦从LocalDNS获取后,会缓存倒内存中,在HttpDNS获取数据后会更新内存中得domain记录。 从库中获取a记录会比从LocalDNS获取a记录快一些。 在访问网络的时候由于是使用ip直链,可以起到一些加速效果,lib库获取domainA记录 + ip直接访问服务器 耗时小于 直接域名请求服务器。相关数据图片
下面给出一个测试系统的截图
7、lib库里面访问网络使用的是哪个网络库? json库用的是哪个?
考虑到该库的轻量级,使用的是android系统的org.apache.http.client.HttpClient库访问网络,如果需要切换到工程在使用的网络库可以实现 INetworkRequests 接口即可切换网络库。 json解析使用的也是android系统自带的org.json.JSONObject 如有需求切换json解析库,可直接实现IJsonParser接口即可切换。
8、使用该网络库会给我的app带来多大的体积增加?
目前该lib库没有引用任何外部的库文件。一切本着使用系统自身的api为原则,来保证库的轻量级,和兼容性。 目前lib库打包后70多k,代码在5千行左右。 测试工程代码在6千行左右。
9、lib库的配置必须要通过修改源代码的方式来进行配置么?
任何参数都可以在库调用方配置,DNSCacheConfig 类是整个库的配置文件。 并且支持云端动态更新配置 需要实现DNSCacheConfig.ConfigText_API 更新地址。 具体配置api接口请参考 dome工程中设置库的方式。
10、缓存domain记录是存储成文件还是数据库,或者android内部的一些存储方式?
lib缓存数据是通过数据库存储的。SQLiteDatabase, 具体的表接口和sql语句请参考 DBConstants 类文件。
11、 评估模块有什么功能?
评估模块目前由五个插件组成, 速度插件、推荐优先级插件、历史成功次数插件、历史错误数插件、最近一次成功时间插件 。 每一个a记录服务器ip,都会经过这五个插件进行评估排序后返回给使用者。 所有插件评估分值比重可以配置, 根据自己的需求以及不同的使用场景,调整出最合理的权重分配。
下面给出评估模块算法细节图
12、速度插件具体算法?
比如速度插件评分体系, 满分100分, 那么有3个服务器ip, 1号服务器http请求耗时10毫秒, 2号服务器20毫秒, 3号服务器30毫秒。 那么经过插件计算后 1号服务器100分, 2号服务器50分, 3号服务器25分。
13、优先级插件又是什么?
如果是自定义的服务器,可以返回服务器优先级字段,该的字段代表推荐使用该服务器的权重, 比如该字段服务端可以和监控系统结合起来,甚至是用来分流。 相应的权重值, 也会算出来不同的分值。
14、历史成功次数插件是什么? 历史错误次数插件是什么?
在当前sp当前链路下, 会记录访问过的该服务器ip的成功次数, 成功次数越多认为该服务器相对稳定。 会在排序的时候根据权重比值进行影响最终排序结果, 该插件权重不建议过高。 同理历史错误插件也是记录当前链路下服务器出过错误的次数,次数越高认为越不稳定。 排序尽量靠后。 同样该插件权重不建议过高。
15、最后一次成功时间?
如果该服务器在 很近的时间内访问过,那么评估系统则认为他链路是通的,则会给一个分值, 越接近现在的时间的服务器 分值越高。 24小时以前访问的分值为0 。
16、评估插件就这五个吗?
该五个插件属于抛砖引玉, 可以自定义插件 只需要实现 IPlugIn 接口即可。 所有的插件启用和停止都在 配置文件中可以修改,以及配置每个插件的权重比。
17、智能评估一定会带来好的效果吗?
首先httpdns返回的a记录已经是 经过当前地域和当前sp返回的最优记录结果集, 至少不会降低效率。
18、我可以不使用智能评估模块么?
可以的在配置文件中关掉智能评估即可,具体代码参照demo即可。 关掉智能评估模块后,会在多个a记录中随机排序返回。
19、该Lib库块兼容性如何?
使用testin兼容性测试 测试兼容性结果:99.49%。 Android平台全部由java代码开发,没有使用任何特殊特性,覆盖全部系统版本。
最后附几张测试工程效果图:
模拟了客户端访问http请求,分别标识了每个任务的详细信息。
这个页面全都是数据库相关配置,在代码中可以直接找到具体设置库文件的接口。
数据报表入口,包含全部任务加速效果延迟效果数据记录, lib库耗时走向,每个ip直接访问请求和domain访问请求速度对比, 统计了服务器平局速度。
缓存数据标签中包含了 当前库的所有状态, 能实时的看到内存缓存层的所有数据状态,包括数据库中得所有数据状态。 每秒钟刷新一次。 在这里可以清空缓存层数据、数据层数据、已经当前测试工程的数据。 在这里你可以清楚的看到 ip 和 domain的对应关系, 以及数据库表中 每项的关系。 和所有的domain 以及 ip 的状态。
全部代码 均已开源 https://github.com/SinaMSRE/HTTPDNSLib , 包括测试工程 也开源了 设计文档 和 流程图都在 git 上有。 测试工程的 ui psd 貌似也在git上
Q1、每次请求url都需要去ping么?
不需要每次都ping的, 测试链路是否通畅 会在 从 httpdns api接口获取数据后, 在测试链路是否通畅, 每次请求 httpdns api间隔是一个 domain 设置的 ttl时间
ping 直发一个包, 最小化的减少 流量开销。
检测链路 如果配置成 http 空的请求, 也是同理 在 httpdns api请求结束后, 才会检测链路是否畅通。
Q2、前面提到的并发请求,被丢弃的请求是怎么处理的
并发请求是说 客户端请求 HttpDNS lib库 ,同时发 api.weibo.cn 的请求么?
因为 去问 HttpDNS api接口的时候 , 只需要有一个请求去问就可以了, 去问 HttpDNS api的时候 已经切换到 非客户端主线程, 在客户端调用的主线程中 如果没有缓存数据 就从 本地获取 dns 的a记录返回了。 所以直接丢弃这个访问 HttpDNS api的请求即可, 不会影响到其他流程逻辑。
Q3、南北网络之间请求有特别处理么?
南方电信,北方网通,运营商ip不一样
首先 HttpDNS 返回的a记录会根据你的出口ip 来从权威的 dns 服务器问出来结果。 如果你是南方的ip 肯定给你的a记录 也是南方的, httpdns 返回的记录理论应该是和 传统的 dns 返回的 a 记录是一样的。 而去问 httpdns 的api 地址 是 bgp的机房。 所以 也是 兼容多链路 多地域。有遇见过 传统 dns 出口可能是 电信的, 但业务访问的 ip 出口是联通的情况。 所以 HttpDNS 访问 a记录 也能避免这类一部分错误。
Q4、用dnspod是用的他的接口么?如果dnspod上是配置的是cname,会递归解析出最终的ip缓存下来么?
会的。 这个依赖dnspod的返回结果, 同时也支持 cname 的返回结果。
比如 图片使用 cdn 如果返回的是 cname 结果。 那么数据库中记录的也是 cname 结果。 通过 cname 家 host 头来访问也是可以的。
Q5、数据库中记录的是cname,还是cname解析出的ip?
数据库中记录的是 cname , 并不是ip 。
因为测试过, 从一栋大楼走到另外一个大楼 里面 访问的最终ip可能都不相同。 所以如果返回的是cname 则直接存储cname 。 网络环境发生变化, 会重新拉取, 不会使用缓存的cname 。
Q6、那cname的情况下,httpdns就起不到实际的作用了?
不会的, 一般劫持的都是 业务的主要域名, 而cname域名的劫持相对较少, 从我们公司的业务来看啊。 而且 dnspod 返回cname 的情况 我目前还没看到。 都是解析倒ip 。 而我们自己做的 httpdns 服务器, 第一期目前会解析倒 cname 的节点。 跨域的ip解析 还没做 会放到二期。
Q7、我们遇到的问题是主域名解析没问题,cname的域名是amazon aws的域名,经常莫名其妙解析不通,怀疑是运营商搞鬼。当时也想自己做这个httpdns,但发现很麻烦,小厂没人力搞这个事情。
有这个可能,我觉得可以把你们的domain放到dnspod里面试下解析出来的是不是cname如果是直接的ip应该没问题。后期我们有计划加上udp直接发送dns协议包到公共的dns服务器节点来获取数据,也支持设置自己家的权威dns服务器。
http://www.tuicool.com/articles/7nAJBb
阅读(...) 评论()}

我要回帖

更多关于 unity3d人才过剩 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信