Nginx 反向代理,负载均衡

2020/07/02

1、安装nginx

linux 下yum 方式安装

[root@helloworld ~]# vim /etc/yum.repos.d/nginx.repo
# 添加以下内容保存
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
# 安装nginx
[root@helloworld ~]# yum install nginx
# 使用yum安装nginx比较简单,并且相关的 SysV 脚本都已经写好,直接用即可
# 配置文件在 /etc/nginx目录下
cd /etc/nginx/
# 日志文件在 /var/log/nginx 目录下
cd /var/log/nginx/
# pid 位于 /var/run 目录下
cd /var/run
# 使用 SysV 脚本控制 nginx
service nginx stop
service nginx start
service nginx restart
service nginx reload
service nginx status

linux下 直接下载解压安装

# 0、nginx 依赖环境准备,已安装忽略
# 安装nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境
yum install -y gcc gcc-c++ 
# PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库
yum install -y pcre pcre-devel 
# zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。
yum install -y zlib zlib-devel
# openssl是一个强大的安全套接字层密码库,囊括主要的密码算法(md5和sha1等)、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。
yum install -y openssl openssl-devel

# 下载,也可以手动下载后上传到服务器上
wget http://nginx.org/download/nginx-1.18.0.tar.gz
# 1、解压
[root@helloworld opt]# tar -zxvf nginx-1.18.0.tar.gz
# 2、配置
[root@helloworld opt] cd nginx-1.18.0
[root@helloworld nginx-1.18.0]# ./configure 
...
  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

# 如果报错了是不是上面的gcc环境是不是没安装好
# 3、安装
[root@helloworld nginx-1.18.0]# make && make install
# 查找安装路径
[root@helloworld ~] whereis nginx
# 4、安装成功,到nginx的目录 /usr/local/nginx
cd /usr/local/nginx
[root@helloworld nginx]# ls
conf  html  logs  sbin
# 启动
[root@helloworld nginx]# ./sbin/nginx
# 查看nginx是否启动
ps -ef | grep nginx
# 设置全局的nginx命令
cp /usr/local/nginx/sbin/nginx /bin/
# 5、设置开机启动
cd /lib/systemd/system/
vi nginx.service
# 编辑nginx.service内容如下
[Unit]
Description=nginx service
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

# 开启nginx开机启动
systemctl enable nginx
# 关闭nginx开机启动
systemctl disable nginx
# 查看所有服务,enable表示开机启动,disabled表示不开机启动
systemctl list-unit-files
# 查看所有开机启动的服务,centos7已不使用chkconfig --list查看
systemctl list-unit-files |grep enable
# 查看nginx是否已开机启动
systemctl list-unit-files |grep nginx

# 配置了全局nginx命令后,不需要cd 切换到ngin的安装目录了
cd /usr/local/nginx/sbin/
./nginx  启动
./nginx -s stop  停止
./nginx -s quit  安全退出
./nginx -s reload  重新加载配置文件
ps aux|grep nginx  查看nginx进程

mac 通过brew的方式安装

# 查看brew版本
brew --version
# 查看nginx是否存在
brew search nginx
# 安装nginx
brew install nginx
# 卸载
brew uninstall nginx
# 查看nginx的安装目录
xjwdeMacBook:~ xjw$ which nginx
/usr/local/bin/nginx
# 配置目录
/usr/local/etc/nginx
# 启动nginx
xjwdeMacBook:~ xjw$ nginx

windows下安装

1、下载nginx

http://nginx.org/en/download.html 下载稳定版本。以nginx/Windows-1.16.1为例,直接下载 nginx-1.16.1.zip。下载后解压,解压后如下:

2、启动nginx

有很多种方法启动nginx

