从零开始学Nginx

Nginx简介

Nginx 是一款高性能的 HTTP 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。

Nginx版本:

  • Mainline version : Mainline是Nginx目前主力在做的版本,可以说是开发版
  • Stable version :最新稳定版,生产环境上建议使用的版本
  • Legacy versions :遗留的老版本的稳定版

Nginx 的应用场景

  • HTTP 服务器:Nginx 是一个 HTTP 服务可以独立提供 HTTP 服务。可以做网页静态服务器。
  • 虚拟主机:可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
  • 反向代理,负载均衡:当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用 Nginx 做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

基于 Docker 部署 Nginx

编写docker-compose.yml

数据卷只会创建目录不会创建文件所以预先创建好./conf/nginx.conf文件和./html目录,不然会报错显示挂载异常.

version: '3.1'
services:
  nginx:
    restart: always
    image: nginx
    container_name: nginx
    ports:
      - 80:80
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
      - ./html:/usr/share/nginx/html
      - ./cert:/etc/nginx/cert
      - ./logs:/var/log/nginx

Nginx命令

nginx -h #帮助信息
start nginx #启动nginx 
nginx -s stop #快速关闭Nginx,可能不保存相关信息,并迅速终止web服务。
nginx -s quit #平稳关闭Nginx,保存相关信息,有安排的结束web服务。
nginx -s reload #因改变了Nginx相关配置,需要重新加载配置而重载。
nginx -s reopen #重新打开日志文件。
nginx -c filename #为Nginx指定一个配置文件,来代替缺省的。
nginx -t #不运行,而仅仅测试配置文件。nginx将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件。
nginx -v #显示nginx的版本。
nginx -V #显示nginx的版本,编译器版本和配置参数

Nginx配置

nginx.conf 配置文件的结构

# 全局配置
# ...
events {
    # ...
}
http {
    # ...
    upstream {
        # ...
    }
    server{
        # ...
    }
    # ...
    server{
        # ...
    }
}

注意: 每个 server 就是一个虚拟主机

全局配置

user nobody; #置用户或者组,默认为nobody 
worker_processes 1; #允许生成的进程数,默认为1,通常设置成和 CPU 的数量相等
error_1og 1ogs/error.1og;#制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别依次为:debug info notice warn error crit alert emerg
error_log logs/error.log notice;
pid 1ogs/nginx.pid;#指定nginx进程运行文件存放地址

events 配置

accept_mutex on;#默认为on .当一个新连接到达时,如果激活了accept_mutex,那么多个Worker将以串行方式来处理,其中有一个Worker会被唤醒,其他的Worker继续保持休眠状态;如果没有激活accept_mutex,那么所有的Worker都会被唤醒,不过只有一个Worker能获取新连接,其它的Worker会重新进入休眠状态,这就是「惊群问题」,但当访问量大时不激活反而更快。
multi_accept off;#设置一个进程是否同时接受多个网络连接,默认为off
use epo11;#事件驱动模型,select po11 kqueue epo11 resigl /dev/po11 eventport 
worker_connections 1024;#最大连接数,默认为1024(早期是512)  

事件驱动模型:

  • epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能

http 配置

#配置nginx支持哪些文件扩展名与文件类型映射表。在conf/mime.types查看支持哪些类型
include mime.types;
#默认文件类型(流)类型,支持很多文件、图片、js/css等
default_type application/octet-stream;

#自定义日志格式
1og_format myFormat 'Sremote_addr-Sremote_user[Stime_local]Srequest Sstatus Sbody_bytes_sent Shttp_referer httpuser_agent Shttp-x_forwarded_for';
#日志配置 access_log off; 取消服务日志  
access_log 1og/access.1og myFormat;

#优化参数允许sendfile方式传输文件,开启高校效传输模式,对于普通应用,必须设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的 uptime.
sendfile on;
#防止网络阻塞
tcp-nopush on;
#长连接超时时间(单位秒)
keepalive_timeout 65;
#每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
sendfile_max_chunk 100k;  
# 设定请求缓冲
client_header_buffer_size 2k;

#开启gzip压缩,对响应数据进行在线实时压缩,减少数据传输量。
gzip on;

#静态压缩,文件必须预先完成gzip压缩
gzip_static on;
gzip_http_version 1.0;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
gzip_vary on;


