- 问题背景
- 知识背景
- DNS解析存在多级缓存(此处仅列举到DNS服务器层;后续流程不涉及)
- DNS一对多域名的解析随机性
- DNS 域名解析负载均衡缺点:
- 可能方案
- 方案一、dns解析层面控制DNS解析结果
- 1.1 通过内置DNS服务器控制IP解析(伪造DNS)
- 1.2、让备机nginx的状态能够影响DNS服务器解析
- 方案二、在DNS解析到备机后,提供备机跳转解决方案
- 2.1 、在访问到备站点后,前端使用脚本/在备机nginx层进行域名重定向
- 2.1.1 nginx层控制
- 2.1.2 备机页面脚本层控制
- 2.1.3 前端登录后检查层控制
- 2.1.4 问题:
- 直接域名重定向
- 先ip重定向到主站点,再重定向到域名
- ip重定向(方案可行,不会造成死锁)
- 2.1.5 尝试解决ip地址反向转换域名
- 尝试1 nginx 采用不同的方式重定向,看看是否有方法不改变浏览器域名
- 尝试2 前端使用html5 history.replaceState特性修改地址栏
- 2.2 在nginx进行反向代理,代理所有备机请求到主机;
- 2.3 新增nginx节点,DNS固定解析到改节点(1对1),再在该节点转发主备节点
- 三、结论
实现多活主备状态下,用户通过域名访问网站,避免用户访问到备站点;
总结一下:
- 同时存在多个nginx容器活跃,需要用户每次通过域名访问,都能访问到特定的nginx容器;
- 主备站点角色可能随着主备状态互换,即原来是主站点的,可能后来是备站点;
- DNS服务器为第三方提供,无法深度定制;
- 备机需要能够通过ip单独访问;
当一个域名对应多个IP时,DNS解析具有随机性;常用此做服务器的负载均衡;
DNS 域名解析负载均衡缺点:- 目前的DNS是多级解析的,每一级DNS都可能缓存A记录,当某台服务器下线之后,即使修改了A记录,要使其生效也需要较长的时间,这段时间,DNS任然会将域名解析到已下线的服务器上,最终导致用户访问失败。
- 不能够按服务器的处理能力来分配负载。DNS负载均衡采用的是简单的轮询算法,不能区分服务器之间的差异,不能反映服务器当前运行状态,所以其的负载均衡效果并不是太好。
为了实现问题,总结下来,只可能有2种解决方案:
- 在DNS解析层面,控制DNS解析结果
- 在DNS解析到备机后,提供备机跳转解决方案
DNS服务器在实际使用场景中,均为客户提供的第三方DNS服务器,无法控制第三方DNS服务器解析的规则;且即使成功控制,由于存在浏览器缓存、本地缓存等多种不可控因素,不可避免还是会存在解析到备机IP,此方案不可行;
1.2、让备机nginx的状态能够影响DNS服务器解析目前DNS服务器解析不会判断服务器状态。无法通过主备机的状态改变影响DNS服务器解析;
再者。由于存在浏览器缓存、本地缓存等多种不可控因素。不可避免还是会存在解析到备机IP;此方案不可行
综上所述 在DNS解析流程 进行干扰无法达成目的;
方案二、在DNS解析到备机后,提供备机跳转解决方案 2.1 、在访问到备站点后,前端使用脚本/在备机nginx层进行域名重定向访问到备站点的控制点,有3个;
- 第一个是请求到达备机nginx层,
- 第二个是备机页面脚本层(页面加载后)
- 第三个是前端登录后检查;
这三个检查点时间应该是越早,用户感知调整约少,对用户体验越好;
2.1.1 nginx层控制请求到达nginx后,需要做跳转,前提需要知道主机IP。这里实现方案有2个:
- 集成njs或者lua模块进行Http请求(需要接口免鉴权)
- 倒换时手动刷新nginx配置 并进行reload
当DNS解析到备机页面后,在页面能执行脚本的最早时机,通过免鉴权接口,获取主备状态进行跳转;
2.1.3 前端登录后检查层控制当主备状态接口因安全原因无法免鉴权使用时,需要通过登录后脚本检查;此时需要做平滑重定向的方案有2个:
- 弹出页面,提示用户点击后跳转
- 登录的同时,获取主备状态,如果自己是备机,则重定向到主机ip,同时传递token,使用户无感知;前提:主备机token需要共享
不管上述哪种方式,都只能重定向到主机IP。无法重定向到域名。原因是域名重定向 还是会走DNS解析;如果解析到备机IP,会造成重定向死循环;如下图两种方案
直接域名重定向DNS 模块包含浏览器缓存DNS、操作系统DNS和DNS服务器,指DNS解析过程
如图红线走向正常,蓝线就会导致重定向死锁
如图红线走向正常,蓝线就会导致重定向死锁。
redirectflag是为了区分跳转请求和非跳转请求,只有对于跳转请求,才会重定向到domain.com;否则不跳转;
所以,按照这种方案,会造成一个致命问题,用户访问的是域名,结果浏览器地址栏可能会显示ip地址;
2.1.5 尝试解决ip地址反向转换域名背景:浏览器输入ip地址 不会有DNS解析流程。为什么反查不了域名?
尝试1 nginx 采用不同的方式重定向,看看是否有方法不改变浏览器域名如果输入的是域名,先查找本地有没有缓存对应的地址和域名的映射,如果没有会将其发往DNS服务器查询对应的映射。也就是说getHostName可能会get到空值的情况,在这种情况下会自动向DNS服务器去反向查询域名,如果能查到就返回域名,查不到就直接把IP地址当成域名。由于安全问题(一开始我们用nslookup就可以看到返回的服务器并不是baidu,而是它的外壳),再加上网络过于复杂(IP相对域名来说太不稳定,域名经常好几年不变但是IP经常变化,导致了现在某个IP对应的域名过段时间或许就对到另一个域名上了;或者直接是域名不一样但是IP是一样的,这时候如果返回所有域名对安全性也没有保证),国内各大网站的服务器基本都不允许通过这种方式反向查询域名,所以基本上都查不到直接返回IP地址。但是有一个是绝对查得出来的,那就是本机上的IP地址(因为本机上IP的映射一定是保存在本机文件里面的,所以能找到)
301-309状态码均尝试 不可使用;
尝试2 前端使用html5 history.replaceState特性修改地址栏这种方法只能同域情况下修改url链接。但是无法跨域(ip切域名属于跨域)
该条路无法实现;
2.2 在nginx进行反向代理,代理所有备机请求到主机;这种方案的思路是,利用nginx的反向代理,代理所有备机请求到主机,让用户访问到备机后,备机作为代理机,访问主机。从而让用户感知不到任何差异。
SMC3.0由于逻辑复杂,可能无法实现;
- 架构层面设计不合理:业务上,从只转发自身站点的请求,转变为需要转发到其他站点的请求;
- 实现层面:如何区分本站请求和域名转发的ip请求;通过备站点添加访问规则做条件代理,但是内部交互如果使用备站点ip,会导致请求被强制转发到主站点,要做大量适配;
这种方案,在不考虑容灾的一般架构下可以实现;但是对于考虑容灾的场景,新增的nginx节点无法做容灾管理。故不讨论;
三、结论nginx反向代理在服务器架构简单的情况下,可以实现;不考虑容灾和架构破坏的情况下,nginx代理节点可以实现;但是排除以上两种情况,如果希望定向ip解析,同时浏览器还需要显示域名,按照当前技术实现不了。如果有博友能够有其他方案,欢迎讨论~



