Nginx学习笔记 - 《Nginx核心知识100讲》

初识Nginx

概述

  • Nginx适用于哪些场景:

    • 静态资源服务
      - 通过本地文件系统提供服务
      • 反向代理服务
        • Nginx的强大性能
        • 缓存
        • 负载均衡
      • Api服务
        • OpenResty
          在这里插入图片描述
  • Nginx出现的历史背景(Nginx为什么出现?)

    • 低效的Apeche:一个连接对应一个进程,处理完一个请求才会处理下一个,无法支持“高并发”。

    • 新增服务器绝大多数都是Nginx
      在这里插入图片描述

  • Nginx的优点

    • 高并发 & 高性能
      • 主流服务器32核64G可达数千万并发连接(RPS, Requests Per Second)
      • 处理静态资源请求可达一百万RPS
    • 可拓展性好
    • 高可靠性
      • 可持续运行数年
    • 热部署
      • 不停止服务,升级Nginx
    • BSD许可证
      • 可定制Nginx且商用
  • Nginx的四个组成部分:

    • Nginx二进制可执行文件(由各模块源码编译出的一个文件)
    • Nginx.conf配置文件(控制Nginx的行为)
    • access.log访问日志(记录每一天http请求)
    • error.log错误日志(定位问题)

安装Nginx

  • 安装方式:

    • apt/yum
    • 编译安装:方便安装第三方模块
  • 选择哪一个Nginx发行版:

    • 开源版即可
    • Mainline:有新功能
    • Stable:稳定版

编译安装