#对IE6浏览器的数据不进行 GZIP 压缩。
gzip_disable "msie6";
#设定通过nginx上传文件的大小
client_max_body_size 8m;
#错误页
error_page   500 502 503 504  /50x.html;

upstream 配置

    # 定义反向代理,负载均衡设备的 Ip及设备状态 
    upstream mysvr {
        # ip_hash;  # 使用源Ip哈希模式(默认轮询),可以解决session问题
        server 127.0.0.1:9090 down;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:6060;
        server 127.0.0.1:7070 backup;
    }

upstream设置每个设备的状态:

  • down:表示当前的 server 暂时不参与负载
  • weight:默认为 1 weight 越大,负载的权重就越大。
  • max_fails:允许请求失败的次数默认为 1 当超过最大次数时,返回 proxy_next_upstream 模块定义的错误
  • fail_timeout:max_fails 次失败后,暂停的时间。
  • backup:其它所有的非 backup 机器 down 或者忙的时候,请求 backup 机器。所以这台机器压力会最轻

server配置

keepalive_requests 120; #单连接请求上限次数。
listen 80; #监听端口
server_name  127.0.0.1;   #监听地址,这里可配置 IP 也可配置域名,支持多域名配置,支持泛域名解析(*.a.com),支持对于域名的正则匹配

# 将ssl证书上传到nginx数据卷暴露出来的cert目录中
# listen可同时配置多个,使得http和https都可访问
listen 443 ssl;   #SSL协议访问端口号为443。此处如未添加ssl,可能会造成Nginx无法启动。
server_name localhost;  #将localhost修改为您证书绑定的域名,例如:www.example.com。
ssl_certificate cert/domain name.pem;   #将domain name.pem替换成您证书的文件名。
ssl_certificate_key cert/domain name.key;   #将domain name.key替换成您证书的密钥文件名。
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  #使用此加密套件。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   #使用该协议进行配置。
ssl_prefer_server_ciphers on;  
rewrite ^(.*)$ https://$host$1 permanent;   #将所有http请求通过rewrite重定向到https。
root /xxhtml; # 根目录
index index.html index.htm;

location /{
           #root path;  #根目录
           #index vv.html;  #设置默认页
           proxy_pass  http://mysvr;  #请求转向 upstream mysvr 定义的服务器列表
           deny 127.0.0.1;  #拒绝的ip
           allow 172.18.5.54; #允许的ip 
         }

location匹配规则及顺序:

  • = 表示精确匹配。只有请求的url路径与后面的字符串完全相等时,才会命中。
  • ^~ 前缀匹配,表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找。
  • ~ 表示该规则是使用正则定义的,区分大小写。
  • ~* 表示该规则是使用正则定义的,不区分大小写。
  • /uri 字符串匹配,匹配符合以后,还要继续往下搜索
    只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  • / 通用匹配, 如果没有其它匹配,任何请求都会匹配到

nginx自定义请求头

http://www.51niux.com/?id=135

语法:    proxy_set_header field value;
默认值:    
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
上下文:    http, server, location
  proxy_set_header Host            $host:$server_port;
  proxy_set_header X-Real-IP       $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Nginx 虚拟主机

虚拟主机是一种特殊的软硬件技术,它可以将网络上的一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供 www 服务,这样就可以实现一台主机对外提供多个 web 服务,每个虚拟主机之间是独立的,互不影响的。

通过 Nginx 可以实现虚拟主机的配置,Nginx 支持三种类型的虚拟主机配置

  • 基于 IP 的虚拟主机
  • 基于域名的虚拟主机
  • 基于端口的虚拟主机

操作流程

  • 创建目录及文件,在 /usr/local/docker/nginx/html 目录下创建 html80 和 html8080 两个目录,并分别创建两个 index.html 文件
  • 配置虚拟主机,创建并修改 /usr/local/docker/nginx/conf 目录下的 nginx.conf
  • 修改docker-compose.yml文件暴露8080端口,up启动
