反向代理


好的,我来为您提供一个完整的示例代码。这个代码集成了之前讨论的优化方案,包括 Nginx 配置和 PHP 后端代码。

首先是 Nginx 配置文件 nginx.conf:

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Gzip 压缩
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # 缓存配置
    location ~* \.(jpg|jpeg|png|gif)$ {
        root /var/www/html/cache;
        try_files $uri @fetch_remote;
        expires 30d;
        access_log off;
        add_header Cache-Control "public";
    }

    location @fetch_remote {
        rewrite ^(.*)$ /index.php?resource=$1 last;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP 配置
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }
}

接下来是 PHP 代码 index.php:

<?php
// index.php

// 设置 Curl 选项
$curl_options = array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 60,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_FORBID_REUSE   => false, // 保持连接不断开
);

// 获取请求的资源路径
$resource = isset($_GET['resource']) ? $_GET['resource'] : null;

if ($resource !== null) {
    $cache_file = 'cache/' . md5($resource) . '.' . pathinfo($resource, PATHINFO_EXTENSION);

    // 检查缓存文件是否存在
    if (file_exists($cache_file)) {
        // 返回缓存的图片资源
        $content_type = pathinfo($cache_file, PATHINFO_EXTENSION);
        header("Content-Type: image/$content_type");
        readfile($cache_file);
        exit;
    } else {
        // 从远程服务器获取资源并缓存
        $ch = curl_init();
        curl_setopt_array($ch, $curl_options);
        curl_setopt($ch, CURLOPT_URL, 'http://remote_server' . $resource);
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if ($response !== false && $http_code === 200) {
            // 将资源缓存到本地
            $dir = dirname($cache_file);
            if (!is_dir($dir)) {
                mkdir($dir, 0755, true);
            }
            file_put_contents($cache_file, $response);

            // 设置响应头并输出内容
            $content_type = pathinfo($cache_file, PATHINFO_EXTENSION);
            header("Content-Type: image/$content_type");
            echo $response;
            exit;
        } else {
            http_response_code($http_code);
            echo 'Error fetching resource';
            exit;
        }
    }
}

// 处理其他类型的请求
$request_uri = $_SERVER['REQUEST_URI'];
$ch = curl_init();
curl_setopt_array($ch, $curl_options);
curl_setopt($ch, CURLOPT_URL, 'http://remote_server' . $request_uri);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($response !== false && $http_code === 200) {
    // 设置响应头并输出内容
    foreach (curl_getinfo($ch) as $key => $value) {
        if (is_string($key) && strpos($key, 'content_') === 0) {
            header($key . ': ' . $value);
        }
    }
    echo $response;
} else {
    http_response_code($http_code);
    echo 'Error fetching resource';
}

curl_close($ch);

这个例子包含了以下优化措施:

  1. Nginx 配置中启用了 Gzip 压缩,可以减小响应内容的大小。
  2. 图片资源的缓存策略已经设置,包括缓存目录、缓存文件名生成、缓存时间等。
  3. PHP 代码中增加了对缓存的检查和更新逻辑,提高了响应速度。
  4. 对于非图片资源的请求,仍然会转发到远程服务器并返回响应内容。

您可以根据实际需求进行进一步的调整和优化。如果有任何其他问题,欢迎继续提出。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注