大家好,我是 17 。

总结了一些 nginx 的常用装备。几经删改,从进口文件开端,讲解 Content-Type、 location 匹配规矩,proxy_pass 署理,页面缓存,url 美化,移动pc 适配,自定义log等。 还包括一些常用指令详解。

为了讲述便利,环境为 CentOS 7, nginx 版别 1.21。

装备文件进口

/etc/nginx/nginx.conf

这是进口文件,这个文件里有这样一句:

include /etc/nginx/conf.d/*.conf;

各个网站的装备文件是放在 conf.d 目录下的。这里面的一切 .conf 文件都会被读取。咱们添加一个 test.conf。 yourname 便是你的用户名。在 /home/yourname/web/test/ 下面添加一个 index.html文件 ,文件。文件内容为 hello。

server{
  listen 3000;
  server_name _;
  location / {
    root /home/yourname/web/test/;
  }
}

发动 nginx,假如现已发动,reload 装备文件。

# 发动
sudo nginx 
# 假如现已发动,从头加载装备
sudo nginx -s reload

用 ip 或 localhost:3000 用浏览器拜访网站,显现 hello。测验办法也能够用 curl localhost:3000,这样或许会更便利些。

文件类型

关于咱们恳求的内容,浏览器的处理方法是不相同的。浏览器怎样判别内容,是依据呼应头 Content-Type。 在进口装备文件 nginx.conf 中有这样两句:

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

mine.types 是 Content-type 和文件后缀名的映射表。比方 xx.css 文件的 Content-typetext/css 。 default_type 是默许的 type。比方当拜访 /a 的时分,假如 a 文件存在,nginx会回来 a 文件,呼应头 Content-type:application/octet-stream。 浏览器对application/octet-stream的处理方法是下载,而不是展现。

假如咱们的恳求地址是这样的 /a.html,/b.css, nginx 都能够主动处理。但有的时分,或许恳求的地址是这样的 /a,这时就需求咱们手动指定 type 类型。指定 type 类型很简略,有两种办法。

location /css {
  add_header Content-type text/css;
}
location /css {
  default_type text/css;
}

自定义log

翻开 /etc/nginx/nginx.conf 找到 log_format

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

关于开发来说能够去掉 ua,ua 很长,去掉能够便利检查。尤其关于初学者,主张加上 $request_filename ,这个变量代表的是拜访的实践文件途径,关于理解各种指令的作用,查找过错十分有帮助。

在进口的装备文件中用 Log_foramt定义了一个 main。咱们能够定义一个 dev,按你所需求选用需求的内容即可。 运用的时分,直接用 dev这个名字就行。

 log_format  dev  '[$time_local] "$request" $request_filename'
                   '$status $body_bytes_sent "$http_referer" '
 access_log /home/duhongwei/log/access.log dev;

location 匹配规矩

@ 匹配规矩在后边的 try_files 中有举例

location 按如下优先级匹配

  1. = 绝对匹配,一个字符也不能差
  2. ^~ 前缀匹配
  3. ~(差异巨细写), ~*(不差异巨细写) 正则匹配
  4. 一般前缀匹配

2,4的匹配是匹配最长优先。 3 的匹配是按次序,写在前面的优先。

完全匹配

location = /abc {
   return 900;
}
curl -I localhost:3000/abc
HTTP/1.1 900

location = abc 尽管只少了 / ,但这样是匹配不到的,一个字符也不能差。完全匹配优先级最高,不管写在前面仍是后边。

^~ 前缀匹配

# 正则匹配
location ~ abc {
   return 900;
}
# 前缀匹配
location ^~  /a {
   return 901;
}
curl -I localhost:3000/abc
HTTP/1.1 901

^~ 匹配的优先级高于正则匹配。

初看到 ^~ 的人会误以为是正则匹配。这个要留意下,这个是前缀匹配,便是从前向后一个字符一个字符匹配。

# 一般前缀匹配
/abc/ {
}
# 前缀匹配
^~ /abc/ {
}

这两种写法的匹配方法是相同,^~ 的优先级更高。

正则匹配

# 一般前缀匹配
location  /abcd {
   return 901;
}
# 正则匹配
location ~ /ab {
   return 902;
}
curl -I localhost:3000/abcd
HTTP/1.1 902

正则匹配的优先级高于一般前缀匹配。

# 正则匹配
location ~ /ab {
   return 901;
}
# 正则匹配
location ~ /abc {
   return 902;
}
curl -I localhost:3000/abc
HTTP/1.1 901

正则匹配是按次序来的,前面的匹配成功,后边的就不再匹配了。

从功用上来说,尽量不要用正则,正则匹配功用最低。

前缀匹配最长优先

location  /abcd {
   return 901;
}
location  /abc {
   return 902;
}
location ^~ /def {
   return 903;
}
location ^~ /defg {
   return 904;
}
curl -I localhost:3000/abcd
HTTP/1.1 901
curl -I localhost:3000/defg
HTTP/1.1 904

pass_proxy 署理

在前端署理主要是为了跨域。尽管前端跨域有多种办法,各有利弊,但用署理来跨域对开发是最友爱的。用署理能够不必修正产品代码切换线上线下,十分安全。pass_proxy 默许会把 cookie 也一起转发。 常用的装备十分简略。

不带斜杠

前端 /api/user

后端 /api/user

 location ^~ /api/ {
     proxy_pass http://127.0.0.1:3001;
 }

不带斜杠把 path 直接拼接在 url后边;

带斜杠

前端 /api/user

后端 /user

 location ^~ /api/ {
     proxy_pass http://127.0.0.1:3001/;
 }

带斜杠会先去掉匹配到的 path, 再拼接。

正则匹配的时分不能带斜杠

~ 差异巨细写正则匹配 ,~* 不差异巨细写正则匹配 。location 用正则匹配的时分,proxy_pass 后边不能以 / 结尾,由于 nginx 不能处理这种状况。

 location ~ /api/ {
     proxy_pass http://127.0.0.1:3001/;
 }

本例中,恳求 localhost:3000/ 会导致 nginx 报错。

斜杠后边加途径

前端 /api/user

后端 /web/api/user

 location ^~ /api/ {
     proxy_pass http://127.0.0.1:3001/web$request_uri;
 }

署理之前rewrite

location /search/ {
    rewrite    /search/([^/]+) /s?wd=$1 break;
    proxy_pass http://127.0.0.1:3001;
}

服务端获取实在ip

反向署理: 简略来说 proxy_pass 把恳求转发到其它服务地址的时分,便是反向署理。

假如是客户端与服务器直接连接,nginx 变量 $remote_addr 就能够拿到实在ip。$remote_addr 是不能伪造的。可是假如客户端是经过反向署理连接的服务器,服务器能拿到的只有署理服务器的 IP。为了能拿到客户端实在 IP,署理服务器在转发的时分需求加上一个 http 扩展头部 X-Forwarded-For。

一切署理的 ip 依次列出来,从远及近。

X-Forwarded-For: IP0, IP1, IP2

X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开端是由 Squid 这个缓存署理软件引进,用来表示 HTTP 恳求端实在 IP。如今它现已成为事实上的标准,被各大 HTTP 代 理、负载均衡等转发服务广泛运用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000/;
}

$proxy_add_x_forwarded_for变量包括客户端恳求头中的”X-Forwarded-For”,与$remote_addr用逗号分开,假如没有”X-Forwarded-For” 恳求头,则$proxy_add_x_forwarded_for等于$remote_addr$remote_addr变量的值是客户端的IP。

或许你会担心,ip会不会被伪造。即便客户端伪造了 ip,nginx 也会用实在的 ip 进行重置。所以 $remote_addr 是可信的。

try_files

try_filesfile...uri;
try_filesfile... =code;

举两个比方,对应这两种语法。

location /images/ {
    try_files $uri /images/default.gif;
}
location = /images/default.gif {
    expires 30d;
}
location / {
    try_files $uri $uri/index.html $uri.html =404;
}

=404 的 等号 是有必要的

try_file 后边有必要有一个file, 一个 url 或 code,file 能够有多个。

简略来说,try_file 按次序检查 file,假如是文件夹,请在 file后加 / ,假如 file 都不存在,依据最终一个参数做跳转。

借这个机会说一下 @ 在location 中的用法。 @ 相当于命名了一个变量。

location / {
    try_files /system/maintenance.html
              $uri $uri/index.html $uri.html
              @mongrel;
}
location @mongrel {
    proxy_pass http://mongrel;
}

try_files 的一个运用场景便是单面运用.

location / {
 try_files $uri $uri/ /index.html
}

假如恳求的是 /a, 首要会查找 a 文件 是否存在,然后找 a 目录是否存在,假如都不存在,转到 /index.html。 再次射中 location / ,再次履行 try_files,这回找到index.html 回来。

留意:假如 index.html 不存在,会报 500,所以用 try_files的时分,要防止屡次射中,最终的跳转最好转到别处。

location / {
 try_files $uri $uri/ /index.html 
}
location /index.html{
}

这样修正后,只经历一次尝试,假如找不到,会报 404,不是 500,功用也会进步。

error_page

error_pagecode... [=[response]]uri;

error_page 会发生内部跳转。

举例

error_page 404             /404.html;
error_page 500 502 503 504 /50x.html;
error_page 404 =200 /empty.gif;
error_page 404 =301 http://example.com/notfound.html;
location / {
    error_page 404 = @fallback;
}
location @fallback {
    proxy_pass http://backend;
}

假如找不到直接跳 404 页面没什么问题,可是假如是跳到主页,或是显现一张图片,

假如这样写

error_page 404 /index.html

当拜访不存在的页面的时分,会跳到主页,可是状况码会显现 404。假如要显现 200,能够指定

error_page 404 =200 /index.html

页面缓存

http header 相关的缓存有两种

  1. 强制缓存
  2. 洽谈缓存

呼应头部有两个值代表是否要强制缓存。Cache-Control 和 expires。至于为什么有两个头,expires 是前史遗留。

假如 不需求强制缓存 nginx能够这样装备

expires -1;

nginx 发回的头部

Cache-Control:no-cache
Expires:Thu, 18 Aug 2022 06:55:23 GMT 

Expires 的时间比当时早一秒。

也能够不装备 nginx。 默许是封闭强制缓存的 expires off

expires offexpires -1 都能够封闭强制缓存,但呼应头不相同,expires off 不会发送 Cache-Control 和 expires。

假如需求强制缓存 这样装备

expires 1d;

1d 表示强制缓存一天。可是浏览器是否选用强制缓存还取决于浏览器的具体完结。

比方你在浏览器中直接恳求一个图片地址(网络上随便找张图片就成),检查呼应头,一般都会带有 expires 和 Cache-control ,下次恳求应该会射中强制缓存,可是,下次恳求的时分走的是洽谈缓存,状况码是 304。为什么会这样呢?由于 chrome 在直接恳求图片的时分 在恳求头中加上了 cache-control:max-age=0,标明本次恳求不会选用强制缓存。

当强制刷新的时分,恳求头 cache-control:no-cache,呼应码 200。浏览器疏忽强制缓存,服务端疏忽洽谈缓存,从头回来内容。

cache-control:no-cache
pragma:no-cache

不光是图片,chrome 直接拜访 html 也不会射中强制缓存。关于浏览器的这个策略也是合理的。当拜访一个网站的时分,咱们榜首个恳求的是网站主页 index.html。假如主页被强制缓存了 10天,那么或许 10 天内用户看到的都是旧内容。

cache-control:no-store 这个字段便是告知浏览器不进行缓存。这个最彻底,不管是强制缓存仍是洽谈缓存都会封闭。nginx 中这样装备

add_header Cache-Control no-sotre;

cache-control:no-cache 封闭强制缓存,但仍是会走洽谈缓存。

封闭了强制缓存就会走洽谈缓存,Last-Modified、etag, nginx 都会默许加上。

给图片等静态资源加强缓存

location ~* \.(?:css(\.map)?|js(\.map)?|gif|svg|jfif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
    # 静态资源设置一年强缓存 
    expires 365d; 
    access_log off; 
}

一般会给静态资源设置一个较长的缓存。假如资源发生变化,会修正文件名。一般用 md5 值做为文件名。

root 与 alias

root 与 alias 决议到哪里在去拜访实践的文件,差异在于 root 会拼接匹配到途径,alias 会替换匹配到的途径。咱们看个实践的比方。

location / {
 root /home/user/web; 
}
恳求 /a.jpg,实践恳求的是 /home/user/web/a.jpg,找到图片
把 root 换成 alias
location / {
 alias /home/user/web; 
}
恳求 /a.jpg,实践恳求的是 /home/user/weba.jpg,找到不图片了。由于 / 被替换掉了。处理的办法是把 / 补上
location / {
 alias /home/user/web/; 
}
也不是说 alias 有必要以 / 结尾,假如location中 不是以 /结尾,alias 后边就不加 /
在下面的比方中 ,恳求 /a/b.jpg ,实践查找 /home/user/web/b.jpg。 仅仅把 /a 去掉而已。
location /a {
 alias /home/user/web; 
}

比较于 alias,主张优先用 root。root 能够用在 http,server,location,if in location,alias 只能用在 location。root 对结尾的斜杠并不介意,兼容性更好。 alias 能够作为 root 的弥补来运用。

url 美化

咱们在开发的时分用的 url 是这样的

/users?id=1

让别人拜访的时分或许是这样的

/users/1

所以咱们需求把 /users/1 转为 /users?id=1 ,这时就需求 rewrite 出场了。

location /users/{
    rewrite ^/users/(.*)$ /nodejs/id=$1? last;
}
location /nodejs/{
   proxy_pass http://127.0.0.1:3000;
}

当恳求/users/1 的时分,射中 location /users/ ,履行rewrite 指令, last flag 指示中止后边的rewrite 指令并做内部跳转,匹配到 location /nodejs/ ,经过 proxy_pass 指令,转到 /nodejs/ 。

你或许对 last 表示疑问,都现已是最终了,怎样又跳到 /nodejs/ 了呢? 接下来,我具体讲解一下 nginx 的 rewrite 模块。为什么说一个模块呢?由于与 rewrite 相关的是一组指令。

nginx http rewrite module 详解

简略来说, ngx_http_rewrite_modulemodule 用正则匹配恳求,改写恳求,然后做跳转。能够是内部跳转,也能够是外部跳转。

学习这个模块的时分,把 rewrite_log 翻开,能够在 error log 里检查跳转信息

 rewrite_log on;
 error_log /home/log/test-error.log notice;

留意 notice 是有必要的

次序履行和循环跳转

  1. 直接写在 server level 的 指令,次序履行。
  2. 写在 location 中的指定次序履行。能够跳到其它 location ,最多不超越 10次。
server{
    rewrite ^/users/(.*)$ /show?user=$1 ;
    rewrite ^/teachers/(.*)$ /show?teacher=$1 ;
}

恳求 /users/1 ,先履行榜首条 rewrite ^/users/(.*)$ /show?user=$1 再履行第二条 rewrite ^/teachers/(.*)$ /show?teacher=$1 ; 尽管榜首条匹配到了,仍是会履行第二条。这便是次序履行的意思。

location /{
    rewrite ^/teachers/(.*)$ /show/$1;
    rewrite ^/users/(.*) /show/$1;
}
location /show/{
    rewrite ^/show/(.*)$ /users/$1 ;
}

恳求 /users/1,射中榜首个location 。次序履行榜首个 rewrite,没射中,即便射中也会持续履行第二 rewrite ,射中。履行 rewirte 指令跳转到第二个location /show/,履行 rewirte 又回跳回 / ,这样循环10次,报 500 过错,检查 error 日志能够看到阐明。

rewrite or internal redirection cycle while processing "/show/1"

这个进程演示了 location 中 rewrite 的履行逻辑。次序履行,循环跳转。

rewrite module 中还有 5 个指令 break,if,return,rewrite, andset。

return

return 能够直接回来,打断后边的 rewrite module 指令的履行。

location / {
 return 409;
 rewrite ^/teachers/(.*)$ /show/$1;
}

履行 return 后,后边的指令就没有机会履行了。

returncode[text];
returncodeURL;
returnURL;
location /admin/{
    return 403 '没有拜访权限';
}
location / {
    return 302 $scheme://www.baidu.com$request_uri;
}
location /abc/{
    return 404;
}

set,break 比较简略,和其它语言差不多。下面着重讲下 rewirte 指令的 flag。

rewrite 指令的 flag

rewriteregexreplacement[flag]

flag有四种

  • last 中止履行后边的 ngx_http_rewrite_module 指令,并发起新的 location 匹配。
  • break 中止履行后边的 ngx_http_rewrite_module 指令,然后没有后续了,不再发起 location 匹配。
  • redirect 履行 302跳转,后边的指令不再履行。
  • permanent 履行 301跳转,后边的指令不再履行。

last、break 中止履行的是 ngx_http_rewrite_module 指令,其它指令不受影响,仍是会履行的。

regex 匹配的是途径部分

location / {
   rewrite ^/teacher/(.*)$ /show1/$1 last;
   rewrite ^/teacher/(.*) /show2/$1;
}
location /show1{
 return 900;
}
location /show2{
 return 901;
}
curl http://localhost:3000/teacher/1
HTTP/1.1 900
由于 last 会终止后边的  ngx_http_rewrite_module 指令,所以 第二句 rewrite ^/teacher/(.*) /show2/$1 不会履行。榜首句履行完后,跳到 /show1,回来 900
假如把 last 换成  break
HTTP/1.1 404
由于 break 不再履行跳转,直接查找 show1/1 找不到,报 404.
把 last 换成 redirect.
HTTP/1.1 302 
浏览器会恳求两次。
把 last 换成 permanent.
HTTP/1.1 301 
浏览器会恳求两次。

假如 replacement 是 http最初,是能够直接跳转的

location / {
  rewrite ^/teacher/ http://
}
curl http://localhost:3000/teacher/1
HTTP/1.1 302 
Location: http://
相当于 redirect 指令的作用。

if 句子

if 句子不复杂,可是十分有用,能够这样说,用 if 能够完结许多指令,可是用内置指令更简洁,仍是要优先用指令。

if ($param) 假如 $param 为空字符串或 0 为假,其它状况为真。

留意 if 后边有必要要有空格,不然报错。

set $param '0';
set $param 0;
set $param '';
这三种写法 $param 都为假,其它状况都为真

用 = ,!=判别相等。

 if ($request_method = POST){
      return 403;
 }

留意 是一个 = 不是两个=, 等号左右有必要要有空格,不然报错

用正则表达式判别

~ 差异巨细写
if ($http_user_agent ~ mobile)
~* 不差异巨细写
if ($http_referer ~* juejin\.cn)
!~ 和 !~* 是对应的两个否定写法,不再举例了。

用 flag

-f !-f  文件是否存在
if (-f $request_filename)
if (!-f $request_filename)
-d !-d 目录是否存在
-e !-e 文件或目录是否存在
-x !-e 是否可履行

移动 pc 适配

咱们期望在拜访 一个网址的时分,假如是在 pc端翻开的时分,显现pc的页面,假如是在移动端翻开的,显现移动端的页面。网址只有一个。

server{
 {  
    set $isMobile true;
    if ($http_user_agent ~* '(Android|webOS|IEMobile|iPhone|iPod|BlackBerry)') { 
        set $isMobile true;
    }
    set $root  /home/duhongwei/web/pc;
    if ($isMobile = true) {
      set $root  /home/duhongwei/web/h5;
    }
    root $root;
}

这个设置需求放在 server 下面,关于一切 location 有效。在 location 里假如有需求还能够修正 root,所以 set 一个 $isMobile 的变量,便利后边运用。

ipad 尽管是移动设置,但从尺度上来看更挨近 pc,所以页面在 ipad 翻开,一般会显现 pc 的页面

装备https服务

尽管在开发的时分用 http 就行,但有的时分,有必要要 https 才行。所以装备开发环境或许也得装备 https 服务。咱们的目的是为了让服务跑起来,仍是很简略的。

  1. 申请证书
  2. 证书包括一个crt文件一个key文件,crt为证书,key为密钥
  3. 装备nginx

假如你正在做一个项目,这个项目的域名证书应该是提早就申请好的。用这个证书就行。本地配 host ,配项目的线上域名,就能够测验了。

server {
    # 1 
    listen       443 ssl;    
    server_name  www.xxx.com; 
    # 2
    ssl_certificate      证书的绝对途径     
    # 3
    ssl_certificate_key  密钥的绝对途径
}   

装备 https服务,只需求三步

  1. 监听 443 端口
  2. 设置证书的绝对途径
  3. 设置密钥的绝对途径

只这三步就完结,很简略吧。

要启用 http2 也很简略, 只需求在 listen 后边加 http2 即可。

listen 443 ssl http2;

恳求地址结尾加斜杠与不加斜杠

恳求 /b 与 /b/ 有什么差异吗? nginx 解析起来差异就大了。

不加斜杠,假如存在 b 文件,回来文件 b 假如不存在文件b,但有文件夹 b, 301 到 b/,在浏览器中看到的现象是发了两个恳求.假如 b下面没有index.html,回来 403,假如有,回来内容。

nginx 常用配置详解

假如没有 index.html,为什么是回来 403而不是 404呢?

这是由于 nginx 假如找不到 index.html,会尝试浏览目录,默许是不允许的。

autoindex off;

假如既没有文件夹 b 也没有文件 b 回来 404。

为什么拜访 b/ 会去查找 b/index.html?这是由于 index 指令默许是这样的

index index.html

nginx 静静做了这么多,便是为了让咱们用起来便利。假如从功用方面来考虑,写完整地址最好,别让nginx去猜了。用户怎样输入网址咱们管不了,可是咱们在写跳转地址的时分,最好是写完整地址。

恳求头信息对应的 nginx 变量

nginx 中的有些变量有是规则的,按规则能够便利记忆。

nginx 常用配置详解

对每一个恳求标头,都对应一个变量

巨细写不灵敏,以 http_ 最初, – 改为 _ 。

  • $http_accept
  • $http_cache_control

cookie 的中的变量

比方 cookie 中 包括 name=jack,用 $cookie_name 能够拿到 jack 这个值。

  • cookie_name

arg 中的变量

比方有这样的 get 恳求 index.html?name=jack ,用 $arg_name 能够拿到 jack 这个值。

  • arg_name

nginx 接纳客户端提交

当咱们提交一个表单的时分,会生成一个恳求的 header,body。在header中 Content-Length:123 标明 content 字节巨细。nginx 接纳到 header,先检查 header 巨细,假如 header 巨细超越 client_header_buffer_size 的默许值 1K,并超越 large_client_header_buffers 的默许值 8K nginx 会报错。

检查 Content-Length ,假如超越 client_body_buffer_size 默许值 8K(除了 x86 的 64位体系是 16K),内存缓冲区无法接纳,会存到 client_body_temp_path 指定的目录。可是接纳的body总巨细不是无限的,不能超越 client_max_body_size 的默许值 1M。

关于大多数恳求来讲,都是 get 恳求,咱们能够直接躺平,默许值即可。 get 恳求没有 body,超限的状况或许是 cookie 过多,url 过长。一般来说,超出的或许性不大。

关于 post 恳求,当上传文件的时分,或许会超限。nginx 默许只能接纳 1M 的内容,能够添加这个默许值。

locatoin /upfile/ {
    client_max_body_size:200M;
}

假如网络状况不好,或许刚发一个字节,就断了,假如在默许 60 秒内没有再次发送,nginx 会中止链接。这样做是为了节省服务器资源。能够经过 修正 client_body_timeout 和client_header_timeout 改变默许值。

server{
  client_body_timeout 10s;
  client_header_timeout 10s;
}

60秒有点太保存了,能够减小这个值。

nginx gzip 紧缩

gzip紧缩的常识仍是十分多的,不过仅仅启用gzip ,翻开功用,仍是很简略的。

server{
gzip on;
gzip_min_length 0;
}

gzip 指令默许是 off,设置为 on 翻开 gzip。假如只设置 gzip on gzip 可有不会生效,gzip 默许只对大于20字节的内容做处理。咱们在测验的时分页面内容都很少,很简单少于 20 字节 gzip_min_length,设为 0 代表一切巨细都紧缩。

启用紧缩后,在恳求 /index.html 呼应 200 的时分,检查 header,发现有两个添加,而且 Content-Length 不见了。

nginx 常用配置详解

Content-Encoding:gzip 内容的格局为 gzip,告知浏览器,需求 gzip 解压再展现。

Transfer-Encoding:chunked 数据是经过一系列块来传输的,省略 Content-Length ,为了得到内容巨细,需求把每个 chunk 的巨细加起来。

为什么翻开 gzip 后 content-length 信息没有了呢? 这是由于 nginx 的紧缩是异步的,发送头的时分,nginx 或许正在紧缩,不知道紧缩完结的文件巨细。

指定需求 gzip 的文件

咱们拜访 /index.css ,发现并没有紧缩,这是由于 gzip ,默许只紧缩 text/html 类型的文件。

添加 text/css 类型后,css 文件 也能够紧缩了。

gzip_types text/html,text/css;

紧缩等级。

gzip 有9个紧缩等级,越高,紧缩作用越好,可是对 cpu 的耗费越多。默许紧缩等级为 1 。咱们能够设置一个适宜的等级,比方 2;

gzip_comp_level 2;

gzip_static

前面讲的nginx 处理 gzip 的方法是服务器担任紧缩,这样会耗费掉许多 cpu 资源。咱们能够先把文件紧缩成 gzip,nginx 直接拿 gzip 过的文件就行了。预处理的优点不光是节省了 cpu 紧缩时间,还能够 让 nginx 能够运用 sendfile 体系调用来传输文件,功用得到进步。

为了能直接拿 gzip 过的文件,需求 gzip_static 模块。 新版别的 nginx 现已默许安装了这个模块,假如是老版的 nginx 这个模块需求安装一下。

gzip_static always; 

假如加上这句,nginx 不报错,阐明 gzip_static 模块现已安装了。

gzip_static 能够有三个值。

  • off 默许值。 不启用 gzip_static。gzip功用仍是能够用的。
  • on 启用。 当客户端支撑 gzip的时分,发送紧缩文件,不支撑的时分发送原文件。
  • always 总是。 不管客户端是否支撑,都优先发送紧缩文件。假如没有紧缩文件,再发送原文件。

实操的时分,用 always 比较好。现在不支撑 gzip 的浏览器太少了,这样能够免掉 nginx 判别的步骤,对功用有所进步。为了便利 nginx 查找(文件越多,查找越慢),只保存 gzip 文件,原文件全部删去。

负载均衡

upstream servers {
    server 192.168.1.1;
    server 192.168.1.2;
}
server {
    listen       80;
    server_name  _;
    location / {
        proxy_pass   http://servers;
        proxy_set_header        Host    $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

nginx 常用的负载均衡 是 upstream 来完结的。默许选用轮询的方法依次拜访各个服务器。能够给每个服务器加权重,调整拜访的频率,权重越高,被拜访的越频频。

upstream servers {
    server 192.168.1.1 weight=1;
    server 192.168.1.2 weight=2;
}

依据 ip 也能够分配恳求。这样能确保同一个用户能够由同一个服务器来服务,能够处理登录 session 的问题。可是依据 ip 分配或许导致某些服务器恳求过多,又不能再做调整,所以处理登录 session 的问题,能够用一致的 redis 服务来处理。

upstream servers {
    ip_hash;
    server 192.168.1.1 ;
    server 192.168.1.2 ;
}

依据 url 分配恳求。比方这样的场景, 资源(图片等静态文件)服务器从源服务器拉取资源后,下次恳求会再次落到这个资源服务器,就能够直接回来成果 ,不必再从源服务器恳求资源了。

upstream servers {
    hash $request_uri;
    server 192.168.1.1 ;
    server 192.168.1.2 ;
}

最终再介绍一下最小连接数方案。在这种场景下,least_conn 算法很简略,首要遍历后端集群,比较每个后端的conns/weight(连接数除权重),选取该值最小的后端。 假如有多个后端的 conns/weight 值同为最小,那么对它们选用加权轮询算法。

upstream servers {
    least_conn;
    server 192.168.1.1 weight=2;
    server 192.168.1.2 weight=1 ;
}

参阅

  • expires
  • try_files
  • rewrite