Apache 作为反向代理 更多资源

Apache 作为反向代理 更多资源

我正在将一个大图像目录从 HTTP 服务器移动到另一个服务器,但无法更改任何配置。

我希望我的用户甚至不会想到有移动正在进行。所以我想在两台服务器前面添加一个配置为反向代理的 Apache httpd 服务器。

当在目标中找不到资源时,此反向代理应尝试在原始服务器中获取它。

有没有办法使用 mod_rewrite 或某些标准 Apache httpd 模块来做到这一点?

资源不在前端服务器上,而是在两台后端服务器上。

答案1

要检查 RewriteCond 中的远程资源,您可以使用以下命令:

'-U'(是现有 URL,通过子请求)检查 TestString 是否是有效 URL,可通过该路径的所有服务器当前配置的访问控制进行访问。这使用内部子请求进行检查,因此请谨慎使用 - 它可能会影响服务器的性能!

我个人从未使用过它。但它的工作原理类似于测试文件是否存在等。

然后您可以拥有一个代理请求的 RewriteRule([P] 选项)。

答案2

我已经使用 Apache httpd 2.2 实现了反向代理,但仅使用 apache 指令无法实现。因此我不得不使用一个简单的 PHP 脚本来检查远程 URL 是否存在。

当有新请求到来时,它会检查服务器 A 上是否存在当前路径,如果成功找到,它会在同一台服务器上反向代理该请求。另一方面,如果在服务器 A 上找不到请求的路径,它会在服务器 B 上实施重写规则反向代理。

我使用了RewriteMapwithMapType prg:和 PHP 脚本。Apache 指令如下:

# Please pay attention to RewriteLock
# this directive must be defined in server config context
RewriteLock /tmp/if_url_exists.lock

RewriteEngine On

ProxyPreserveHost Off
ProxyRequests Off

RewriteMap  url_exists "prg:/usr/bin/php /opt/local/scripts/url_exists.php"
RewriteCond ${url_exists:http://serverA%{REQUEST_URI}}   >0
RewriteRule .            http://serverA%{REQUEST_URI} [P,L]

RewriteRule .            http://serverB%{REQUEST_URI} [P,L]

接下来是有趣而棘手的部分。这是url_exists.php由 Apache 执行的脚本。它等待标准输入流并写入标准输出。1如果找到并可读资源,则此脚本返回,否则返回0。实际上它非常简单,因为它仅使用 HEAD 方法实现 HTTP 请求。

<?php

function check_if_url_exists($line) {
    $curl_inst = curl_init($line);

    curl_setopt( $curl_inst, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt( $curl_inst, CURLOPT_LOW_SPEED_LIMIT, 1);
    curl_setopt( $curl_inst, CURLOPT_LOW_SPEED_TIME, 180);
    curl_setopt( $curl_inst, CURLOPT_HEADER, true);
    curl_setopt( $curl_inst, CURLOPT_FAILONERROR, true);

    // Exclude the body from the output and request method is set to HEAD.
    curl_setopt( $curl_inst, CURLOPT_NOBODY, true);
    curl_setopt( $curl_inst, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt( $curl_inst, CURLOPT_RETURNTRANSFER, true);

    $raw = curl_exec($curl_inst);

    curl_close($curl_inst);

    return ($raw != false) ? true : false;

}

set_time_limit(0);
$keyboard = fopen("php://stdin","r");

while (true) {
    $line = trim(fgets($keyboard));
    if (!empty($line)) {
        $str = (check_if_url_exists($line)) ? "1" : "0";
        error_log($line. " ".$str);
        echo $str."\n";
    } else {
        error_log('empty line!');
    }
}

相关内容