我的网络

不论我走到哪里,我的网络环境都是一致的。

实现目标

已知:

  1. 我的服务分散于ABC三地。
  2. 三地间网络可能会出现一定时间的全面中断。
  3. 三地间网络传输过程中充满了监听者。
  4. 三地间部分公网服务不互通,比如A地无法访问B地的某服务。

要求:

  1. 不论何时何地,访问我的服务应该都具有类似的体验。
  2. 不论何时何地,访问到的公网资源应该是三地公网服务的总和。

实现思路

CDN。其实就是想要CDN。但是因为已经有了一些其他的沉没成本,因此就直接自己动手搞。


实现细节

实现起来其实就是围绕着CDN思路展开。实现途径主要就是:域名解析,dns定制,nginx分流。物料准备:ABC三地各一台拥有公网ip的机器。(都是钱……)

域名解析

先说域名解析,这个最简单。就是将域名设置不同地区解析到不同ip。

我个人的做法是这样的:

对于xloypaypa.pub这个域名根据地域不同分别解析到a.xloypaypa.pub,b.xloypaypa.pub,和c.xloypaypa.pub。然后再将三个子域名解析到对应的ip。
这样做的理由有两个:

  1. 方便管理。甚至可以考虑让不同的人管理不同地区的服务。
  2. 允许强制访问某地区。方便调试,且后面nginx那边显然会用到这个特性。

dns定制

显然为了保证公网服务的体验一致。我需要保证我在abc三地的服务器里的V姓网络工具收到请求后知道到底该往哪里去,而默认各地的解析是按各地的服务走的,因此要统一三地的dns解析。

于是我写了一个dns-relay,已经放在了open infra的主页上了。这个中继会把每次的dns查询分别向三地都查一次,然后根据写好的逻辑,选一个结果返回。举个例子对于bilibili我们采A地的解析结果,对于知名搜索引擎baidu我们采B地的解析结果。这样V姓网络工具再根据目标ip处于何地来决定向何处转发。

就使用上来说,只需要无脑将公网请求发往各地的V姓网络工具,就可以实现各地体验一致。

最后举个例子:

假设,现在处于C地访问A地公网资源。那么访问流程大概如下:

  1. 将访问请求发往C地V服务。
  2. C地V服务向C地DNS服务查询DNS。
  3. C地DNS服务向ABC三地DNS服务器查询当地dns。
  4. C地DNS服务选择A地DNS结果。如果A地查询失败,则采B或C地的结果。
  5. C地V服务根据C地DNS服务的结果选择将请求发往A地服务器。
  6. A地V服务访问公网。
  7. A地V服务将结果返回给C地V服务。
  8. C地V服务将结果返回给用户。

Nginx分流

上面我们已经保证了公网访问的一致。那么对于自己的服务的一致的方法就变得比较比较显而易见了。简而言之,就是各地都接受服务的访问,然后看情况发往目标地。

我个人的做法是维护一个公共的nginx配置,同时各地再维护一个特例的nginx配置。其中特例配置会覆盖公共配置。

公共的nginx配置需要定义的内容是:某某某服务,转发往A地的域名。比如blog.xloypaypa.pub,这个服务host在B地。公共配置中,server_name ~^blog\..*xloypaypa\.pub$;的upstream都是blog.b.xloypaypa.pub
对于A地和C地的nginx,特例配置里就不需要做任何事情。如果收到请求,那么就直接根据公共配置转发往B地。
对于B地来说,特例配置里需要在特例里添加同样的server_name的配置,并将upstream指向这个服务的ip。这样如果B地收到请求,就会忽略公共配置,而直接访问那个服务。

如果到此为止,就会有个缺陷:就是如果A地与B地网络不通的情形。假设三地之间只有AB两地不通,那么其实A地可以通过C地转发请求进而访问B地管辖的服务。因此对于A地来说,会做类似如下配置:

upstream b.xloypaypa.pub {
    server b.xloypaypa.pub:443;
    server c.xloypaypa.pub:443 backup;
}

upstream c.xloypaypa.pub {
    server c.xloypaypa.pub:443;
    server b.xloypaypa.pub:443 backup;
}

也就是说,A地访问B地会优先直接访问,如果失败再采用C地的地址。

但这其实会导致另一个缺陷,那就是AB和CB都不通的时候,AB两地可能会对请求进行无限转发。因此这里只是提供一个简单可用的伪代码,具体重试策略啥的还是要自行取舍(nginx这一块还蛮复杂的)。


大概网络结构就是这样。我觉得还是比较简单,就是贵了一些。但如果本来就有内网穿透的需求的话,其实成本就是沉没成本,就还好。至于扩展性我认为其实还可以,显然是可以很容易新增一个D地。