• 线上多域名实战


    本文博主给大家分享线上多域名实战,当线上主域名不可用的情况下,启用备用域名完成网站高可用保障。

    网站的高可用性一直是网站运维的重中之重。一旦网站宕机,不仅会造成巨大的经济损失,也会严重影响用户体验。备份域名就是一种实现网站高可用的重要手段。通过备份域名,可以在主域名不可访问时快速切换域名,保证网站正常运行。

    一、前情回顾

    博主上个星期,线上项目突然出现了少量用户无法打开项目网站,技术支持联系技术人员(也就是博主我)在用户电脑上复现了这一情况。

    经过博主排查,发现在客户电脑访问主域名时,会出现连接超时,通过 curl 进一步分析连接详情,举例如下:

    C:\Users\16697>curl -v www.wayn.com
    
    * Uses proxy env variable http_proxy == 'http://11.22.11.22:4780'
    *   Trying 11.22.11.22:4780...
    

    发现线上主域名在用户电脑上返回的 CDN 节点 11.22.11.22 存在访问不通的情况。博主便跟运维沟通 CDN 节点不通的问题,运维回复是 CDN 节点不通是无法避免的,要看 CDN 厂商对于用户的覆盖情况,建议线上项目使用多域名,并且每个域名使用不同的 CDN 厂商,最大限度避免主备域名都不可用。

    OK,得到的运维的意见,我们开始着手做多域名实现方案。

    二、购买备用域名

    实现域名高可用解决方案,首先需要准备一到两条与主域名功能和形式相似的备份域名。如下

    主域名
    www.wayn.com
    
    备用域名一
    bak1.wayn.com
    
    备用域名二
    bak2.wayn.com
    

    购买备份域名后,需要注意一下两点:

    1. 需要在域名服务商那设置DNS记录,将主域名和备份域名指向同一个IP地址。同时也需要为两个域名设置相同的CDN加速和安全证书,保证用户访问体验一致。
    2. 将备份域名的网站配置(nginx配置文件)与主域名保持一致。确保使用备份域名也可以访问我们的网站。

    三、主备域名切换实战

    这里我们介绍一下通过 JavaScript 代码来实现网站的主备域名如何进行切换。

    JavaScript 实现域名切换的流程如下:

    1. 在页面启动时,首先发起对主域名的请求,判断其是否能够正常响应。如果启动时主域名不可访问,就会访问备份域名。针对每个备用域名每隔一秒发送三次请求,如果都能访问成功则认为备用域名可用。代码如下:
    // ES6 的模块引入方式
    import fetch from 'node-fetch'
    
    const domain = 'https://www.wayn111.com'
    const bakDomains = ['http://bak1.wayn.com', 'http://baidu.com']
    
    masterDomainCheck()
    
    // 主域名检测,如果不可用会检查备用域名是否可用
    async function masterDomainCheck() {
      try {
        await fetch(domain)
        console.log('主域名启用成功')
      } catch (e) {
        // console.log(e)
        try {
          await getBakDomain()
          console.log('备用域名可用')
        } catch (e) {
          console.log('备用域名也不可用')
        }
      }
    }
    
    // 访问备用域名,返回其中可用的一个域名
    async function getBakDomain() {
      const apiPromiseList = []
      for (let i = 0; i < bakDomains.length; i++) {
        apiPromiseList.push(
          new Promise((resolve, reject) => {
            bakDomainCheck(bakDomains[i], 3, resolve, reject)
          })
        )
      }
      return await Promise.any([...apiPromiseList])
    }
    
    // 域名检测逻辑
    async function bakDomainCheck(url, count, resolve, reject) {
      console.log(count)
      if (count > 0) {
        try {
          await fetch(url)
          bakDomainCheck(url, --count, resolve, reject)
        } catch (e) {
          console.log('e')
          reject(e)
        }
      } else {
        console.log(`bak domain:${url} access success`)
        resolve({ url, count })
      }
    }
    

    以上代码经过博主实测,大家感兴趣可以将代码拷贝在本地跑一遍。

    1. 如果主域名启动时正常,则开始定时监测主域名的可访问性。每30秒发起一次请求,判断主域名的HTTP状态码是否为200。
    // 主域名正常,开始定时监测
    setInterval(() => {
      fetch('https://www.wayn111.com')
        .then(res => {
          if (res.status !== 200) {
            switchDomain() 
          }
        })  
    }, 30000)
    
    1. 一旦监测到主域名故障,开始调用 JavaScript 函数,找到页面所有包含主域名的链接,并将其替换为备份域名。
    // 开始替换页面内域名为备份域名
    function switchDomain() {
      let links = document.querySelectorAll('a')
      for (let i=0; ilength; i++) {
        if (links[i].href.indexOf('https://www.wayn111.com') > -1) {
          links[i].href = links[i].href.replace('https://www.wayn111.com'
                  , 'https://bak1.wayn.com')
        }
      }
    }
    
    1. 继续定时监测主域名,在主域名恢复正常时,调用 JavaScript 函数将备份域名的链接替换回主域名。
    // 定时检查主域名故障恢复,一旦恢复再切回主域名  
    setInterval(() => {
      fetch('https://www.wayn111.com')
        .then(res => {
          if (res.status === 200) { 
            switchDomainBack()
          }
        })  
    }, 5000)
    
    function switchDomainBack() {
      let links = document.querySelectorAll('a')
      for (let i=0; ilength; i++) {
        if (links[i].href.indexOf('https://bak1.wayn.com') > -1) {
          links[i].href = links[i].href.replace('https://bak1.wayn.com'
                  , 'https://www.wayn111.com')
        }
      }
    }
    
    1. 这样通过 JavaScript 检测域名状态与自动切换,可以最大限度减少域名切换造成的访问中断时间,确保网站高可用。

    希望大家通过这个案例,能对线上用多域名来实现高可用网站有一个较为全面的认知。网站过于依赖某单一域名存在潜在风险,备份域名的引入主要是解决少数场景下用户访问不通我们网站的问题。

    最后感谢大家阅读,喜欢的朋友可以点赞加关注,你的支持将是我的更新动力😘。

    公众号【waynblog】每周更新技术干货、线上项目实战经验、高效开发工具等。

  • 相关阅读:
    浅析目标检测入门算法:YOLOv1,SSD,YOLOv2,YOLOv3,CenterNet,EfficientDet,YOLOv4
    unity3d 布娃娃系统插件 PuppetMaster 木偶师
    十五、红外遥控器
    c++一级练习题
    基于图搜索的规划算法之A*家族(七):Field D*算法
    springboot获取不到客户端ip问题排查
    CC002:ContextCapture倾斜摄影建模流程
    一文总结提示工程框架,除了CoT还有ToT、GoT、AoT、SoT、PoT
    Mysql 事务的概念-隔离级别-锁
    Java设计模式——单例模式
  • 原文地址:https://www.cnblogs.com/waynaqua/p/17344128.html