wget http://nginx.org/download/nginx-1.14.2.tar.gz
tar -xzf nginx-1.14.2.tar.gz
cd nginx-1.14.2  # 进入源码目录
  • 源码目录结构

    • auto目录:编译、lib库、操作系统判断

    • CHANGS文件:功能改动和BUGFIX文档

    • conf文件:conf配置示例

    • configure脚本:执行编译前的动作

    • contrib目录:vim不支持nginx语法

      # 配置vim,支持nginx语法
      cp -r contrib/vim/* ~/.vim/
      
    • html目录:html示例

      • 50x.html:500错误示例
      • index.html:首页示例
    • man文件:帮助文件

    • src目录:源代码

  • configure支持的参数:./configure --help | more
    在这里插入图片描述

# 安装在/opt/nginx目录,可能报错,安装对应依赖即可
./configure --prefix=/opt/nginx
# 编译
make
# 首次安装使用
make install
  • 升级Nginx时,不能执行make install:

    • objs/nginx复制进安装目录中
    • 安装动态模块的中间文件也在objs目录
  • 安装完成后,/opt/nginx的结构

    • sbin:nginx程序
    • conf:nginx配置,均复制于/nginx/nginx-1.14.2
    • logs:日志
  • 可将nginx目录配置进环境变量,方便使用:export PATH="$PATH:/opt/nginx/sbin"

Nginx配置文件的通用语法

  • 配置文件由指令与指令块构成

  • 每条指令以;分号结尾,指令与参数间以空格符号分割。

  • 指令块以{}大括号将多条指令组织在一起

  • include语句允许多个配置文件以提升可维护性

  • 使用#符号添加注释,提高可读性

  • 使用$符号使用变量

  • 部分指令的参数支持正则表达式

  • 配置参数:时间单位与空间单位
    在这里插入图片描述
    在这里插入图片描述

  • http配置的指令块

在这里插入图片描述

Nginx命令行

  • 格式:nginx -s commandnginx -s reload
  • 帮助:-? -h
  • 使用指定配置指令:-g
  • 指定运行目录:-p
  • 发送信号:-s
    • 立刻停止服务:stop
    • 优雅地停止服务:quit
    • 优雅地重载配置文件:reload
    • 重新开始记录日志文件:reopen,常用于日志切割
  • 测试配置文件是否有语法错误:-t -T
  • 打印nginx的版本信息、编译信息等:-v -V
热部署
# 替换nginx二进制执行文件
cp /home/jay/lxj/nginx-1.14.2/objs/nginx /opt/nginx/sbin/nginx -f
# 发送信号给nginx,13426为nginx master的PID,结果如示例
kill -USR2 13426
# 优雅地关闭老nginx进程
kill -WINCH 13426
# 老master不会关闭,可reload再次 拉起新worker(我没有实现)
  • 示例:新老nginx同时运行,但老nginx不再监听对应端口80/443
    在这里插入图片描述

Nginx搭建静态资源服务器

  • 在nginx.conf中配置
    • alias类似root,但更常用。
    • alias:url路径与指定目录路径相同。
# 静态文件服务器
server {
    listen 8080;
    server_name geek.lxj.pub;
    # charset koi8-r;
    access_log logs/geek.access.log main;

    location / {
            alias   dlib/;  # 根目录与dlib/后相同
            autoindex on;
            set $limit_rate 1k;
            index  index.htm;
    }
    #error_page 404         /404.html;
}
  • 即可在浏览器中获取dlib目录下对应路基的文件:http://10.211.55.8:8080/MyGit/django_course/Day01/01-animate.html
    在这里插入图片描述

  • autoindex模块:把文件目录结构分享给访问者。

location / {
	autoindex on;
}

在这里插入图片描述

  • set $limit_rate 1k;:限制Nginx对浏览器的响应速度,避免个别大文件占满带宽。示例为 每秒1K。

  • 配置access日志:

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

用Nginx搭建一个具备缓存功能的反向代理服务

  • 把静态服务器作为“上游服务”
  • 通过Nginx反向代理
    • 方便通过“负载均衡”增加“上游”服务器,来提升处理性能。
    • 也方便在上游服务出现问题时,Nginx把请求转交给正常服务器。
# 静态服务(上游服务)
server {
        listen 127.0.0.1:8080;  # 只能本机访问,上游服务不对外提供服务
        server_name geek.lxj.pub;
        # charset koi8-r;
        access_log logs/geek.access.log  main;

        location / {
                alias   dlib/;
                autoindex on;
                set $limit_rate 1k;
                #index  index.htm;
        }
        #error_page 404         /404.html;
}

# 反向代理
include vhost/*.conf;
# 上游服务
upstream local {
    server 127.0.0.1:8080;
}
server {
    server_name geektime.lxj.pub;  # 需要配置本地的/etc/hosts文件
    listen 80;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;  # 帮上游服务器 添加访问者的真实地址
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_cache my_cache;  # 再配置好缓存后,打开缓存功能
            proxy_cache_key $host$uri$is_args$args;  # 配置key:用户+资源等=整体key
            proxy_cache_valid 200 304 302 1d;  # 这些不处理
            proxy_pass http://local;  # 默认监听80
    }
}
配置Nginx缓存
  • proxy_cache_path /tmp/nginxcache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off:指定路径,配置10MB的缓存。
注意
  • Nginx反向代理和上游服务应该配置为两台Nginx。
  • 关闭上游服务后,开启缓存的反向代理Nginx还可以返回缓存的上游服务的内容。

用免费SSL证书实现一个HTTPS站点(没实现)

  • 背景:编译安装nginx-2
# 安装工具
sudo apt install python-certbot-nginx
# 生成证书
certbot --nginx --nginx-server-root=/opt/nginx-2/conf/ -d geektime.lxj-2.pub

Nginx架构基础

  • Nginx的请求处理流程
    在这里插入图片描述

  • Nginx进程结构
    在这里插入图片描述

  • 多进程结构:多线程会共用地址空间,发生地址越界时 会导致多进程挂掉,不利于Nginx的“健壮性”。

  • 进程间通讯使用“共享内存”。

  • Worker进程:每个W进程与一个CPU绑定,方便使用每个CPU缓存来减少“缓存失效”的命中率。

使用信号管理Nginx的父子进程

Nginx进程管理:信号

  • Master进程:
    • 监控worker进程:CHLD
    • 管理worker进程
    • 接收信号:
      • TERM, INT:立刻停止Nginx进程
      • QUIT:优雅停止,不立刻断开用户的连接
      • HUP:重载配置文件
      • USR1:重新配置日志文件,用于切割日志
      • USR2:kill USR2 NGINX_PID,用于热部署
      • WINCH:kill WINCH NGINX_PID,用于热部署
  • Worker进程
    • 接收信号:不直接对worker进程发送信号,一般通过master进程进行管理
      • TERM, INT
      • QUIT
      • USR1
      • WINCH
  • nginx命令行:本质是发送信号
    • reload:HUP
    • reopen:USR1
    • stop:TERM
    • quit:QUIT

reload重载配置文件的真相

  • reload的流程:

    • 想master进程发送HUP信号(同reload命令)
    • master进程校验配置语法是否正确
    • master进程打开新的监听端口
    • master进程用新配置启动新的worker子进程
    • master进程向老worker子进程发送QUIT信号
    • 老worker进程关闭监听句柄,处理完当前连接后结束进程
  • 不停机载入新配置
    在这里插入图片描述

热升级的完整流程

  • 流程:

    • 将就Nginx文件替换成新Nginx文件(注意备份)
    • 想master进程发送USR2信号
    • master进程修改PID文件名,加后缀.oldbin
    • master进程用心Nginx文件启动新master进程
    • 向老master进程发送QUIT信号,关闭老master进程
    • 回滚:向老master发送HUP,向新master发送QUIT
  • 不停机更新Nginx二进制文件
    在这里插入图片描述

优雅地关闭worker进程

  • 针对HTTP请求:因为Nginx无法识别TCP、WeSocket连接一共需要多少报文才能完成该连接。
  • 使用方法:配置定时器(woker_shutdown_timeout),其内部过程如下
    • 关闭句柄
    • 关闭空闲连接
    • 在循环中等待全部连接关闭
    • 退出进程

网络收发与Nginx事件的对应关系

  • 网络传输:以一次GET请求为例
    在这里插入图片描述

  • TCP流与报文:每个“小报文”(MSS)即为一次“网络事件”
    在这里插入图片描述

  • TCP协议与非阻塞接口:左读右写
    在这里插入图片描述

29-41 (# TODO)

HTTP模块

冲突的配置指令以谁为准?

  • 指令的合并

    • 值指令(存储配置项的值):可以合并,如root, access_log, gzip
    • 动作类指定(指定行为):不可合并,
      • 如rewrite, proxy_pass
      • 生效阶段server_rewrite阶段, rewrite阶段,content阶段
  • 储存值的指令继承规则:向上覆盖

    • 子配置不存在时,直接使用父配置块;子配置存在时,直接覆盖父配置块。
server {
	listen	8080;  # 只能出现在server的context中
	root /home/geek/nginx/html;
	access_log logs/geek.access.log main;
	location /test {
		root /home/geek/nginx/test;  # 覆盖父配置
		access_log logs/access.test.log main;  # 覆盖父配置
	}
	location /dlib {
		alias dlib/;
	}
	location / {  # 使用父配置块的root
	}
}
  • HTTP模块合并配置的实现:
    • 指令在哪个块下生效?
    • 指令允许出现在哪些块下?
    • 在server块内生效,从http向server合并指令:char *(*merge_srv_conf)(ngx_conf_t*cf, void *prev, void *conf);
    • 配置缓存在内存:char *(*merge_loc_conf)(ngx_conf_t*cf, void *prev, void *conf);

Listen指令的用法

  • 语法
    在这里插入图片描述

  • 示例

# 监听套接字
listen unix:/var/run/nginx.sock;
# 监听ip地址和端口
listen 127.0.0.1:8000;
listen 8000;
listen *:8000;  # 所有ip
listen localhost:8000 bind;
listen [::]:8000 ipv6only=on;  # 只ipv6
listen [::1];  #???

Nginx中的正则表达式

  • 元字符与重复
    在这里插入图片描述

  • 示例
    在这里插入图片描述

  • 测试工作:使用pcretest

如何找到处理请求的Server指令块

  • server_name指令
    • 指令后可以跟多个域名,第1个是主域名
Syntax  server_name_in_redirect on | off;
Default  server_name_in_redirect off;
Context  http, server, location
  • *泛域名:仅支持在最前面或者最后

    • server_name *.taohui.tech
  • 正则表达式:加~前缀

    • server_name www.taohui.tech ~^www\d+\.taohui\.tech$;
  • Server匹配顺序:

    • 精确匹配
    • *在前的泛域名
    • *在后的泛域名
    • 按文件中的顺序匹配正则表达式域名
    • default server:第1个,listen指定default
  • 示例

    • 配置
    server {
            server_name primary.lxj.tech second.lxk.tech;
            server_name_in_redirect on;
    
            return 302 /redirect;
    }
    
    • 开启后,指向主域名
      在这里插入图片描述

详解HTTP请求的11阶段

  • 流程图:(右图为 阶段对应指令块)
    在这里插入图片描述

11个阶段的顺序处理

  • 示意图

在这里插入图片描述

postread阶段:realip模块获取真实ip地址

  • 如何拿到真实的用户IP地址?

    • TCP连接四元组(src ip, src port, dst ip, dst port)
    • HTTP头部X-Forwarded-For用于传递IP:可多个
    • HTTP头部X-Real-IP用于传递用户IP:只有一个
    • 网络中存在许多反向代理(前提)
  • 示例场景
    在这里插入图片描述

  • 拿到真实用户IP后如何使用?

    • 基于变量
    • 如binary_remote, remote_addr这样的变量,其值就为真实的IP。这样做链接限制(limit_conn模块)才有意义。

realip模块

  • realip模块

    • 默认不会编译进Nginx:通过--with-http_realip_module启用功能
    • 功能:修改客户端地址
    • 指令:set_real_ip_from, real_ip_header, real_ip_recursive
    • 变量:realip_remote_addr, realip_remote_port
  • realip模块的指令
    在这里插入图片描述

  • 示例配置

server {
        server_name realip.lxj.tech;

        error_log logs/myerror.log debug;
        set_real_ip_from 10.211.55.8;
        #real_ip_header X-Real-IP;
        real_ip_recursive off;
        #real_ip_recursive on;
        real_ip_header  X-Forwarded-For;

        location /{
                return 200 "Client real ip: $remote_add\n";
        }

}

反向代理与负载均衡

  • 负载均衡示例图
    在这里插入图片描述

  • Nginx在AKF扩展立方体上的应用
    在这里插入图片描述

  • 反向代理
    在这里插入图片描述

  • 反向代理与缓存
    在这里插入图片描述

负载均衡策略:round-robin

  • 指定上游服务地址的upstream与server指令

    • 指定一组上游服务器地址,其中地址可以是域名、IP或者unix socket地址。可以在域名或者IP地址后加端口,如果不加端口,那么默认使用80端口。
    • 通用参数:
      • backup:指定当前server为备份服务,仅当非备份server不可以时,请求才会转发到该server
      • down:标识某服务已经下线,不提供服务
        在这里插入图片描述
  • 加权Round-Robin负载均衡算法

    • 功能:在加权轮询的方式访问server指令指定的上游服务。集成在Nginx的upstream框架中。
    • 指令:
      • weight:服务访问的权重,默认是1。
      • max_conns:server的最大并发连接数,仅作用于但worker今次。默认是0,表示没有限制。
      • 在fail_timeout时间段内,最大的失败次数。当达到最大失败时,会在fail_timeout秒内这台server不允许再次被选择。
      • fail_timeout:单位为秒,默认值为10秒。具有2个功能:指定一段时间内,最大失败次数max_fails。达到max_fails后,该server不能访问的时间。
  • 对上游服务使用keepalive长连接

    • 功能:通过复用连接,降低nginx与上游服务器建立、关闭连接的消耗,提升吞吐量的同时降低时延。

    • 模块:ngx_http_upstream_keepalive_module,默认编译进nginx。

    • 对上游连接的http头部设定:

      proxy_http_version 1.1;
      proxy_set_header Connetion "";
      
    • upstream_keepalive的指令
      在这里插入图片描述

  • 指定上游服务域名解析的resolver指令
    在这里插入图片描述

负载均衡哈希算法:ip_hash与hash模块

  • 基于客户端IP地址的Hash算法实现负载均衡:upstream_ip_hash模块
    • 功能:以客户端的IP地址作为hash算法的关键字,映射到特定的上游服务器中。
      • IPV4地址使用前3个字节作为关键字,对IPV6则使用完整地址。
      • 可以基于realip模块修改用于执行算法的IP地址。
    • 模块:ngx_http_upstream_ip_hash_module。
    • 语法:ip_hash, 用于upstream块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值