ngixn conditionally reverse proxy or serve directl

2019-06-02 06:26发布

问题:

The question is to ask for a possibility of making nginx conditionally redirect requests to other servers (by reverse proxy) or process the request by itself.

Here's the details.

I have a Raspberry Pi (RPi) running nginx + wordpress for 24*7 at home. I also have a laptop running Ubuntu for about 5 hours every night.

The wordpress on RPi is working great but it's slow (especially when it's working on php). So I would like to let the laptop help:

  • If laptop is on, RPi's nginx redirects all requests to Ubuntu by reverse proxy;
  • If laptop is off, RPi's nginx process the request as usual.

I wonder if it's possible to achieve this? If yes, how to configure RPi and Ubuntu?

回答1:

The basic solution is, make nginx as a reverse-proxy with fail_timout, when it receives a request, it dispatch to the upstreams where Ubuntu has higher priority, and if Ubuntu is offline, RPi will handle the request by itself.

This requires:

  1. mysql can be access by two clients with different ip, which is already supported;
  2. wordpress should be the same for RPi and Ubuntu, which can be done by nfs share;
  3. nginx should be correctly configured.

Below is the details of configuration.

Note, in my configureation:

  • RPi's IP is 192.168.1.100, Ubuntu's IP is 192.168.1.101;
  • The wordpress only allows https, all http requests are redirected to https;
  • Server listens at port 80 and 443, upstreams listen on port 8000;

Mysql

Set bind-address = 192.168.1.100 in /etc/mysql/my.cnf, and make sure skip-networking is not defined;

Grant permission to RPi and Ubuntu in mysql's console:

grant all on minewpdb.* to 'mineblog'@'192.168.1.100' identified by 'xxx';
grant all on minewpdb.* to 'mineblog'@'192.168.1.100' identified by 'xxx';

Wordpress

Set DB_HOST correctly:

define('DB_NAME', 'minewpdb');
define('DB_USER', 'mineblog');
define('DB_PASSWORD', 'xxx');
define('DB_HOST', '192.168.1.100');

NFS

On RPi, install nfs-kernel-server, and export by /etc/exports

/path/to/wordpress 192.168.1.101(rw,no_root_squash,insecure,sync,no_subtree_check)

To enable nfs server on RPi, rpcbind is also required:

sudo service rpcbind start
sudo update-rc.d rpcbind enable
sudo service nfs-kernel-server start

On Ubuntu, mount the nfs (it should also be set in /etc/fstab to make it mount automatically)

sudo mount -t nfs 192.168.1.100:/path/to/wordpress /path/to/wordpress

Nginx

On RPi, make a new config file /etc/nginx/sites-available/wordpress-load-balance, with below parameters:

upstream php {
  server unix:/var/run/php5-fpm.sock;
}

upstream mineservers {
  # upstreams, Ubuntu has much higher priority
  server 192.168.1.101:8000   weight=999 fail_timeout=5s max_fails=1;
  server 192.168.1.100:8000;
}

server {
  listen 80;
  server_name mine260309.me;
  rewrite     ^ https://$server_name$request_uri? permanent;
}

server {
  listen          443 ssl;
  server_name     mine260309.me;

  ssl_certificate     /path/to/cert/cert_file;
  ssl_certificate_key /path/to/cert/cert_key_file;
  ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;
  access_log         /path/to/wordpress/logs/proxy.log;
  error_log            /path/to/wordpress/logs/proxy_error.log;

location / {
  # reverse-proxy to upstreams
  proxy_pass  http://mineservers;

  ### force timeouts if one of backend is died ##
  proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

  ### Set headers ####
  proxy_set_header        Accept-Encoding   "";
  proxy_set_header        Host            $host;
  proxy_set_header        X-Real-IP       $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

  ### Most PHP, Python, Rails, Java App can use this header ###
  #proxy_set_header X-Forwarded-Proto https;##
  #This is better##
  proxy_set_header        X-Forwarded-Proto $scheme;
  add_header              Front-End-Https   on;

  ### By default we don't want to redirect it ####
  proxy_redirect     off;
  }
}

server {
  root /path/to/wordpress;
  listen          8000;
  server_name     mine260309.me;
  ... # normal wordpress configurations
}

On Ubuntu, it can use the same config file.

Now any request received by RPi's nginx server on port 443, it's dispatched to either Ubuntu or RPi's port 8000, where Ubuntu has much higher priority. If Ubuntu is offline, RPi itself can handle the request as well.

Any comments are welcome!