nginx 透過反向代理在多個平臺接入上游的客戶資訊

Luerdog發表於2019-06-02

感謝

  • 美滋滋的nginx
  • 百度上大佬寫的blog
  • laravel
  • silber/page-cache

需要實現的功能

  • 在多個不同的平臺(可能不在同一個伺服器)接入同一個上游的客戶資訊
  • 客戶相關頁面實現靜態頁面

前提

  • 我使用的是laravel框架
  • 所有的客戶資訊都儲存在上游網站http://push.push.do中,每個使用者擁有一個唯一的標識(tag),用於識別客戶,之後我所說的上游都是表示http://push.push.do
  • 現在 http://pingtai.do需要接入上游網站的客戶資訊,標識為client的客戶在此平臺的二級域名為http://client.pingtai.do
  • http://pingtai.do只使用了@和www兩個解析
  • push.push.do 解析地址 127.0.0.1
  • pingtai.do 解析地址 127.0.0.2

分析

  1. 一開始的時候,我想用linux提供的軟連線的方式來做,但是因為後來得知每個平臺可能在不同的伺服器上,veto~
  2. 然後開始嘗試使用nginx的反向代理來實現

反向代理操作步驟

  1. 域名解析

pingtai.do做泛域名解析,解析地址為127.0.0.2

  1. 基礎的反向代理

新增*.pingtai.do的nginx配置,這裡需要注意www.pingtai.dopingtai.do的配置檔案不要去動他

分兩個server模組是為了不影響平臺本身實現的功能

server {
    listen 80;
    server_name pingtai.do www.pingtai.do;
    ...
}
server {
    listen 80;
    server_name ~^(.*?).pingtai.do$; #這裡使用了正則的捕獲,我需要請求地址中的客戶唯一標識來識別客
    location / {
        proxy_pass http://push.push.do; #反向代理到擁有全部客戶資訊的上游地址
        proxy_redirect             off; 
        proxy_set_header           Host $proxy_host; 
        proxy_set_header           X-Real-IP $remote_addr; 
        proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header           RequestUrl $host; #將請求地址傳送給上游
        proxy_set_header           Domain $1; #將客戶唯一標識傳送給上游
        client_max_body_size       10m;
        client_body_buffer_size    128k;
        proxy_connect_timeout      300;
        proxy_send_timeout         300;
        proxy_read_timeout         300;
        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }
}
  1. http://push.push.do的程式的routes/web.php中實現對應的路由

    //其他的解析對應的路由
    ...
    //因為push.do上還有其他的解析,使用laravel提供的子域名路由功能
    Route::group(['domain' => 'push.push.do', 'namespace' => 'Client'], function () {
    //客戶二級域名首頁
    Route::get('/', 'IndexController@index')->name('client.index');
    //客戶模組資訊列表頁面
    Route::get('{chunk}','ChunkController@index')->name('client.chunk');
    //客戶單頁資訊頁面
    Route::get('{page}.html','PageController@index')->name('client.page');
    //客戶詳細資訊頁面
    ROute::get('{chunk}/{info}.html','InfoController@pc')->name('client.info');
    //還有手機站的路由 我沒寫
    });
  2. 到了這一步,基本上就實現了反向代理了("=>"標識請求對應的上游)

    • http://client.pingtai.do => http://push.push.do
    • http://client.pingtai.do/product => http://push.push.do/product
    • http://client.pingtai.do/about.html => http://push.push.do/about.html
    • http://client.pingtai.do/product/1.html => http://push.push.do/product/1.html
  3. 得到客戶唯一標識,識別客戶

    //很簡單 因為我再反向代理時設定了頭資訊,可以在push.push.do的程式中使用laravel提供的方法簡單的得到
    request()->server('HTTP_DOMAIN')#使用唯一標識去查詢資料庫得到使用者資訊
  4. 渲染頁面

    既然都得到了客戶的資訊,渲染頁面也就很簡單的 查詢相關資訊,然後渲染到blade模版就ok了

靜態頁面生成操作步驟

  1. 靜態頁面?

    為了加快速度,在第一次訪問客戶頁面的時候我希望將渲染的頁面儲存為靜態頁面,要是在用nginx的gzip壓縮一下,那就美滋滋了

我使用了silber/page-cache這個擴充來生成(做了一點修改)靜態頁面

  1. 安裝silber/page-cache

  2. 修改silber/page-cache預設生成靜態頁面的位置,加入客戶唯一標識做路徑

    //修改檔案vendor/silber/page-cache/src/Cache.php的getDefaultCachePath方法
    protected function getDefaultCachePath()
    {
    if ($this->container && $this->container->bound('path.public')) {
        return $this->container->make('path.public') . '/page-cache/' . request()->server('HTTP_DOMAIN');
    }
    }
    //這裡的request()->server('HTTP_DOMAMIN') 就是之前提到的客戶唯一標識
  3. 修改http://push.push.do的nginx配置,來實現靜態頁面的反向代理

    server {
    listen 80;
    server_name push.push.do;
    ...
    # 開啟了gzip 美滋滋    
    gzip on;
    #這是首頁的實現(有靜態頁面就用靜態頁面,沒有就正常訪問程式)
    location = / {
        try_files /page-cache/$http_domain/pc__index__pc.html /index.php?$query_string;#上游可以得到請求頭中的引數,$http_domain就是客戶唯一標識
    }
    #這是其他的靜態頁面(有靜態頁面就用靜態頁面,沒有就正常訪問程式)
    location / {
        try_files $uri $uri/ /page-cache/$http_domain/$uri.html /index.php?$query_string;#上游可以得到請求頭中的引數,$http_domain就是客戶唯一標識
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass php_upstream;      
        #fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }
    charset utf-8;
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
    location ~ /\.ht {
        deny all;
    }
    }
  4. 認證閱讀silber/page-cache的文件後,我們知道怎麼生成靜態頁面

    //只要新增一箇中介軟體就好了
    $this->middleware('page-cache');

End

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章