(1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过

(2)打开cmd命令窗口,切换到nginx解压目录下,输入命令 nginx.exe ,回车即可

3、检查nginx是否启动成功

直接在浏览器地址栏输入网址 http://localhost:80 回车,出现以下页面说明启动成功!

4、配置监听

nginx的配置文件是conf目录下的nginx.conf,默认配置的nginx监听的端口为80,如果80端口被占用可以修改为未被占用的端口即可(要放开可被访问)。

当我们修改了nginx的配置文件nginx.conf 时,不需要关闭nginx后重新启动nginx,只需要执行命令 nginx -s reload 即可让改动生效,如果nginx没有被平滑关闭,需要手动关闭重启

5、关闭nginx

如果使用cmd命令窗口启动nginx, 关闭cmd窗口是不能结束nginx进程的,可使用两种方法关闭nginx

(1)输入nginx命令 nginx -s stop(快速停止nginx) 或 nginx -s quit(完整有序的停止nginx)

(2)使用taskkill taskkill /f /t /im nginx.exe

taskkill是用来终止进程的,
/f是强制终止 .
/t终止指定的进程和任何由此启动的子进程。
/im示指定的进程名称 .

2、nginx 常用命令

# -h 打印命令行参数的帮助信息
[root@VM_0_3_centos nginx]# nginx -h

# -c 启动时指定配置文件的位置,如果不指定则使用默认的配置文件 /etc/nginx/nginx.conf
[root@VM_0_3_centos nginx]# nginx -c file

# -t 检查nginx的配置文件是否有语法错误,通常在修改配置文件后先检查配置文件,然后在重新加载配置文件
[root@VM_0_3_centos nginx]# nginx -t

# -s signal : 给nginx主进程发信号: stop, quit, reopen, reload
# 快速关闭nginx
[root@VM_0_3_centos nginx]# nginx -s stop

# 平滑关闭nginx,如果没关闭请用kill
[root@VM_0_3_centos nginx]# nginx -s quit

# reload 重新加载配置文件,使用新配置文件开启一个新的工作进程(worker progress),然后平滑的关闭原来的工作进程。
[root@VM_0_3_centos nginx]# nginx -s reload

# reopen 重新打开日志文件,如果你发现你的nginx日志文件不再记录日志了,可以使用该指令重新打开日志文件。
[root@VM_0_3_centos nginx]# nginx -s reopen

# -q 在 nginx 进行配置文件测试时只打印错误信息。和 -t 参数配合使用。
[root@VM_0_3_centos nginx]# nginx -qt

# 修改配置文件后,优雅重启nginx
# 获取ningx进程id
ps -ef|grep nginx
kill -HUP 进程id

nginx默认只开启一个工作进程,可以通过配置workprocess 启动多个工作进程

3、nginx的配置

location

# 格式
location [=|~|~*|^~] /uri/ {  }
# 例子:区分大小写匹配,以.txt结尾的请求将访问/usr/local/nginx/html/ 路径下的txt文件
location ~ ^.+\.txt$ {
  root /usr/local/nginx/html/;
}
模式 含义
location = /uri = 表示精确匹配,只有完全匹配上才能生效
location ^~ /uri ^~ 开头对URL路径进行前缀匹配,并且在正则之前。
location ~ pattern 开头表示区分大小写的正则匹配
location ~* pattern 开头表示不区分大小写的正则匹配
location /uri 不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location / 通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default

匹配顺序:

  • 首先精确匹配 =
  • 其次前缀匹配 ^~
  • 其次是按文件中顺序的正则匹配
  • 然后匹配不带任何修饰的前缀匹配。
  • 最后是交给 / 通用匹配

注意:

  • 当有匹配成功时候,停止匹配,按当前匹配规则处理请求

  • 前缀匹配,如果有包含关系时,按最大匹配原则进行匹配

    比如在前缀匹配:`location /dir01``location /dir01/dir02`,如有请求 `http://localhost/dir01/dir02/file` 将最终匹配到 `location /dir01/dir02`*
    

alias与root的区别

  • alias,不拼接url中的路径

    location ^~ /sta/ {  
       alias /usr/local/nginx/html/static/;  
    }
    请求:http://test.com/sta/sta1.html
    实际访问:/usr/local/nginx/html/static/sta1.html 文件
    
  • root,拼接url中的路径

    location ^~ /sta/ {  
      root /usr/local/nginx/html/static/;  
    }
    请求:http://test.com/sta/sta1.html
    实际访问:/usr/local/nginx/html/static/sta/sta1.html 文件
    

    你会发现一样的配置,一样的请求,root多了一层sta。

permanent & redirect:

  • rewrite … permanent 永久性重定向,请求日志中的状态码为301
  • rewrite … redirect 临时重定向,请求日志中的状态码为302
location ^~ /sta/ {  
  rewrite /static/1  ;  
}

从实现功能的角度上去看,permanent 和 redirect 是一样的,不存在性能上的问题,但是对seo会有影响,permanent不会影响网站排名,redirect会使用网站排名降低

其它指令

  • return : 返回http状态码 和 可选的第二个参数可以是重定向的URL

    location /permanently/moved/url {
        return 301 http://www.example.com/moved/here;
    }
    
  • rewrite: 重写URI请求 rewrite,通过使用rewrite指令在请求处理期间多次修改请求URI

    第一个参数(必需)是请求URI必须匹配的正则表达式;

    第二个参数(必需)是用于替换匹配URI的URI。

    第三个参数(可选)可以停止进一步重写指令的处理或发送重定向(代码301或302)的标志

    location /users/ {
        rewrite ^/users/(.*)$ /show?user=$1 break;
    }
    
  • error_page

    使用error_page指令,您可以配置NGINX返回自定义页面以及错误代码,替换响应中的其他错误代码,或将浏览器重定向到其他URI。在以下示例中,error_page指令指定要返回404页面错误代码的页面(/404.html)。

    error_page 404 /404.html;
    
  • 日志

    需要开启压缩 gzip on; 否则不生成日志文件,打开log_format、access_log注释

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
      
    access_log  /usr/local/etc/nginx/logs/host.access.log  main;
      
    gzip  on;
    
  • deny 禁止访问某个目录

    location ~* \.(txt|doc)${
        root $doc_root;
        deny all;
    }
    
  • 内置变量

    nginx的配置文件中可以使用的内置变量以美元符$开始,也有人叫全局变量。其中,部分预定义的变量的值是可以改变的。

    $args :#这个变量等于请求行中的参数,同$query_string
    $content_length :请求头中的Content-length字段。
    $content_type :请求头中的Content-Type字段。
    $document_root :当前请求在root指令中指定的值。
    $host :请求主机头字段,否则为服务器名称。
    $http_user_agent :客户端agent信息
    $http_cookie :客户端cookie信息
    $limit_rate :这个变量可以限制连接速率。
    $request_method :客户端请求的动作,通常为GET或POST。
    $remote_addr :客户端的IP地址。
    $remote_port :客户端的端口。
    $remote_user :已经经过Auth Basic Module验证的用户名。
    $request_filename :当前请求的文件路径,由root或alias指令与URI请求生成。
    $scheme :HTTP方法(如http,https)。
    $server_protocol :请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
    $server_addr :服务器地址,在完成一次系统调用后可以确定这个值。
    $server_name :服务器名称。
    $server_port :请求到达服务器的端口号。
    $request_uri :包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
    $uri :不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
    $document_uri :与$uri相同
    

4种负载均衡策略

主要是对proxy_pass和upstream的配置。

http {
    upstream upstream_name{
        server 192.168.0.28:8001;  # 具体的服务
        server 192.168.0.28:8002;
    }

    server {
        listen       8080;
        server_name  localhost;

        location / {
            proxy_pass http://upstream_name;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

负载策略(有4种)

1、轮询(默认)

它是upstream的默认策略,每个请求会按时间顺序逐一分配到不同的后端服务器。

参数:

  • max_fails: 最大失败次数,如果超过,那么该服务器会被认为是停机了
  • fail_timeout:连接失败超时,与max_fails结合使用
  • fail_time:服务器会被认为停机的时间长度,默认为10s。
  • backup:标记该服务器为备用服务器。当主服务器的服务停止时,请求会被发送到它这里。备胎
  • down:标记服务器永久停机了,请求不会访问这里。

在轮询中,如果服务器down掉了,会自动剔除该服务器。

此策略适合服务器配置相当,无状态且短平快的服务使用。

2、权重

# weight参数用于制定轮询的几率,weight默认值为1;weight的数值和被访问的几率成正比。
upstream foo {
    server localhost:8001 weight=2;
    server localhost:8002;
    server localhost:8003 backup;
    server localhost:8004 max_fails=3 fail_timeout=20s;
}

注意:
- 权重越高分配到需要处理的请求越多。
- 此策略可以与least_conn和ip_hash结合使用。
- 此策略比较适合服务器的硬件配置差别比较大的情况

3、ip_hash

# 按照客户端IP地址的分配方式,可以确保相同客户端的请求一直发送到相同的服务器。这样每个访客都固定访问一个后端服务器。
upstream foo {
    ip_hash;
    server localhost:8001 weight=2;
    server localhost:8002;
    server localhost:8003;
    server localhost:8004 max_fails=3 fail_timeout=20s;
}

注意:
- 在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
- ip_hash不能与backup同时使用。
- 此策略适合有状态服务,比如session。
- 当有服务器需要剔除,必须手动down掉。

4、least_conn 最小连接

# 把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果
upstream foo {
    least_conn;
    server localhost:8001 weight=2;
    server localhost:8002;
    server localhost:8003 backup;
    server localhost:8004 max_fails=3 fail_timeout=20s;
}
注意:
- 此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

在实际运用中,需要根据不同的场景选择不同的策略,大多是多种策略结合使用以达到实际需求的性能。

配置参考

nginx.conf

user  nginx;
worker_processes  1;	# 开启的nginx的进程数,并发高的时候可以增加

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024; # 连接限制
}

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

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65; # 超时
    include /etc/nginx/conf.d/*.conf; # 包含的配置文件
}

/etc/nginx/conf.d/default.conf

upstream nacos {
    server 127.0.0.1:8848;
    server 127.0.0.1:8858;
    server 127.0.0.1:8868;
}

server {
    listen       80;
    server_name  139.199.13.139;

    location /nacos {
         proxy_pass http://nacos;
    }
        
    # 前缀匹配
    location ^~ /blog {
        alias  /usr/share/nginx/html/;
        index  index.html index.htm;
    }
    # 精确匹配,代理跳转
    location = /deploy {
       proxy_pass http://127.0.0.1:3001/deploy;
    }
    # 通用匹配
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    # 错误页面
    error_page  404              /404.html;
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

开启gzip解压缩

修改nginx.conf文件

upstream backend {
    server 192.168.10.21:8000;
}
 
server {
    listen       80;
 
    gzip on; #开启gzip
    gzip_disable "MSIE [1-6]."; #ie1-6浏览器时禁用gzip
    gzip_vary on; #是否在响应头添加Content-Encoding
    gzip_proxied any; #Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服务器必须要返回包含"Via"的 header头。
    gzip_comp_level 6; #压缩级别【1-9】,越大压缩率越高,同时消耗cpu资源也越多,建议设置在6左右。 
    gzip_http_version 1.0; #识别http的协议版本
    gzip_min_length 256; #低于256kb的资源不压缩
    #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片
    gzip_types application/atom+xml application/geo+json application/javascript application/x-javascript application/json application/ld+json application/manifest+json application/rdf+xml application/rss+xml application/xhtml+xml application/xml font/eot font/otf font/ttf image/svg+xml text/css text/javascript text/plain text/xml; 
}

如何gzip配置不生效,gzip_http_version由1.1改为1.0就好了,默认是1.1,

验证生效

Chrome浏览器F12控制台,查看响应头Response-Header的Content-Encoding:gzip证明已开启gzip:

查看压缩的前后效果

可以看到,网页压缩前是331K,压缩后是86.9K

使用了gzip响应返回数据后,如果是浏览器它根据Content-Encoding:gzip 进行数据解压,如果是客户端或APP端接受数据,要注意进行数据解压,否则显示的是压缩数据,是乱码的

从图中可以看到,对于返回的数据,以gzip格式的进行返回,而客户端进行解析的时候,是使用普通的流进行解析,所以会出现问题。

前端gzip压缩的数据不经过nginx,那么后端接受数据需要解压>

前后端请求数据gzip压缩方案

  1. 前端Vue项目,package.json下添加pako依赖

    "dependencies": {
        "pako": "^1.0.11"
     }
    

    采用axios发送请求,所以在需要请求的接口下进行请求参数的处理

    export function save(id, data) {
      return axios({
        url: `/save/${id}`,
        method: "post",
        headers: {'Content-Encoding': 'gzip'},
        data: data,
        transformRequest: [function (data, headers) {
          // 将数据压缩
          const gzip = pako.gzip(encodeURIComponent(JSON.stringify(data)), {to: "string"});
          const base64 = btoa(gzip);
          return base64;
        }],
      });
    }
    

    在请求头内添加'Content-Encoding': 'gzip',同时在请求转换器transformRequest内实现数据压缩,首先使用pako将数据进行gzip压缩,然后转为base64提交到后台保存

  2. 前端获取数据解压

    浏览器会根据响应头的Content-Encoding:gzip 进行数据解压,对应前端来说是无感的,但请求头没有加这个参数,前端需要自己手动解压

    export function get(id) {
      return axios({
        url: `/get/${id}`,
        method: "get",
        transformResponse: [function (res) {
          res = JSON.parse(res);
          if (res.code === 200) {
            let strData = atob(res.data)
            let charData = strData.split('').map(function (x) { return x.charCodeAt(0); })
            let binData = new Uint8Array(charData)
            let data = pako.inflate(binData)
       
            strData = ''
            let chunk = 8 * 1024;
            let i;
            for (i = 0; i < data.length / chunk; i++) {
              strData += String.fromCharCode.apply(null, data.slice(i * chunk, (i + 1) * chunk));
            }
            strData += String.fromCharCode.apply(null, data.slice(i * chunk));
       
            // 解压后数据
            res.data = decodeURIComponent(strData);
          }
          return res;
        }],
      });
    }
    
  3. 后端获取数据解压

    后端接口经过nginx,nginx开启了gzip解压缩,那么数据会被自动解压后给到后端,但如果需要手动解压可使用hutool工具,引入hutool工具maven依赖

    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.7.21</version>
    </dependency>
    

    解压代码示例:

    String base64 = this.getData(id);
    // base64解码
    byte[] gzip = Base64.decode(base64);
    // gzip解压
    String unGzip = ZipUtil.unGzip(gzip, "UTF-8");
    // uri解码
    String data = URLUtil.decode(unGzip, "UTF-8");
    

4、五大应用场景

http服务器

Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署,这个jekyll 博客就是静态的html,也是通过这种方式部署的。

1) 首先在文档根目录Docroot(/usr/local/var/www)下创建html目录, 然后在html中放一个test.html;

2) 配置nginx.conf中的server

user mengday staff;

http {
    server {
        listen       80;
        server_name  localhost;
        client_max_body_size 1024M;

        # 默认location
        location / {
            root   /usr/local/var/www/html;
            index  index.html index.htm;
        }
    }
}

3) 访问测试

  • http://localhost/ 指向/usr/local/var/www/index.html, index.html是安装nginx自带的html
  • http://localhost/test.html 指向/usr/local/var/www/html/test.html

注意:如果访问图片出现403 Forbidden错误,可能是因为nginx.conf 的第一行user配置不对,默认是#user nobody;是注释的,linux下改成user root; macos下改成user 用户名 所在组; 然后重新加载配置文件或者重启,再试一下就可以了, 用户名可以通过who am i 命令来查看。

配置说明:

server : 用于定义服务,http中可以有多个server块
listen : 指定服务器侦听请求的IP地址和端口,如果省略地址,服务器将侦听所有地址,如果省略端口,则使用标准端口
server_name : 服务名称,用于配置域名
location : 用于配置映射路径uri对应的配置,一个server中可以有多个location, location后面跟一个uri,可以是一个正则表达式, / 表		示匹配任意路径, 当客户端访问的路径满足这个uri时就会执行location块里面的代码
root : 根路径,当访问http://localhost/test.html,“/test.html”会匹配到”/”uri, 找到root为/usr/local/var/www/html,用			户访问的资源物理地址=root + uri = /usr/local/var/www/html + /test.html=/usr/local/var/www/html/test.html
index : 设置首页,当只访问server_name时后面不跟任何路径是不走root直接走index指令的;如果访问路径中没有指定具体的文件,则返回		index设置的资源,如果访问http://localhost/html/ 则默认返回index.html

location uri正则表达式

. :匹配除换行符以外的任意字符
? :重复0次或1次
+ :重复1次或更多次
* :重复0次或更多次
\d :匹配数字
^ :匹配字符串的开始
$ :匹配字符串的结束
{n} :重复n次
{n,} :重复n次或更多次
[c] :匹配单个字符c
[a-z] :匹配a-z小写字母的任意一个
(a|b|c) : 属线表示匹配任意一种情况,每种情况使用竖线分隔,一般使用小括号括括住,匹配符合a字符 或是b字符 或是c字符的字符串
\ 反斜杠:用于转义特殊字符

静态服务器

在公司中经常会遇到静态服务器,通常会提供一个上传的功能,其他应用如果需要静态资源就从该静态服务器中获取。

1)在/usr/local/var/www 下分别创建images和img目录,分别在每个目录下放一张test.jpg

2) 配置nginx.conf中的server

http {
    server {
        listen       80;
        server_name  localhost;


        set $doc_root /usr/local/var/www;

        # 默认location
        location / {
            root   /usr/local/var/www/html;
            index  index.html index.htm;
        }

        location ^~ /images/ {
            root $doc_root;
       }

       location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
           root $doc_root/img;
       }
    }
}

自定义变量使用set指令,语法 set 变量名值;引用使用变量名值;引用使用变量名; 这里自定义了doc_root变量。

静态服务器location的映射一般有两种方式:

  • 使用路径,如 /images/ 一般图片都会放在某个图片目录下,
  • 使用后缀,如 .jpg、.png 等后缀匹配模式

访问http://localhost/test.jpg 会映射到 $doc_root/img

访问http://localhost/images/test.jpg 当同一个路径满足多个location时,优先匹配优先级高的location,由于^~ 的优先级大于 ~, 所以会走/images/对应的location

常见的location路径映射路径有以下几种:

  • = 进行普通字符精确匹配。也就是完全匹配。
  • ^~ 前缀匹配。如果匹配成功,则不再匹配其他location。
  • ~ 表示执行一个正则匹配,区分大小写
  • ~* 表示执行一个正则匹配,不区分大小写
  • /xxx/ 常规字符串路径匹配
  • / 通用匹配,任何请求都会匹配到

优先级

  • 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项,停止搜索。
  • ^~类型表达式,不属于正则表达式。一旦匹配成功,则不再查找其他匹配项,停止搜索。
  • 正则表达式类型(~ ~*)的优先级次之。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个。
  • 常规字符串匹配类型。按前缀匹配。
  • / 通用匹配,如果没有匹配到,就匹配通用的

从高到低:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

示例:

location = / {
    # 精确匹配/,主机名后面不能带任何字符串 /
    [ configuration A ]
}
location / {
    # 匹配所有以 / 开头的请求。
    # 但是如果有更长的同类型的表达式,则选择更长的表达式。
    # 如果有正则表达式可以匹配,则优先匹配正则表达式。
    [ configuration B ]
}
location /documents/ {
    # 匹配所有以 /documents/ 开头的请求,匹配符合以后,还要继续往下搜索。
    # 但是如果有更长的同类型的表达式,则选择更长的表达式。
    # 如果有正则表达式可以匹配,则优先匹配正则表达式。
    [ configuration C ]
}
location ^~ /images/ {
    # 匹配所有以 /images/ 开头的表达式,如果匹配成功,则停止匹配查找,停止搜索。
    # 所以,即便有符合的正则表达式location,也不会被使用
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    # 匹配所有以 gif jpg jpeg结尾的请求。
    # 但是 以 /images/开头的请求,将使用 Configuration D,D具有更高的优先级
    [ configuration E ]
}

location /images/ {
    # 字符匹配到 /images/,还会继续往下搜索
    [ configuration F ]
}

location = /test.htm {
    root   /usr/local/var/www/htm;
    index  index.htm;
}

反向代理

反向代理应该是Nginx使用最多的功能了。

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

这时Nginx就是一个中间层了,请求和返回结果都会经由Nginx代理

反向代理通过proxy_pass指令来实现。

示例:启动一个Java Web项目,端口号为8081

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://localhost:8081;
        proxy_set_header Host $host:$server_port;
        # 设置用户ip地址
         proxy_set_header X-Forwarded-For $remote_addr;
         # 当请求服务器出错去寻找其他服务器
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; 
    }
}

当我们访问localhost的时候,就相当于访问 localhost:8081了

负载均衡

负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。

负载均衡通过upstream指令来实现

1、RR(round robin :轮询 默认)

同一个项目分别使用8081和8082端口启动项目,配置nginx.conf

upstream web_servers {  
   server localhost:8081;  
   server localhost:8082;  
}

server {
    listen       80;
    server_name  localhost;
    #access_log  logs/host.access.log  main;


    location / {
        proxy_pass http://web_servers;
        # 必须指定Header Host
        proxy_set_header Host $host:$server_port;
    }
 }

2、权重

指定轮询几率,weight和访问比率成正比, 也就是服务器接收请求的比例就是各自配置的weight的比例,用于后端服务器性能不均的情况,比如服务器性能差点就少接收点请求,服务器性能好点就多处理点请求。配置ngin.conf

upstream test {
    server localhost:8081 weight=1;
    server localhost:8082 weight=3;
    server localhost:8083 weight=4 backup;
}

示例是4次请求只有一次被分配到8081上,其他3次分配到8082上。backup是指热备,只有当8081和8082都宕机的情况下才走8083

3、ip hash

4、fair (第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个配置是为了更快的给用户响应

upstream backend {
    fair;
    server localhost:8080;
    server localhost:8081;
}

5、url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法

upstream backend {
    hash $request_uri;
    hash_method crc32;
    server localhost:8080;
    server localhost:8081;
}

动静分离

动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。

upstream web_servers {  
       server localhost:8081;  
       server localhost:8082;  
}

server {
    listen       80;
    server_name  localhost;

    set $doc_root /usr/local/var/www;

    location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
       root $doc_root/img;
    }

    location / {
        proxy_pass http://web_servers;
        # 必须指定Header Host
        proxy_set_header Host $host:$server_port;
    }

    error_page 500 502 503 504  /50x.html;  
    location = /50x.html {  
        root $doc_root;
    }

 }

5、KuangStudy

以下内容来自于狂神的分享。

单体应用的并发局限

一个jar包启动应用,适合项目初期,并发量小,用户量小,用户访问tomcat内应用,tomcat响应应用的内容给用户,如下图:

但是慢慢的,使用平台的用户越来越多了,并发量慢慢增大了,这时候一台服务器满足不了需求了。

这时候需要横向扩展,增加服务器,几个项目启动在不同的服务器上,用户要访问,就需要增加一个代理服务器了,通过代理服务器来帮我们转发和处理请求。多个项目应用需要解决用户session的共享问题,一种解决方案是将用户session放入redis,一种解决方案是使用nginx的iphash进行负载代理请求,还有其他解决方案,这里不细说。

我们希望这个代理服务器可以帮助我们接收用户的请求,然后将用户的请求按照规则帮我们转发到不同的服务器节点之上。这个过程用户是无感知的,用户并不知道是哪个服务器返回的结果,我们还希望他可以按照服务器的性能提供不同的权重选择。保证最佳体验!所以我们使用了Nginx。

什么是nginx

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。2011年6月1日,nginx 1.0.4发布。

其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。在全球活跃的网站中有12.18%的使用比率,大约为2220万个网站。

Nginx 是一个安装非常的简单、配置文件非常简洁(还能够支持perl语法)、Bug非常少的服务。Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够不间断服务的情况下进行软件版本的升级。

Nginx代码完全用C语言从头写成。官方数据测试表明能够支持高达 50,000 个并发连接数的响应。

nginx的作用

Http代理,反向代理:作为web服务器最常用的功能之一,尤其是反向代理。

  • 正向代理

    假如我们要访问国外的某些网站,但是国内访问不了,而某些服务器可以访问(称为代理服务器),我们将请求发送给代理服务器,让它去访问国外网站,然后把返回的数据传递给我们。

    正向代理的特点是客户端非常明确要访问的服务器地址,服务器只清楚来自哪个代理服务器,所以正向代理隐藏了客户端信息。

  • 反向代理

    多个客户端给服务器发送的请求,Nginx收到后按照一定的规则分发给后端的业务处理服务器。这时,请求的来源客户端是明确的,但是请求具体由哪台业务服务器处理并不明确,Nginx扮演的就是一个反向代理角色,主要用于服务分布式部署的场景,反向代理隐藏了业务服务器信息

Nginx提供的负载均衡策略有2种:内置策略和扩展策略。内置策略为轮询,加权轮询,Ip hash。扩展策略,就天马行空,只有你想不到的没有他做不到的。

  • 轮询

    具体配置内容参考上面

  • 加权轮询

  • iphash

    iphash对客户端请求的ip进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享的问题。

动静分离

动静分离,在我们的软件开发中,有些请求是需要后台处理的,有些请求是不需要经过后台处理的(如:css、html、jpg、js等等文件),这些不需要经过后台处理的文件称为静态文件。动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作。提高资源响应的速度。

目前,通过使用Nginx大大提高了我们网站的响应速度,优化了用户体验,让网站的健壮性更上一层楼!

nginx的安装

看上面第一个标题。

Post Directory