归档:构建服务重定向器
| 本文关于开放构建服务的文档已过时! 您可以在 https://github.com/openSUSE/MirrorCache 上找到最新的信息 |
openSUSE 下载重定向器
历史
为了方便 openSUSE 的下载,第一个下载重定向器版本于 2005 年底开发完成,并在 2006 年的 FOSDEM 上展示。这个第一个概念验证并没有包含今天重定向器所具备的任何功能,该重定向器可以在 download.openSUSE.org 上访问。
重定向器的前两次迭代是用 PHP 编写的。它们被 (当前的) C 作为 Apache 模块的实现所取代。还有一个用 Ruby 编写的 prototype 实现,可以通过 FastCGI 集成,但是我们使用的是 Apache 模块。
后来,该项目成为一个独立的项目,现在可以在 http://mirrorbrain.org/ 上找到。
当前的实现是几位人士共同努力的结果。值得一提的人有 Jürgen Weigert 和 Martin Polster (scanner, mirrorprobe), (mod_mirrorbrain, mirrorprobe), (Ruby prototype)。当然,还有许多其他人也贡献了自己的意见,特别是 ,他实现了下载重定向器的前两次迭代。(这些不再使用,但当前的实现源于他们基本的的技术设计。)
它做什么?
download.openSUSE.org 的目标是提供自动且透明的镜像选择,根据每个用户的地理位置 (GeoIP) 和镜像性能,为他们提供最佳匹配。为了实现这一点,有一个完整的框架,形成了一种“镜像大脑”,它将镜像数据库作为每个镜像上每个文件的“状态缓存”。该数据库由镜像“扫描器”不断更新,该扫描器能够通过 ftp、http 和 rsync 爬取镜像。框架的另一个重要部分是监控,一个定期使用 HTTP 请求探测镜像的守护进程,以检查它们的在线状态 - 以确保随时提供正常重定向。这个框架的关键是重定向器本身,一个名为 mod_mirrorbrain 的 Apache 模块。它使用 MaxMind 的 GeoIP,一个将 IP 地址映射到国家和地区的免费数据库,以确定请求者的位置,然后查询镜像数据库以获取潜在镜像的列表,并选择最佳镜像。
大多数 openSUSE 下载 (download.opensuse.org, software.opensuse.org, ftp.opensuse.org) 都是通过这种方式处理的。有些不是 - 出于安全原因,某些文件 (如签名) 直接从 download.opensuse.org 传送。小文件是另一个例外,因为 HTTP 重定向的大小与直接传送小文件的大小相同,因此可以节省客户端的往返时间。此外,尚未在任何镜像上存在的文件,或不打算镜像的文件,将直接发送。总而言之,这些例外导致大约 50% 的请求被重定向到镜像。
有关技术实现以及背景文档的更多信息可以在 MirrorBrain 项目页面 上找到。
它是如何工作的?
镜像选择的方式可能最容易通过查看一些 伪代码 来理解。算法如下
do not redirect in certain cases:
is this a request for a directory index?
does the file exist?
is the file too small?
is the file excluded from being redirected by user agent / client IP / mime type / filemask?
canonicalize filename, resolving symlinks in the path
look up country and continent of client IP via GeoIP
if client country needs to be treated as another country:
/* New Zealand case -- pick a mirror from Australia */
client country = other country
mirrors =
SELECT file_server.serverid, server.identifier, server.country, server.region, server.score, server.baseurl \
FROM file \
LEFT JOIN file_server \
ON file.id = file_server.fileid \
LEFT JOIN server \
ON file_server.serverid = server.id \
WHERE file.path=canonicalized_filename AND server.enabled=1 AND server.status_baseurl=1 AND server.score > 0
results example:
+----------+----------------------------+---------+--------+-------+---------------------------------------------------+
| serverid | identifier | country | region | score | baseurl |
+----------+----------------------------+---------+--------+-------+---------------------------------------------------+
| 14 | ftp.ale.org | us | NA | 100 | http://ftp.ale.org/pub/mirrors/opensuse/opensuse/ |
| 18 | ftp.fi.muni.cz | cz | EU | 10 | http://ftp.fi.muni.cz/pub/linux/opensuse/ |
| 23 | ftp.iasi.roedu.net | ro | EU | 10 | http://ftp.iasi.roedu.net/mirrors/opensuse.org/ |
| 41 | ftp.uni-heidelberg.de | de | EU | 100 | http://download.uni-hd.de/ftp/pub/linux/opensuse/ |
| 44 | ftp5.gwdg.de | de | EU | 200 | http://ftp5.gwdg.de/pub/opensuse/ |
| 44 | ftp5.gwdg.de | de | EU | 200 | http://ftp5.gwdg.de/pub/opensuse/ |
| 70 | ftp.nux.ipb.pt | pt | EU | 50 | http://ftp.nux.ipb.pt/pub/dists/opensuse/ |
| 74 | mirrors.uol.com.br | br | SA | 50 | http://ftp.opensuse.org/pub/opensuse/ |
| 79 | ftp.halifax.rwth-aachen.de | de | EU | 100 | http://ftp.halifax.rwth-aachen.de/opensuse/ |
+----------+----------------------------+---------+--------+-------+---------------------------------------------------+
for mirror in mirrors:
/* use the "score" to give each mirror a weighted randomized rank */
mirror->rank = (rand()>>16) * ((RAND_MAX>>16) / mirror->score)
if memcache daemon knows combination of this client ip and this mirror id:
/* client got this mirror before */
chosen = mirror
if country of client is same as mirror:
put country into country pool
else if continent of client is same as mirror:
put country into region pool
else
put country into world pool
if country pool is not empty:
chosen = find lowest ranked mirror(country pool)
else if continent pool is not empty:
chosen = find lowest ranked mirror(continent pool)
else if world pool is not empty:
chosen = find lowest ranked mirror(world pool)
else:
do not redirect, send the file ourselves
store combination client ip <-> mirror id in memcache daemon
if metalink_requested:
send metalink
else:
do the redirect
一旦选择了镜像,重定向器将返回 HTTP 状态码 302 (Found),并在 Location 标头中包含重定向 URL,这将使请求者转到那里。如果对于给定的文件没有已知的镜像,服务器将直接传送该文件。
有一些重要的例外情况。对于某些文件,很难确保它们在所有镜像上都是最新的,因为它们经常更改。因此,服务器不会为这些文件重定向。
镜像“粘性”
过去,我们使用“镜像粘性”
一旦客户端被重定向到某个镜像,在下一次请求时,它将被重定向到同一个镜像,而不是随机选择另一个镜像。
这种配置被证明与仅仅随机分配镜像没有好处,因此不再激活 (我想从 2008 年初开始)。
内置 Metalink 支持
重定向器生成 metalink 文件 (参见 http://metalinker.org)。启用的客户端可以在出现问题时自动故障转移,甚至可以并行下载。每当将“.metalink”附加到要下载的文件的 URL 时,都会返回一个 metalink。
一个例子是 http://download.opensuse.org/distribution/11.1/iso/openSUSE-11.1-DVD-i586.iso.metalink
以下博客文章解释了如何充分利用它:http://lizards.opensuse.org/2008/12/16/best-way-to-download-opensuse/
重定向器支持将验证哈希和 PGP 签名注入到 metalink 中,并且对于大多数较大的文件 (如 iso 镜像) 都会包含它们。
有关使用 metalink 下载 openSUSE 的更多信息可以在 此处 找到。
其他说明
集中式分发文件的方式有一个有趣的含义 - 它允许我们收集有关请求文件的有趣数据,否则我们无法做到。因此,我们还有一个 apache 模块。它收集有关单个 Build Service 包下载的统计信息。原则上,该模块将路径和文件名拆分,并分别记录组件或增加 SQL 数据库中的计数器。来源可以在这里找到:https://forgesvn1.novell.com/svn/opensuse/trunk/tools/download-stats/mod_stats/。
开发者信息和联系方式
- 有关邮件列表、IRC 等,请参见 http://mirrorbrain.org/communication
致谢
本产品包含由 MaxMind 创建的 GeoLite 数据,可从 http://maxmind.com/ 获取