Nginx的安装与配置

来源:互联网 发布:欧洲7日游要多少钱知乎 编辑:程序博客网 时间:2024/05/16 23:49

Nginx的简单介绍

作为普通的Web服务器
作为反向代理服务器

Nginx的安装

Windows有专门的编译版本,直接下载运行即可。一般用来测试配置,不推荐在产品环境下使用Windows运行Nginx。

Linux下的安装,一般使用yum或apt等包管理器来安装预编译好的安装包,若有特殊的调整要求,也可以使用编译源码的方式来安装。

CentOS下的yum安装

在官网有介绍(http://nginx.org/en/linux_packages.html),搬过来。

首先在系统中添加nginx的源,建立文件 /etc/yum.repos.d/nginx.repo,内容如下

1
2
3
4
5
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

注意里面的baseurl,如果是CentOS 6.x,需要把里面的7改为6。

repo文件添加好后,使用 yum install nginx 就可以安装了。

CentOS下的源码安装

Nginx内置了不少模块,同时有很多模块并没有内置(例如可以处理图片的ngx_http_image_filter_module模块),如果使用这些模块的话,需要重新编译Nginx。

不过这里不展开这个话题了…… (眨眼)

Nginx的配置

配置文件的一般结构

Nginx是由很多模块组成的,每个模块提供多个配置指令。这些模块就是被配置文件中与之对应的配置指令控制的。

配置指令有单行的简单配置指令,也有块级配置指令的。简单指令形如 “worker_processes 2;”,“proxy_pass http://backend;” ,都是由 指令名+空格+参数+分号组成的。块级指令与简单指令类似,不过不是以分号结尾,而是由一系列花括号包含起来的指令结尾。

可以包含其他指令的块级指令会形成一个context,常见的context有http, server, location等。顶级(没有任何花括号包含的)context叫main context。有些配置指令是限制必须在某个context里的。例如location必须在server里,server必须在http里。

举个例子:

1
2
3
4
5
6
7
8
9
user www www;
http {
  server {
    listen 127.0.0.1:8000;
    location / {
      root/data/www;
    }
  }
}

以上就完成了一个简单的静态文件服务器的配置,里面的每个指令都可以从官方文档(http://nginx.org/en/docs/)里查询。

server、location的配置

server的配置

server是nginx配置里最重要的指令之一。一个nginx服务可以承载多个网站(也可以理解为虚拟主机等等),每个虚拟主机需要在nginx里配置一个server。

server里最关键的配置指令是listen和server_name。其中listen指定了这个server所监听的IP和端口。多个server也可以共用同一个IP和端口,这时候就需要使用server_name(域名)来区分。

当一个请求到达nginx后,首先根据IP和端口确定由哪些server处理(不存在没配置端口但是进入到nginx的请求),然后根据server_name来最终确定处理的server。

server_name可以配置多个域名,用空格隔开。

location的配置

location的语法:

location [ = | ~ | ~* | ^~ ] uri { ... }

在开始之前需要注意:

  1. location匹配的是从域名之后的“/”到“?”之前的部分,不含query string;
  2. location是解码过的, 也就是说 "%xx"这类的编码已经被处理为正常的字符了,.././,//这类也被处理了;

location有两种匹配规则:prefix匹配规则和正则匹配规则。

prefix匹配规则可以匹配以设置的uri开头的请求。prefix规则uri前可以不带任何修饰符,也可以用以下两个修饰符:“=”表示严格(完整)匹配;“^~”表示优先于正则匹配。

正则匹配必须以~或~*开头,~表示区分大小写的正则表达式,~*不区分大小写。

location的详细匹配规则如下:

  1. 先查找prefix匹配,标记出最长的匹配(如果有"="规则匹配,或者最长匹配的是"^~"规则,则立即完成,不再执行后面的步骤)
  2. 根据配置顺序,找到第一个可匹配的正则location
  3. 如果没有正则匹配,就使用第1步中标记的最长匹配

注意,如果非正则匹配的location以"/"结尾,同时使用了proxy_pass、fastcgi_pass等指令的话,nginx会做特殊的301跳转处理。

常见的配置任务

静态资源服务器

理解了nginx的基本配置,熟悉了server和location的配置规则后,用nginx做静态资源服务器就非常轻松了。需要额外使用的指令就只有root、alias、index和try_files了。

root指令用来指定静态资源的根目录做为网站的根目录,nginx实际访问的文件就是根目录+uri部分,例如下面的配置(在server context):

 

1
2
3
4
5
6
7
8
9
root/www/html;
location/img/ {
  root /data/images/;
}
location ~ \.gif$ {
  root /data/gif_gen/;
}
location / {
}

如果请求 /img/20170911/default.jpg, 实际访问的文件是/data/images/img/20170911/default.jpg(注意img也跟进来了); 如果请求/img/20170911/default.gif, 实际访问的是/data/gif_gen/img/20170911/default.gif (注意跟/img/的冲突,如果不理解可以看看上面location的部分)。如果请求/images/default.jpg,则会访问 /www/html/images/default.jpg。也就是说,实际访问的文件路径是root部分+请求部分。

如果不想多上面那一层/img/,可以考虑使用alias: 修改方法 location /img/ {alias /data/images/;}  这时候请求 /img/20170911/default.jpg 就会访问/data/images/20170911/default.jpg。即:alias会移除location中配置的uri部分。

另外root或alias是可以使用正则表达式提取uri的某一部分的,例如:

1
2
3
location ~ ^/users/(.+)/head\.(jpe?g|gif|png)$ {
  alias/data/upload/head/$1.$2;
}

反向代理/负载均衡

反向代理的大概意思是,由代理(这里就是Nginx)接管后端服务器与用户的通信,用户不需要知道代理服务器的存在,以为与他通信的就是后端服务器(正向代理是用户必须知道的,例如各种X墙工具)。

因为灵活的配置和强大的处理能力,Nginx是目前使用最广泛的反向代理服务器之一。

Nginx的反向代理功能是通过http_proxy_module模块来提供的。这个模块最常用的指令就是proxy_pass。

proxy_pass的功能与前面讲到的root和alias有点类似,不过是把请求发送到指定的服务器(也可以是自己)、所用的协议(http、https),以及调整后的路径(可选项,如果路径有变化的话)

proxy_pass URL;  #例如  proxy_pass http://localhost:8000/uri/;

另外还有 proxy_set_header、proxy_redirect 这两个配置偶尔也需要调整。

一般需要注意的问题:

路径转换的问题

常常正个应用系统提供给用户的url和后端服务器实际要用的url并不完全一致,这就需要在反向代理服务器上做一定的配置。使用location和proxy_pass的参数配合可以解决大部分的问题。

1. 如果指定了uri(域名端口后面的部分,包括第1个斜杠),那么Nginx就会把原始的URL移除location指定的部分后追加到这个uri后面

1
2
3
location/name/{
  proxy_pass http://127.0.0.1/remote/;
}

上面这个,如果请求 /name/Einstein.html就会被转发到http://127.0.0.1/remote/Einstein.html这个地址。

注意这个写法仅适用于prefix匹配规则的location,正则表达式的location只能用下面2、3的写法,否则会报配置错误,nginx无法启动。

2. 如果uri部分省略,则不进行任何url替换,uri会原样发送到后端的服务器。

上例中,如果 proxy_pass http://127.0.0.1; (注意没有结尾的斜杠),如果请求 /name/Einstein.html就会被转发到http://127.0.0.1/name/Einstein.html这个地址。正则表达式的location能用这种写法。

3. 如果想用正则又必须改变后端地址的话,可以在uri中使用变量来解决(当然,其他变量也是可以在uri中使用的)

1
2
3
4
5
6
7
8
9
location ~ ^/name/(\w+)\.html$ {
  proxy_pass http://127.0.0.1/users?name=$1;
}
 
#使用rewrite的等效写法
location/name/{
  rewrite/name/(\w+)\.html$/users?name=$1break;
  proxy_pass http://127.0.0.1;
}

上面这两个配置,都可以将客户端发来的“/name/Einstein.html”这个伪静态请求转为“/users?name=Einstein”后发送给后端。

Host name的问题

大部分情况下,后端服务器是不需要绑定host name(是指域名或server name,下同)的。但在某些情况下,后端应用需要根据接收到的host name来提供不同的服务,这时候,就涉及到了host name转换的问题。

默认proxy_pass会直接将后面参数中提供的host name发送给后端服务器,但也可以使用“proxy_set_header Host xxxx;”来调整。

proxy_set_header Host www.example.com; #将发送给后端服务器的请求中的Host项置为www.example.com。

说到这里,就不得不提一下nginx如何处理服务端的301、302跳转的问题。

在host name不传递给后端的情况下,后端的应用并不知道自己的实际域名的,而是使用一个内部IP,于是在301、302(也就是resquest.redirect)的时候,会跳转到一个内部的url,如果不做处理就会导致地址错乱。万幸的是,nginx默认配置已经处理了大多数情况。

在ngx_http_proxy_module中有个proxy_redirect指令,默认配置是default,他的意思就是使用请求(如果没有,就用server指令里的server_name)中的域名,来替换proxy_pass中的域名。

举个例子,还是上面的配置,如果用户使用http://www.example.com/name/Einstein.html访问到了上述的location,proxy_pass将使用http://127.0.0.1/users?name=Einstein来访问后端。假设后端返回302 redirect到http://127.0.0.1/account/login,nginx会将转向地址中的127.0.0.1自动替换为www.example.com,以保证还能正常访问。但如果后端302 redirect到了http://10.254.23.67:8090/sso/login,那nginx的默认配置就替换不了了,原样返回给客户端会出错。

这种情况下,需要在上面的location中,或者干脆在server context中,加“proxy_redirect 10.254.23.67:8090 sso.example.com;”来完成跳转的替换。

其他问题

其实除了host name,还有很多其他的问题,例如客户端的实际IP(因为后端服务器拿到的是代理服务器的IP)、实际使用的协议是HTTP还是HTTPS(因为代理服务器可能使用不同的协议连接后端)。

这些问题,一般是通过在代理服务器上设置各种header来搞定的,实际上,我一般习惯添加一个proxy.conf把常用的header指令写进来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
proxy_connect_timeout 300s;
proxy_send_timeout 900;
proxy_read_timeout 900;
proxy_buffer_size 32k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
#proxy_redirect off;
proxy_hide_header Vary;
proxy_set_header Accept-Encoding '';
proxy_set_header Referer \$http_referer;
proxy_set_header Cookie \$http_cookie;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr; #这个是直接连接代理服务器的IP
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; #这个是一个IP列表,因为可能是多级代理
proxy_set_header X-Forwarded-Proto $scheme; #这个是传递原始的协议

在后端的应用程序,就需要根据这些特殊的Header的值来判断原始的协议和IP地址了。

缓存

这里说的缓存,其实是在做反向代理的时候有用的(直接做web服务器的时候也没必要啊)。有一篇文章《NGINX缓存使用官方指南》已经写的很透彻了,建议大家参考。

原创粉丝点击