文 掘金号 wandyers @每日优鲜
著作权归作者所有。商业转载请联系本账号获得授权,非商业转载请注明每日优鲜大前端团队以及原文地址。
注:本文为系列文章,将分为方案简介,方案落地方案,具体方案剖析,技术实现细节等多篇文章,敬请期待。
背景
因部分地区App域名解析出现问题,导致部分B端App等(以下统一简称App)都出现网络请求超时,找不到主机或异常错误,导致部分配送App无法登录、使用等问题,影响了部分To B业务。
目标
尽量消除因外部网络原因(如外部DNS解析异常、域名不可达等)导致的App出现网络异常的问题。 经过调研,我们总结了下面的几种方案来防止类似问题再次发生,对比之后,我们最终也选择了部分策略做为我们的分批落地方案(步骤后续会详细讲解)。 我们的希望App达到避免DNS劫持,降低访问延迟,降低用户连接失败率,提升用户体验度,SDK高可扩展度及可复用性。
方案简介
以下的各种实现策略的简介及简单的优缺点对比。
方案详细
本章节将对上面提到的策略做出详细阐述,包括实现流程及部分重点细节。
1.系统DNS缓存策略
本策略即现在的实现策略,无需额外开发,使用域名进行请求,依赖系统DNS和网络服务商的DNS解析等。不再详细说明。
2. 直连策略
直连方案实现较为简单,当使用域名访问出现找不到主机,请求超时等异常时,直接切换至IP地址重试请求;且App在下次启动之前,一直使用该IP进行网络请求。
IP或域名优先级为: LocalDNS(域名) > 内置固定IP。
流程图如下图所示:
本方案实现较为简单,在紧急时可以作为临时过度方案。但不建议长期使用此策略,因为App内置的IP无法实时动态更新,会增加未来的风险。
3. 配置文件策略
App首次启动时(包含冷启动),请求后端接口下发配置文件,数据格式可参照附录一定义,并持久化缓存在App客户端本地以供将来使用。
当App启动时,从缓存读取出来配置,并验证有效期。如全部过期,则使用域名或系统内置的IP使用;如部分未过期或全未过期(其实大部分情况下,即使IP过期,在一定时间段内还是有效的),则按照优先级次序使用IP地址直连请求;
IP或域名优先级为: 配置文件IP > LocalDNS(域名)> 内置固定IP 。
此方案相比较直连方案,更加灵活,后台可随时更换IP地址而不影响生产环境客户端。
但会出现当域名不可达时间段较长时,或者用户在较长时间段内未打开App,而打开时正好域名不可达,导致缓存配置文件的全部失效,进而降级至直连方案。简而言之,配置文件TTL时间阀值不好控制,不够灵活。
因为每次App启动都会请求配置文件并更新本地缓存,无法根据每个IP的TTL灵活的更新。
这种方案也会与项目耦合度较高,不利于扩展,各端都需要实现自己业务逻辑,与实际业务耦合度较高。
缓存文件或数据的安全性校验也必不可少(此部分将在后续的分享中详细阐述),防止被第三方恶意篡改导致出现异常。
参考流程如下图所示:
以下两种策略都是基于HttpDNS。HttpDNS是以Http或Https的方式向外提供域名解析的服务。与传统的运营商的Local DNS相比,有以下几点优势:
一、 防止出现DNS劫持
二、 可实现精准调度,让客户端接入最近的业务节点
三、 0ms解析延迟
四、 快速生效
五、 扩展性强
4.第三方HttpDNS策略
腾讯云HttpDNS,阿里云HttpDNS,DNSPod等厂家提供HttpDNS方案,客户端接入方便,开发量较小,相对稳定。
但由于依赖第三方服务,不能自定义一些依赖规则,比如分流等。且第三方服务也可能出现服务异常进而导致我们的网络状态不可控。
拓扑图如下图所示【图片参考于网络】:
流程图与自建HttpDNS方案相似,请参考"自建HttpDNS"章节流程图。
5.自建HttpDNS策略
自建HttpDNS就是提供私有的DNS解析服务,以Http或Https的方式向外提供服务。严格来讲,此方案不是降级策略,而是使用自建DNS替代系统DNS拿到直连IP进行网络请求,而把系统级的缓存作为最后的降级方案。
独立域名或独立IP提供HttpDNS域名解析服务,自研HttpDNS的SDK实现与服务器的通讯;各端App接入SDK并完成Http DNS的解析工作,并根据域名拿到部分或全部可用的IP地址列表,不再依赖现有域名访问后台服务,每次均采用IP的方式访问服务。
拓扑图如下图所示【图片参考于网络】:
App在启动时,需要按照以下流程完成SDK初始化,访问业务接口时,直接使用IP访问,降低延迟,避免DNS劫持等问题,也能方便的集成在其它App中。
IP或域名优先级为:自建HttpDNS > LocalDNS(域名) > 内置固定IP 。
主要流程图如下图所示:
自定HttpDNS与配置文件策略的区别在于,第一提供SDK供多端快捷接入;第二能对单个IP的生命周期进行管理;第三SDK接入方不需要关心IP的管理,只要根据SDK返回的IP或域名(无有效IP时自动切换为域名)进行网络请求即可。
关注问题
- 无论采用哪种方案,都需要考虑Header中Host参数配置问题,Https的证书校验问题,SNI等问题,App内嵌的网页的网络请求等问题。
- 无论采用何种方案,都默认使用App内部固定的IP作为最后的容灾方案。
- 相同优先级中存在多个IP有效时,采取轮询或优先级的方案就行分流。
上面提到的问题,都将在后续的分享中说明相关实现方案。
建议方案
基于以上阐述,考虑App现状,建议初始阶段暂时采用直连策略(DS001)或配置文件策略(DS002),在既能减少生产环境问题。App能正常访问的前提下。
第二步根据实际情况,建议尽快实现或接入第三方HttpDNS策略方案(DS003)或自建Http DNS方案(DS004),并实现自己的SDK供多端使用,此方案在灵活性,扩展性,可维护性,可控制性上比其它方案更加有优势。
附录
附录一
[
{
"hostName":"a.test.cn", //域名
"ips":[ // 域名对应的IP地址列表
{
"priority":1, // 优先级
"ipAddr":"192.168.1.23", // ip地址
"ttl":1568859453 // 超时时间
},
{
"priority":1,
"ipAddr":"192.168.1.23",
" ttl":1568859453
}
]
},
{
"hostName": "b.test.cn" ,
"ips":[
{
"priority":1,
"ipAddr":"192.168.1.23",
" ttl":1568859453
}
]
}
]
复制代码