Nginx就是一个HTTP服务器,可以将服务器上面的静态文件比如html,图片,影音通过HTTP协议的方式传递给客户端,这种情况下,nginx的配置是:
server {
listen 8000; # 端口号 这个是nginx占用的端口号,后端就不可以和这个端口重复
location / {
root /usr/share/nginx/html; # 静态文件的路径
}
}
反向代理服务器
首先我们介绍一下正向代理:
代理服务器一般作用在客户端,比如在翻墙的时候,我们使用的就是正向代理,在客户端运行一个软件,将我们的http请求转发到其他不同的服务器。
同时Nginx还是一个反向代理服务器:
正常情况下,客户端是直接通过HTTP协议访问某网站的应用服务器,但是反向代理服务器的原理是:当网站管理员在中间加上一个Nginx,客户端会去请求Nginx,然后Nginx再请求服务器然后才把结果返回给客户端。但是这里客户端是不知道反向代理服务器的存在的。
这个时候Nginx作为反向代理服务器的配置是:
server {
listen 80;
location / {
proxy_pass http://192.168.0.112:8080; # 应用服务器HTTP地址
}
}
那么问题来了,为什么使用反向代理,而不是直接HTTP访问
- 负载均衡:
当网站访问量大的时候,一台服务器就不够用了,所以将相同的应用部署在多台服务器上,这样大量用户的请求会分配给多台这机器工作,那么万一一台服务器挂掉了,还有其他服务器,这就叫做负载均衡。
负载均衡的Nginx配置:
upstream myapp {
server 192.168.0.111:8080; # 应用服务器地址
server 192.168.0.112:8080; # 应用服务器地址
server 192.168.0.113:8080; # 应用服务器地址
server 192.168.0.114:8080; # 应用服务器地址
}
server {
listen 80;
location / {
proxy_pass http://myweb;
}
}
虚拟主机
有的网站访问量小,为了节省成本将多个网站部署到同一台服务器上,比如网站www.xxx.com和网站www.yyy.com部署在同一台服务器上,两个域名解析到同一个ip地址,但是两个域名却可以打开两个完全不同的网站,就像访问的是两个不同的服务器一样,这就是两个虚拟主机。
Nginx的虚拟主机配置:
server {
listen 80 default_server;
server_name _;
return 444; # 过滤其他域名的请求,返回444状态码
}
server {
listen 80;
server_name www.aaa.com; # www.aaa.com域名
location / {
proxy_pass http://localhost:8080; # 对应端口号8080
}
}
server {
listen 80;
server_name www.bbb.com; # www.bbb.com域名
location / {
proxy_pass http://localhost:8081; # 对应端口号8081
}
}
在服务器的8080和8081端口分别起了应用,客户端通过不同的域名访问可以反向代理到对应的服务器上,虚拟主机的原理是通过HTTP请求头中的host是否匹配server_name来匹配的
Nginx查看配置文件的方法:
- 首先我们可以使用
locate nginx.conf
命令来显示该文件存在的所有路径
如果这里显示了多个路径,我们不知道实际上调用的是哪一个,我们需要弄清楚: - 使用
ps aux|grep nginx
, 我们可以看到master显示的nginx实际路径
假如实际路径是/usr/sbin/nginx - 根据nginx实际路径我们可以使用
/usr/sbin/nginx -t
命令,查看配置文件路径
Nginx详解
首先安装nginx:
我们使用源码编译安装nginx,因为这样非常的灵活
然后我们准备把所有的东西都储存在/etc/nginx
目录下面,所以:
1. 创建本地环境:
mkdir /etc/nginx
cd /etc/nginx
2. 安装依赖库:
安装zlib:
wget http://www.zlib.net/zlib-1.2.11.tar.gz
tar zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure
make
make test
sudo make install
安装PCRE:
wget https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.gz
tar -zxf pcre-8.41.tar.gz
安装OpenSSL:
$ wget http://www.openssl.org/source/openssl-1.0.2m.tar.gz
$ tar -zxf openssl-1.0.2m.tar.gz
$ cd openssl-1.0.2m
$ ./config
$ sudo make
$ sudo make install
# 检查是否成功
$ openssl version
OpenSSL 1.1.0g 2 Nov 2017
安装Nginx:
$ wget http://nginx.org/download/nginx-1.13.6.tar.gz
$ tar zxf nginx-1.13.6.tar.gz
./configure \
--prefix=/etc/nginx/nginx-1.13.6 \
--sbin-path=/etc/nginx/nginx-1.13.6/nginx \
--conf-path=/etc/nginx/nginx-1.13.6/nginx.conf \
--pid-path=/etc/nginx/nginx-1.13.6/nginx.pid \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-pcre=../pcre-8.41 \
--with-zlib=../zlib-1.2.11
$ sudo make
$ sudo make install
这样就编译安装成功了,可以在nginx.conf文件里面看到默认监听的端口是80
# 检查配置文件是否有错
$ sudo /etc/nginx/nginx-1.13.6/nginx -t
nginx: the configuration file /etc/nginx/nginx-1.13.6/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx-1.13.6/nginx.conf test is successful
# 启动Nginx
$ sudo /etc/nginx/nginx-1.13.6/nginx
# 重启Nginx
$ sudo /etc/nginx/nginx-1.13.6/nginx -s reload
如果无法启动,很有可能是apache目前占用了端口80
可以查看Nginx的运行效果:
$ curl -I 127.0.0.1:80
Nginx配置web服务器
1.设置虚拟服务器
NGINX配置文件必须至少包含一个服务器指令来定义虚拟服务器
server {
listen 127.0.0.1:8080;
}
- 通配符是一个字符串,其开头,结尾或两者都包含星号(*); 星号匹配任何字符序列。
- NGINX将Perl语法用于正则表达式; 在它们之前使用波浪号(〜)
这里有一个完整的nginx虚拟机配置,这里配置两个虚拟机:
- 域名:vhost1.com 网站主目录:/data/www/vhost1
- 域名:vhost2.com 网站主目录:/data/www/vhost2
server {
listen 80;
server_name vhost1.com www.vhost1.com;
index index.html index.html;
root /data/www/vhost1;
access_log /var/log/vhost1.com.log;
}
server {
listen 80;
server_name vhost2.com www.vhost2.com;
index index.html index.html;
root /data/www/vhost2;
access_log /var/log/vhost2.com.log;
}
2.根据URL配置位置
Nginx可以根据请求的URL向不同的代理发送请求,这是用server
中的location
指令来定义的。
location
指令有两种类型的参数:前缀字符串(路径名)
和正则表达式
:
- 前缀字符串:下面的例子必须匹配以/some/path开头的URL
location /some/path/ { ... }
- 正则表达式:表达式前面是区分大小写匹配的符号
~
,或者是不区分大小写匹配的符号~*
location ~ \.html? { # 匹配任何包含.html的URL ... # \.用于匹配. ?匹配前面字符串零次或者一次 }
location
上下文可以包含如何解析请求的指令:提供静态文件,或者传递给代理服务器处理逻辑,就是上面第二个实例的情况:
server {
location /images/ { # 先走这个判断
root /data; # 去/data/images/.../...下面找文件
}
location / { # 所有不以/images开头的请求会走这一步
proxy_pass http://www.example.com;
}
}
3.重写URL请求
使用rewrite
指令在请求的时候修改URI,该指令有三个参数:
- 第一个(必须)是请求URI必须匹配的正则表达式
- 第二个(必须)是用于替换的URI
- 第三个(可选)是可以停止进一步重写指令的处理或者发送重定向的标志
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
当上下文中包含多个rewrite
指令,nginx会按照顺序依次执行指令,处理完一组rewrite指令后,会根据新的URI选择一个location上下文,直到结束。
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
这里的第一个参数是^(/download/.*)/media/(.*)\..*$
,
^
符号表示匹配输入字符串的开始位置.
表示除了换行符的任何单字符,*
表示匹配前面的表达式零次或者多次,所以使用(.*)
来匹配多任一字符。- 最后面的
$
会依次将前面括号内匹配的内容储存为变量$1
$2
…
第二个参数是$1/mp3/$2.mp3
,获取前面储存的变量加进来
第三个参数是中断处理重写的指令:
last
停止后面的重写指令,直接用该行重写后的URI匹配break
停止后面的重写指令,也不使用重写后的URI进行匹配redirect
直接使用重写后的URI重定向到新的URI
Nginx配置静态内容服务器
root
指令用于指定搜索文件的根目录
,nginx会将请求的URL附加到root指令指定的根目录后面:
server {
root /www/data;
location / {
index index.$geo.html index.html index.html;
# nginx会以顺序搜索文件,并返回找到的第一个文件
}
location /images/ { # 这里会在/www/data/images目录搜索
autoindex on; # 配置nginx返回自动生成的目录列表
}
location ~ \.(mp3|mp4) {
root /www/media; # 这里重新指定了根目录
}
}
通过index索引文件附加到基本URL后面会进行内部重定向:
假设URL是/path/ 并且/data/path里面没有index.html文件
location / {
root /data;
index index.html index.php; # 那么会索引index.php
# URL改写为/path/index.php,会进入下面的location
}
location ~ \.php {
fastcgi_pass localhost:8000;
...
}
Nginx反向代理
Nginx可以使用proxy_pass
指令将请求发送到指定的代理服务器:
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
这里代理服务器后面有URL/link/
,如果地址和URL一起指定,那么会替换location参数匹配请求URL的部分:
如果URL是/some/aaa/page.html
,那么会变成http://www.example.com/link/page.html
传递请求标头
- 当
proxy_host
的时候,如果不想改变请求头Host的值,就可以设置为:
proxy_set_header Host $http_host;
- 但是有时候客户端的请求头中没有这个头部,那么最好使用:
proxy_set_header Host $host;
这样的话,在请求包含host请求头的时候使用Host的值,要是没有这个请求头就设置为虚拟主机的主域名。 - 如果某个请求头的值为空,那么这个请求头将不会传递给后端服务器:
proxy_set_header Accept-Encoding "";
Nginx实例:
1.需要外部访问下载文件
server {
lsiten 80;
location /Content{
alias /opt/download/content;
autoindex on;
try_files $uri $url/ =404;
}
}
这里遇到/Content
的URL就改写成alias
指定的地址,URL后面的路径不变
如果使用root
来指定位置,那么就会把/Content
接在root指定的位置后面
2.使用代理同时可以下载文件和访问自己的服务
假如后端服务起在了8080,然后导致文件下载的URL里面的端口号也是8080,那我们需要过滤掉下载文件的URL,使之不走后端服务。可是会发现nginx如果监听8080,服务就无法启动在同一端口8080。所以我们可以使用nginx监听80端口,然后加上非下载文件的请求传递给后端APP:
location /{
proxy_set_header Host $http_host;
proxy_pass http:127.0.0.1:8080;
}
这样的话,访问后端app使用80端口,nginx会处理请求的。
Nginx 主要应用场景
反向代理、负载均衡、HTTP服务器、正向代理
1.反向代理
反向代理是指以代理服务器的身份来接受客户端的请求,然后转发给网络内部的服务器上,并且将从服务器上得到的结果返回给客户端。所以就是真是的应用服务器不能被外部直接访问,所以需要一台代理服务器:
server {
listen 80;
server_name localhost;
client_max_body_size 1024M;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host:$server_port;
}
}
这样我们访问localhost的时候其实是访问了localhost:8080
2.负载均衡
upstream test {
server localhost:8080;
server localhost:8081;
}
server {
listen 81;
server_name localhost;
client_max_body_size 1024M;
location / {
proxy_pass http://test;
proxy_set_header Host $host:$server_port;
}
}
这里配置了相当于两台服务器,如果其中有一台服务器宕机了也没事,因为nginx不会跳转到这个服务器上。如果想设置权重,让某些服务器被访问的次数更多,可以这样:
upstream test {
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}
如果服务器启用类似session保存了当前登录信息,想让一个访客固定访问一个后端服务器,可以这样使用iphash
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}