# 启动进程,通常设置成和 CPU 的数量相等
worker_processes  1;
events {
    # epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式
    # 但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能
    use epoll;
    # 单个后台 worker process 进程的最大并发链接数
    worker_connections  1024;
}
http {
    # 设定 mime 类型,类型由 mime.type 文件定义
    include       mime.types;
    default_type  application/octet-stream;
    # sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    # 必须设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的 uptime.
    sendfile        on;
    # 连接超时时间
    keepalive_timeout  65;
    # 设定请求缓冲
    client_header_buffer_size 2k;
    # 配置虚拟主机,根据server_name和listen的不同实习虚拟主机功能
    server {
    # 监听端口
        listen       80;
    # 虚拟主机名称,这里可配置 IP 也可配置域名
        server_name  192.168.141.121;
    # 所有的请求都以 / 开始,所有的请求都可以匹配此 location
        location / {
        # 使用 root 指令指定虚拟主机目录即网页存放目录
        # 比如访问 http://ip/index.html 将找到 /usr/local/docker/nginx/html/html80/index.html
        # 比如访问 http://ip/item/index.html 将找到 /usr/local/docker/nginx/html/html80/item/index.html
            root   /usr/share/nginx/html/html80;
        # 指定欢迎页面,按从左到右顺序查找
            index  index.html index.htm;
        }
    }
    # 配置虚拟主机 
    server {
        listen       8080;
        server_name  192.168.141.121;
        location / {
            root   /usr/share/nginx/html/html8080;
            index  index.html index.htm;
        }
    }
}

Nginx 反向代理

代理服务器

代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬盘中,再发送给客户机。

代理服务器功能

  • 提高访问速度: 由于目标主机返回的数据会存放在代理服务器的硬盘中,因此下一次客户再访问相同的站点数据时,会直接从代理服务器的硬盘中读取,起到了缓存的作用,尤其对于热门站点能明显提高请求速度。
  • 防火墙作用: 由于所有的客户机请求都必须通过代理服务器访问远程站点,因此可在代理服务器上设限,过滤某些不安全信息。
  • 通过代理服务器访问不能访问的目标站点: 互联网上有许多开放的代理服务器,客户机在访问受限时,可通过不受限的代理服务器访问目标站点,通俗说,我们使用的翻墙浏览器就是利用了代理服务器,虽然不能出国,但也可直接访问外网。

正向代理

正向代理,架设在客户机与目标主机之间,只用于代理内部网络对 Internet 的连接请求,客户机必须指定代理服务器,并将本来要直接发送到 Web 服务器上的 HTTP 请求发送到代理服务器中。

反向代理

反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。

使用 Nginx 反向代理 Tomcat

启动 Tomcat 容器

启动两个 Tomcat 容器,映射端口为 8081 和 8082,docker-compose.yml 如下:

version: '3.1'
services:
  tomcat1:
    image: tomcat
    container_name: tomcat1
    ports:
      - 8081:8080
  tomcat2:
    image: tomcat
    container_name: tomcat2
    ports:
      - 8082:8080

配置 Nginx 反向代理

修改 /usr/local/docker/nginx/conf 目录下的 nginx.conf 配置文件:

#Nginx用户及组:用户 组。window下不指定
user  nginx;
worker_processes  1;
events {
    use epoll;
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    # 配置一个代理即 tomcat1 服务器
      #如果nginx和tomcat在同一个局域网,可以使用 服务名:8080 进行代理通信,并且tomcat可以不用暴露端口
    upstream tomcatServer1 {
        server 192.168.141.121:8081;
    }
    # 配置一个代理即 tomcat2 服务器
    upstream tomcatServer2 {
        server 192.168.141.121:8082;
    }
    # 配置一个虚拟主机
    server {
        listen 80;
        server_name service1.funtl.com;
        location / {
                # 域名 service1.funtl.com 的请求全部转发到 tomcatServer1 即 tomcat1 服务上
                proxy_pass http://tomcatServer1;
                # 欢迎页面,按照从左到右的顺序查找页面
                index index.jsp index.html index.htm;
        }
    }
    server {
        listen 80;
        server_name service2.funtl.com;
        location / {
            # 域名 service2.funtl.com 的请求全部转发到 tomcatServer2 即 tomcat2 服务上
            proxy_pass http://tomcatServer2;
            index index.jsp index.html index.htm;
        }
    }
}

注意: 新版 Nginx的upstream配置中的名称不可以有下划线("_"),否则会报 400 错误

