8

我维护一个包含大量可下载文件的站点。它目前托管在美国的服务器上,但我最近在德国购买了一台新服务器。我想将下载镜像到德国的服务器,并在第一台服务器(托管网站)上有一个 PHP 脚本,根据用户的位置检测要使用的文件镜像。例如,如果用户在加拿大,他们应该从我目前在美国的服务器下载文件。如果他们在法国,他们应该从德国获取文件,而不是跨大西洋下载。那么,我怎样才能确定他们离哪个国家更近呢?

我知道 MaxMind GeoIP,并安装了它,但这只是给了我一个国家,而且 AFAIK,没有办法自动确定给定国家最接近我的两个镜像国家中的哪一个。我想我能做的就是按大陆:让亚洲、欧洲、非洲和澳大利亚的用户从德国获取内容,让北美和南美的访问者从美国获取文件如果有人能想到更好的解决方案,我愿意接受建议。


好吧,我想我会按照我最初的按大洲检查的想法去做。对于其他想要做这种事情的人来说,这将是一个很好的起点。当我在欧洲有多个镜子时,问题就会出现,但大陆的想法现在必须奏效。

4

5 回答 5

2

到目前为止,在提议的解决方案中似乎存在很多开发人员开销。如果这是我必须在自己的应用程序中解决的问题,我可能会选择重新发明轮子来节省几个小时的工作时间。

确定最近的镜子(使用邮政编码)

  1. 为可用的镜像服务器维护一个数组中的邮政编码列表。
  2. 确定用户代理的邮政编码(例如用户输入或 PHP 库)
  3. 计算两个邮政编码之间的距离(例如PHP库)
  4. 根据返回的距离继续选择镜像

请记住,更近的距离并不一定意味着更快的响应时间。但是,在您的场景中,假设两个镜像都打开,一个国家的镜像显然会比另一个国家的镜像快。继续阅读我认为更“强大”的解决方案。

资源和链接

“特立独行”的方法

在我看来,Mavericks 也被称为我们今天都在使用的这些伟大的库和框架的创新者、问题解决者和发明者。有时错误地与“hackish”想法相关联,但我们接受了补充:)

  1. 在将接受 $_GET 或 $_POST 请求的任一镜像服务器上创建您自己的 API 服务。

  2. 此 API 服务将获取它提供的 IP 地址并 ping() 它,计算响应时间,然后取平均值,将其返回到请求接口(例如,客户端连接的前端门户和/或服务器尝试连接确定最近的镜子)。响应速度最低的服务器应该是您响应速度最快的服务器,尽管不一定是最近的。哪个对你更重要?请参阅Ping 站点并在 PHP中返回结果以获取不依赖于本地执行 shell 命令(例如平台无关)的工作 ping() 函数。

  3. 最后一步,派生请求客户端的 IP 地址并将其传递给您在后台镜像服务器上运行的 API 服务。我们都知道如何获取 IP,但并不像你想象的那么好。如果您是负载平衡的或在代理之后,您可能需要首先检查是否有任何这些标头通过(HTTP_FORWARDED、HTTP_FORWARDED_FOR、HTTP_X_FORWARDED、HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP)。如果是这样,那可能是用户代理的真实IP 地址。

此时(第 3 步),您将比较每个镜像在 ping 用户代理时回复的平均响应时间。然后继续选择用户代理应该从哪个镜像下载。您将创建的服务流类似于以下内容:

  1. 用户代理访问门户
  2. Portal 使用后台 AJAX/jQuery 请求(或传统的 POST 和重定向)将用户代理的 IP 地址转发到在两个镜像上单独运行的 API 服务。
  3. 在镜像上运行的 API 服务 ping 它接收到的 IP 地址并返回它配置为获取的响应总数的平均值。
  4. Portal 读取返回的平均值并进行比较。

希望对您有所帮助并祝您编码愉快!

于 2012-05-03T16:21:53.800 回答
1

如果您只有两个镜像,请在浏览器中启动 AJAX 请求,从每个服务器下载 50K 文件。这足够小,不会对用户造成巨大的延迟,但足够大,可以使计时器测量差异显着 - 当然你应该稍微考虑一下这个数字。

然后,一旦你有一个“最佳时间”,设置一个 JS cookie 并在需要下载时重定向到首选镜像。测量可以从后台的下载页面开始,因此用户可能不会注意到延迟(当他们正在选择他们想要的文件时)。

您甚至可以在每个 AJAX 操作中回复“服务器负载”,并且不仅在响应时间上而且在当前负载上选择最佳服务器。因此,即使最近的服务器在德国,如果后者的负载明显高于第一个,英国用户也会使用美国服务器。

于 2012-05-03T10:55:49.207 回答
0

我不记得有任何图书馆可以做到这一点。但是,如果我有一个想法,而不是构建一个系统,那也许可以帮助您。

使用此距离计算器计算两个 IP 之间的距离。或者找出两个IP地址(一台服务器)和(一台访客)的经纬度并计算距离。这是一个伪代码

distance = ( 3956 *2 * ASIN( SQRT( POWER( SIN( ( 34.1012181 - ABS( latitude ) ) * PI( ) /180 /2 ) , 2 ) + COS( 34.1012181 * PI( ) /180 ) * COS( ABS( latitude ) * PI( ) /180 ) * POWER( SIN( ( ABS( - 118.325739 ) - ABS( longitude ) ) * PI( ) /180 /2 ) , 2 ) ) ))
于 2012-05-01T02:06:09.610 回答
0

执行 traceroute(将 traceroute 客户端配置为不解析主机名并且超时时间很小)。

根据跳数和 traceroute 客户端的位置(我假设它与 PHP 脚本相同)在美国和德国之间进行选择。

地理距离与网络距离和网络速度,或带宽成本无关。

除了 traceroute(因为它是一个 hackish 的小代码解决方案),我建议您使用 $_SERVER["REMOTE_ADDR"] 并在地理 ip 数据库中查找它以获取国家代码。如果国家/地区代码不是美洲​​大陆上的国家之一,为避免穿越拥挤的互联网骨干网,请回退到德国(此外,您可以将国家/地区代码设置为来自欧洲)。

设置 geo ip 数据库后,我建议您将范围内的 IP 地址从点格式转换为整数格式,以提高查询速度和便于查询。

根据我对上述地理 ip 数据库的经验,它很少错过也没关系。

于 2012-05-03T10:43:01.613 回答
0

正如你所说,使用像geoip这样的库并使用纬度和经度来比较镜子和用户之间的距离不是更容易吗?

我认为它不那么复杂,而且很容易实现,适用于 N 个镜像,并且您不需要要求 Zip 或其他类型的数据来进行参考

于 2012-05-03T17:10:30.943 回答