反向代理中url的传递问题

proxy_pass url中的url只是host:port地址,不包含任何资源路径哪怕一个/,nginx会将完整路径将直接传递给代理服务器.

// 访问:   /                               后端:   /
// 访问:   /api/xx                         后端:   /api/xx
// 访问:   /api/xx?aa                      后端:   /api/xx?aa
location / {
    proxy_pass http://node:8080;
}

// 访问:   /api/                           后端:   /api/
// 访问:   /api/xx                         后端:   /api/xx
// 访问:   /api/xx?aa                      后端:   /api/xx?aa
// 访问:   /api-xx?aa                      后端:
location /api/ {
    proxy_pass http://node:8080;
}

proxy_pass url中的url包含了资源路径,nginx会将location 匹配后的链接传递给代理服务器

// 访问:   /                               后端:   /
// 访问:   /api/xx                         后端:   /api/xx
// 访问:   /api/xx?aa                      后端:   /api/xx?aa
location / {
    proxy_pass http://node:8080/;
}

// 访问:   /api/                           后端:   /
// 访问:   /api/xx                         后端:   /xx
// 访问:   /api/xx?aa                      后端:   /xx?aa
// 访问:   /api-xx?aa                      未匹配
location /api/ {
    proxy_pass http://node:8080/;
}

// 访问:   /api                            后端:   /
// 访问:   /api/                           后端:   //
// 访问:   /api/xx                         后端:   //xx
// 访问:   /api/xx?aa                      后端:   //xx?aa
// 访问:   /api-xx?aa                      后端:   /-xx?aa
location /api {
    proxy_pass http://node:8080/;
}

// 访问:   /api/                           后端:   /v1
// 访问:   /api/xx                         后端:   /v1xx
// 访问:   /api/xx?aa                      后端:   /v1xx
// 访问:   /api-xx?aa                      未匹配
location /api/ {
    proxy_pass http://node:8080/v1;
}

// 访问:   /api/                           后端:   /v1/
// 访问:   /api/xx                         后端:   /v1/xx
// 访问:   /api/xx?aa                      后端:   /v1/xx
// 访问:   /api-xx?aa                      未匹配
location /api/ {
    proxy_pass http://node:8080/v1/;
}

当 location 以正则形式匹配时,proxy_pass 不能包含路径.

反向代理解决跨域问题

当服务器无法设置 header 或提供 callback 时我们就可以采用 Nginx 反向代理的方式解决跨域问题。

user  nginx;
worker_processes  1;

events {
    worker_connections  1024;
}

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

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen 80;
        server_name upload.myshop.com;
        add_header 'Access-Control-Allow-Origin'  '*';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        location / {
            proxy_pass  http://192.168.0.104:8888;
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin  *;
                add_header Access-Control-Allow-Headers X-Requested-With;
                add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,PATCH,OPTIONS;
                # 解决假请求问题,如果是简单请求则没有这个问题,但这里是上传文件,首次请求为 OPTIONS 方式,实际请求为 POST 方式
                # Provisional headers are shown.
                # Request header field Cache-Control is not allowed by Access-Control-Allow-Headers in preflight response.
                add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range;
                return 200;
            }
        }
    }
}

Nginx 负载均衡

修改 /usr/local/docker/nginx/conf 目录下的 nginx.conf 配置文件:

user  nginx;
worker_processes  1;
events {
    use epoll;
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    # 定义负载均衡设备的 Ip及设备状态 
    upstream myServer {
        server 127.0.0.1:9090 down;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:6060;
        server 127.0.0.1:7070 backup;
    }
    server {
        listen 80;
        server_name nginx.funtl.com;
        location / {
            #代理
            proxy_pass http://myapp1;
            index index.jsp index.html index.htm;
        }
    }
}

upstream设置每个设备的状态:

  • down:表示当前的 server 暂时不参与负载
  • weight:默认为 1 weight 越大,负载的权重就越大。
  • max_fails:允许请求失败的次数默认为 1 当超过最大次数时,返回 proxy_next_upstream 模块定义的错误
  • fail_timeout:max_fails 次失败后,暂停的时间。
  • backup:其它所有的非 backup 机器 down 或者忙的时候,请求 backup 机器。所以这台机器压力会最轻
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值